From 87b857960f0b48a7443394bb3d9065a0f5384c1a Mon Sep 17 00:00:00 2001 From: Antoine Hoarau <703240+ahoarau@users.noreply.github.com> Date: Thu, 11 Dec 2025 12:11:08 +0100 Subject: [PATCH 1/3] =?UTF-8?q?cmake:=C2=A0Refactor=20project=20to=20use?= =?UTF-8?q?=20jrl=20cmake=20modules=20v2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gersemirc | 4 +- .gitattributes | 2 + .github/workflows/ci-arch.yml | 28 - .github/workflows/ci-linux-osx-win-conda.yml | 221 - .github/workflows/ci-linux-ros.yml | 46 - .github/workflows/ci-linux.yml | 93 + .github/workflows/{nix.yml => ci-nix.yml} | 11 +- .github/workflows/ci-pixi.yml | 121 + .github/workflows/ci-ros.yml | 69 + .github/workflows/conda/environment.yml | 21 - .github/workflows/gh-pages.yml | 68 +- .gitignore | 19 +- .gitmodules | 9 - .pre-commit-config.yaml | 8 +- CHANGELOG.md | 1 + CMakeLists.txt | 549 +- README.md | 17 + benchmark/CMakeLists.txt | 40 +- bindings/CMakeLists.txt | 3 - bindings/python/CMakeLists.txt | 412 +- bindings/python/external/nanobind | 1 - bindings/python/proxsuite/__init__.py | 6 + cmake-external/FindMatio.cmake | 38 - cmake-external/FindSphinx.cmake | 14 - cmake-external/compiler_warnings.cmake | 91 - cmake-external/doctest.cmake | 178 - cmake-external/doctestAddTests.cmake | 91 - cmake-external/extra_local_settings.cmake | 58 - cmake-external/sanitizers.cmake | 76 - cmake-external/static_analyzers.cmake | 33 - cmake-module | 1 - cmake/get-jrl-cmakemodules.cmake | 49 + development/build.md | 2 - development/release.md | 28 + development/scripts/pixi/activation.bat | 6 + development/scripts/pixi/activation.sh | 18 + doc/2-ProxQP_api.md | 4 +- doc/5-installation.md | 23 +- doc/CMakeLists.txt | 73 + doc/Doxyfile.extra.in | 59 - doc/images/proxsuite-logo-transparent.png | Bin 0 -> 67400 bytes doc/images/proxsuite-logo.png | Bin 67400 -> 48201 bytes examples/CMakeLists.txt | 11 +- examples/cpp/CMakeLists.txt | 49 +- examples/julia/CMakeLists.txt | 26 +- examples/julia/overview-simple.jl | 3 + examples/python/CMakeLists.txt | 53 +- .../python/estimate_nonconvex_eigenvalue.py | 4 +- external/cereal | 1 - flake.lock | 475 +- flake.nix | 111 +- include/proxsuite/helpers/tl-optional.hpp | 2471 ---- include/proxsuite/linalg/sparse/factorize.hpp | 2 +- include/proxsuite/linalg/veg/tuple.hpp | 7 - .../linalg/veg/type_traits/constructible.hpp | 2 +- .../proxsuite/proxqp/dense/backward_data.hpp | 1 - include/proxsuite/proxqp/dense/solver.hpp | 2 +- include/proxsuite/proxqp/sparse/workspace.hpp | 6 +- .../proxqp/utils/random_qp_problems.hpp | 46 +- .../proxsuite/proxqp/utils/uint128_msvc.hpp | 234 + package.xml | 11 +- pixi.lock | 11190 ++++++++++++++++ pixi.toml | 302 + pyproject.toml | 7 +- test/CMakeLists.txt | 120 +- test/cpp/CMakeLists.txt | 96 + test/{src => cpp}/cvxpy.cpp | 28 +- test/{src => cpp}/dense_backward.cpp | 18 +- test/{src => cpp}/dense_maros_meszaros.cpp | 6 +- test/{src => cpp}/dense_qp_eq.cpp | 42 +- test/{src => cpp}/dense_qp_solve.cpp | 60 +- test/{src => cpp}/dense_qp_with_eq_and_in.cpp | 43 +- test/{src => cpp}/dense_qp_wrapper.cpp | 1214 +- .../{src => cpp}/dense_ruiz_equilibration.cpp | 12 +- test/{src => cpp}/dense_unconstrained_qp.cpp | 28 +- test/{include => cpp}/maros_meszaros.hpp | 0 test/{src => cpp}/parallel_qp_solve.cpp | 10 +- test/{src => cpp}/serialization.cpp | 17 +- test/{src => cpp}/sparse_factorization.cpp | 2 +- test/{src => cpp}/sparse_maros_meszaros.cpp | 6 +- test/{src => cpp}/sparse_qp.cpp | 2 +- test/{src => cpp}/sparse_qp_solve.cpp | 61 +- test/{src => cpp}/sparse_qp_wrapper.cpp | 913 +- .../sparse_ruiz_equilibration.cpp | 2 +- test/cpp/uint128.cpp | 322 + test/{src => cpp}/util_f32.cpp | 2 +- test/{include => cpp}/util_f32.hpp | 1 + test/{src => cpp}/util_f64.cpp | 0 test/{include => cpp}/util_f64.hpp | 0 test/cpp/utils.hpp | 4 + test/doctest/doctest.cpp | 3 - test/doctest/doctest.hpp | 8694 ------------ test/include/cnpy.hpp | 317 - test/include/utils.hpp | 4 - .../packaging/cmake-components/CMakeLists.txt | 7 + test/packaging/cmake/CMakeLists.txt | 5 +- test/packaging/external/CMakeLists.txt | 17 - test/packaging/fetchcontent/CMakeLists.txt | 16 + test/python/CMakeLists.txt | 27 + test/{src/cvxpy.py => python/test_cvxpy.py} | 0 .../test_dense_qp_solve.py} | 0 .../test_dense_qp_wrapper.py} | 7 +- .../test_parallel_qp_solve.py} | 0 .../test_serialization.py} | 0 .../test_sparse_qp_solve.py} | 0 .../test_sparse_qp_wrapper.py} | 9 +- test/src/backward.cpp | 5 - test/src/cnpy.cpp | 350 - 108 files changed, 15098 insertions(+), 14977 deletions(-) create mode 100644 .gitattributes delete mode 100644 .github/workflows/ci-arch.yml delete mode 100644 .github/workflows/ci-linux-osx-win-conda.yml delete mode 100644 .github/workflows/ci-linux-ros.yml create mode 100644 .github/workflows/ci-linux.yml rename .github/workflows/{nix.yml => ci-nix.yml} (74%) create mode 100644 .github/workflows/ci-pixi.yml create mode 100644 .github/workflows/ci-ros.yml delete mode 100644 .github/workflows/conda/environment.yml delete mode 100644 .gitmodules delete mode 100644 bindings/CMakeLists.txt delete mode 160000 bindings/python/external/nanobind delete mode 100644 cmake-external/FindMatio.cmake delete mode 100644 cmake-external/FindSphinx.cmake delete mode 100644 cmake-external/compiler_warnings.cmake delete mode 100644 cmake-external/doctest.cmake delete mode 100644 cmake-external/doctestAddTests.cmake delete mode 100644 cmake-external/extra_local_settings.cmake delete mode 100644 cmake-external/sanitizers.cmake delete mode 100644 cmake-external/static_analyzers.cmake delete mode 160000 cmake-module create mode 100644 cmake/get-jrl-cmakemodules.cmake create mode 100644 development/release.md create mode 100644 development/scripts/pixi/activation.bat create mode 100644 development/scripts/pixi/activation.sh create mode 100644 doc/CMakeLists.txt delete mode 100644 doc/Doxyfile.extra.in create mode 100644 doc/images/proxsuite-logo-transparent.png delete mode 160000 external/cereal delete mode 100644 include/proxsuite/helpers/tl-optional.hpp create mode 100644 include/proxsuite/proxqp/utils/uint128_msvc.hpp create mode 100644 pixi.lock create mode 100644 pixi.toml create mode 100644 test/cpp/CMakeLists.txt rename test/{src => cpp}/cvxpy.cpp (86%) rename test/{src => cpp}/dense_backward.cpp (92%) rename test/{src => cpp}/dense_maros_meszaros.cpp (98%) rename test/{src => cpp}/dense_qp_eq.cpp (87%) rename test/{src => cpp}/dense_qp_solve.cpp (91%) rename test/{src => cpp}/dense_qp_with_eq_and_in.cpp (89%) rename test/{src => cpp}/dense_qp_wrapper.cpp (89%) rename test/{src => cpp}/dense_ruiz_equilibration.cpp (84%) rename test/{src => cpp}/dense_unconstrained_qp.cpp (92%) rename test/{include => cpp}/maros_meszaros.hpp (100%) rename test/{src => cpp}/parallel_qp_solve.cpp (96%) rename test/{src => cpp}/serialization.cpp (89%) rename test/{src => cpp}/sparse_factorization.cpp (99%) rename test/{src => cpp}/sparse_maros_meszaros.cpp (98%) rename test/{src => cpp}/sparse_qp.cpp (99%) rename test/{src => cpp}/sparse_qp_solve.cpp (93%) rename test/{src => cpp}/sparse_qp_wrapper.cpp (90%) rename test/{src => cpp}/sparse_ruiz_equilibration.cpp (99%) create mode 100644 test/cpp/uint128.cpp rename test/{src => cpp}/util_f32.cpp (97%) rename test/{include => cpp}/util_f32.hpp (99%) rename test/{src => cpp}/util_f64.cpp (100%) rename test/{include => cpp}/util_f64.hpp (100%) create mode 100644 test/cpp/utils.hpp delete mode 100644 test/doctest/doctest.cpp delete mode 100644 test/doctest/doctest.hpp delete mode 100644 test/include/cnpy.hpp delete mode 100644 test/include/utils.hpp create mode 100644 test/packaging/cmake-components/CMakeLists.txt delete mode 100644 test/packaging/external/CMakeLists.txt create mode 100644 test/packaging/fetchcontent/CMakeLists.txt create mode 100644 test/python/CMakeLists.txt rename test/{src/cvxpy.py => python/test_cvxpy.py} (100%) rename test/{src/dense_qp_solve.py => python/test_dense_qp_solve.py} (100%) rename test/{src/dense_qp_wrapper.py => python/test_dense_qp_wrapper.py} (99%) rename test/{src/parallel_qp_solve.py => python/test_parallel_qp_solve.py} (100%) rename test/{src/serialization.py => python/test_serialization.py} (100%) rename test/{src/sparse_qp_solve.py => python/test_sparse_qp_solve.py} (100%) rename test/{src/sparse_qp_wrapper.py => python/test_sparse_qp_wrapper.py} (99%) delete mode 100644 test/src/backward.cpp delete mode 100644 test/src/cnpy.cpp diff --git a/.gersemirc b/.gersemirc index c682c6bb5..b67911cf9 100644 --- a/.gersemirc +++ b/.gersemirc @@ -1,4 +1,4 @@ -definitions: [./CMakeLists.txt,./cmake-module,./cmake-external,./bindings,./include] -line_length: 80 +definitions: [./CMakeLists.txt, ./test] +line_length: 100 indent: 2 warn_about_unknown_commands: false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..997504b46 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# SCM syntax highlighting & preventing 3-way merges +pixi.lock merge=binary linguist-language=YAML linguist-generated=true -diff diff --git a/.github/workflows/ci-arch.yml b/.github/workflows/ci-arch.yml deleted file mode 100644 index 1a28ba5ee..000000000 --- a/.github/workflows/ci-arch.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: CI - ArchLinux - -on: - push: - branches: devel - pull_request: - paths-ignore: - - CHANGELOG.md - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build-with-arch: - runs-on: "ubuntu-latest" - container: - image: archlinux/archlinux:base-devel - steps: - - run: pacman -Syu --noconfirm cmake eigen git libmatio python-scipy simde - - - uses: actions/checkout@v7 - with: - submodules: recursive - - - run: cmake -B build -S . -DBUILD_PYTHON_INTERFACE=ON - - run: cmake --build build - - run: cmake --build build -t test diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml deleted file mode 100644 index 1f6d6eced..000000000 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ /dev/null @@ -1,221 +0,0 @@ -name: CI - Linux/OSX/Windows - Conda - -on: - push: - branches: devel - pull_request: - paths-ignore: - - CHANGELOG.md - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build-with-conda: - name: '[conda:${{ matrix.os }}:${{ matrix.build_type }}:c++${{ matrix.cxx_std }}]' - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - build_type: [Release, Debug] - name: [ubuntu-latest, macos-latest, windows-2022-clang-cl, windows-2022, macos-15-intel] - cxx_std: [17, 20] - continue_on_error: [false] - - include: - - name: ubuntu-latest - os: ubuntu-latest - - name: macos-latest - os: macos-latest - - name: macos-15-intel - os: macos-15-intel - - name: windows-2022-clang-cl - os: windows-2022 - compiler: clang-cl - - name: windows-2022 - os: windows-2022 - compiler: cl - - name: macos-latest - os: macos-latest - build_type: Debug - cxx_std: 17 - continue_on_error: true - - name: macos-latest - os: macos-latest - build_type: Debug - cxx_std: 20 - continue_on_error: true - - exclude: - - name: macos-latest - build_type: Debug - cxx_std: 17 - continue_on_error: false - - name: macos-latest - build_type: Debug - cxx_std: 20 - continue_on_error: false - - steps: - - uses: actions/checkout@v7 - with: - submodules: recursive - - - uses: conda-incubator/setup-miniconda@v4 - with: - activate-environment: proxsuite - environment-file: .github/workflows/conda/environment.yml - auto-activate-base: false - auto-update-conda: true - - - name: Install dependencies [Conda/Windows-2022] - if: contains(matrix.os, 'windows-2022') - shell: bash -l {0} - run: | - # Use VS2022 on Windows-2022 - conda install vs2022_win-64 - - - name: Install julia [Linux] - if: contains(matrix.os, 'ubuntu') - shell: bash -l {0} - run: | - conda install julia - - - name: Activate ccache [Conda] - uses: hendrikmuhs/ccache-action@v1.2 - with: - key: ${{ matrix.os }}-${{ matrix.type }}-${{ matrix.cxx_std }} - max-size: 1G - - - name: Print environment [Conda] - shell: bash -l {0} - run: | - conda info - conda list - env - - - name: Configure [Conda/Linux&macOS] - if: contains(matrix.os, 'macos-') || contains(matrix.os, 'ubuntu') - shell: bash -l {0} - run: | - echo $(whereis ccache) - echo $(which ccache) - git submodule update --init - mkdir build - cd build - cmake .. -GNinja -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_EXECUTABLE=$(which python3) -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON -DTEST_JULIA_INTERFACE:BOOL=OFF -DOpenMP_ROOT=$CONDA_PREFIX - - - name: Configure [Conda/macOS-debug/CheckMalloc] - if: contains(matrix.os, 'macos-latest') && contains(matrix.build_type, 'Debug') - shell: bash -l {0} - run: | - echo $(whereis ccache) - echo $(which ccache) - cd build - cmake .. -GNinja -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCHECK_RUNTIME_MALLOC:BOOL=ON -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_EXECUTABLE=$(which python3) -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON -DTEST_JULIA_INTERFACE:BOOL=OFF -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DOpenMP_ROOT=$CONDA_PREFIX - - - name: Configure [Conda/Windows] - if: contains(matrix.os, 'windows-') - # It's better to use CMD to have all VS variables setup - shell: cmd /C CALL {0} - run: | - git submodule update --init - mkdir build - cd build - set CC=${{ matrix.compiler }} - set CXX=${{ matrix.compiler }} - cmake .. -GNinja -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=%CONDA_PREFIX%/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=%CONDA_PREFIX%/Lib/site-packages -DPYTHON_EXECUTABLE=%CONDA_PREFIX%/python.exe -DOpenMP_ROOT=%CONDA_PREFIX% -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON - - - name: Build [Conda/Linux&macOS] - if: contains(matrix.os, 'macos-') || contains(matrix.os, 'ubuntu') - shell: bash -l {0} - run: | - cd build - cmake --build . --config ${{ matrix.build_type }} -v -j 1 - - - name: Build [Conda/Windows] - if: contains(matrix.os, 'windows-') - # It's better to use CMD to have all VS variables setup - shell: cmd /C CALL {0} - run: | - cd build - cmake --build . --config ${{ matrix.build_type }} -v -j 1 - - - name: Build documentation [Conda] - shell: bash -l {0} - run: | - cd build - cmake --build . --config ${{ matrix.build_type }} --target doc - - - name: Install [Conda] - shell: bash -l {0} - run: | - cd build - cmake --install . --config ${{ matrix.build_type }} - - - name: Test [Conda] - continue-on-error: ${{ matrix.continue_on_error }} - shell: bash -l {0} - run: | - find $CONDA_PREFIX -name proxsuite* - python -c "import proxsuite" - cd build - ctest --output-on-failure -C ${{ matrix.build_type }} - # - name: Test pkg-config [Conda] - # shell: bash -l {0} - # run: | - # cd build - # export PKG_CONFIG_PATH=$CONDA_PREFIX/lib/pkgconfig - # pkg-config --cflags proxsuite - # g++ -std=c++17 examples/cpp/overview-simple.cpp -o overview-simple $(pkg-config --cflags proxsuite) - # ./overview-simple - - - name: Test FetchContent packaging [Conda/Linux&macOS] - if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu') - shell: bash -l {0} - run: | - cd test/packaging/external - mkdir build && cd build - export PROXSUITE_GIT_REPOSITORY="file://"$GITHUB_WORKSPACE - export PROXSUITE_GIT_TAG="test-external-"$(git rev-parse --short HEAD) - git tag $PROXSUITE_GIT_TAG - cmake .. -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - cmake --build . --config ${{ matrix.build_type }} --target all - ./run-proxqp - - - name: Test CMake packaging [Conda/Linux&macOS] - if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu') - shell: bash -l {0} - run: | - cd test/packaging/cmake - mkdir build && cd build - cmake .. -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DPACKAGE_PREFIX_DIR=${CONDA_PREFIX} - cmake --build . --config ${{ matrix.build_type }} --target all - ./run-proxqp - - - name: Uninstall [Conda] - shell: bash -l {0} - run: | - cd build - cmake --build . --config ${{ matrix.build_type }} --target uninstall - - - name: Display ccache statistics [Conda] - shell: bash -l {0} - run: | - echo $(ccache -s) - - check: - if: always() - name: check-ci-linux-osx-win-conda - - needs: - - build-with-conda - - runs-on: Ubuntu-latest - steps: - - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 - with: - jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/ci-linux-ros.yml b/.github/workflows/ci-linux-ros.yml deleted file mode 100644 index babf87807..000000000 --- a/.github/workflows/ci-linux-ros.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: CI - Linux - ROS -on: - push: - branches: devel - pull_request: - paths-ignore: - - CHANGELOG.md - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - CI: - strategy: - fail-fast: false - matrix: - env: - - {ROS_DISTRO: humble} - - {ROS_DISTRO: jazzy} - - {ROS_DISTRO: kilted} - - {ROS_DISTRO: lyrical} - - {ROS_DISTRO: rolling} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7 - with: - submodules: recursive - # Run industrial_ci - - uses: 'ros-industrial/industrial_ci@master' - env: ${{ matrix.env }} - - - check: - if: always() - name: check-ci-linux-ros - - needs: - - CI - - runs-on: Ubuntu-latest - steps: - - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 - with: - jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml new file mode 100644 index 000000000..a8a22f593 --- /dev/null +++ b/.github/workflows/ci-linux.yml @@ -0,0 +1,93 @@ +name: CI - Linux + +on: + push: + branches: + - devel + pull_request: + paths-ignore: + - CHANGELOG.md + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ubuntu: + name: CI - Ubuntu ${{ matrix.ubuntu_version }} - ${{ matrix.build_type }} (APT) + runs-on: ubuntu-latest + container: + image: ubuntu:${{ matrix.ubuntu_version }} + strategy: + fail-fast: false + matrix: + ubuntu_version: ["22.04", "24.04"] + build_type: [Release, Debug] + env: + CCACHE_BASEDIR: ${{ github.workspace }} + CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_COMPRESS: true + CCACHE_COMPRESSLEVEL: 6 + CMAKE_C_COMPILER_LAUNCHER: ccache + CMAKE_CXX_COMPILER_LAUNCHER: ccache + DEBIAN_FRONTEND: noninteractive + steps: + - uses: actions/checkout@v6 + - name: Setup ccache + uses: actions/cache@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-ubuntu-${{ matrix.ubuntu_version }}-${{ matrix.build_type }}-${{ github.sha }} + restore-keys: ccache-ubuntu-${{ matrix.ubuntu_version }}-${{ matrix.build_type }}- + + - name: Update APT repositories + run: apt-get update + + - name: Install dependencies via APT + run: apt-get install -y git cmake g++ ninja-build ccache graphviz libmatio-dev doxygen catch2 libeigen3-dev python3-numpy python3-dev python3-scipy libcereal-dev libsimde-dev + + - name: Clear ccache stats + run: ccache --show-stats --zero-stats --verbose + + - name: CMake Configure + run: cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE=ON -DBUILD_TESTING=ON -DPROXSUITE_BUILD_EXAMPLES=ON -DBUILD_DOCUMENTATION=ON -DBUILD_BENCHMARK=ON + + - name: CMake Build + run: cmake --build build --verbose --parallel 2 + + - name: Show ccache stats + run: ccache --show-stats --verbose + + - name: CTest + run: ctest --test-dir build --output-on-failure + + - name: CMake Install + run: cmake --install build --prefix install + + archlinux: + name: CI - ArchLinux + runs-on: ubuntu-latest + container: + image: archlinux/archlinux:base-devel + steps: + - run: pacman -Syu --noconfirm cmake ninja catch2 git eigen cereal libmatio doxygen graphviz nanobind python-scipy simde + - uses: actions/checkout@v6 + - run: cmake -G Ninja -B build -S . -DBUILD_PYTHON_INTERFACE=ON -DBUILD_TESTING=ON -DPROXSUITE_BUILD_EXAMPLES=ON -DBUILD_DOCUMENTATION=ON -DBUILD_BENCHMARK=ON + - run: cmake --build build --verbose --parallel 2 + - run: ctest --test-dir build --output-on-failure + + check: + if: always() + name: check-linux + + needs: + - ubuntu + - archlinux + + runs-on: ubuntu-latest + + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/nix.yml b/.github/workflows/ci-nix.yml similarity index 74% rename from .github/workflows/nix.yml rename to .github/workflows/ci-nix.yml index 9b9ae2d24..bbc6403ea 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/ci-nix.yml @@ -1,4 +1,4 @@ -name: "CI - Nix" +name: CI - Nix on: push: @@ -13,8 +13,8 @@ jobs: runs-on: "${{ matrix.os }}" strategy: matrix: - os: ["ubuntu-24.04", "ubuntu-24.04-arm", "macos-15-intel", "macos-15"] - eigen: ["", "-eigen_5"] + os: ["ubuntu-24.04", "ubuntu-24.04-arm", "macos-15"] + extends: ["", "pkgs-eigen5"] steps: - uses: actions/checkout@v7 - uses: cachix/install-nix-action@v31 @@ -22,7 +22,8 @@ jobs: with: name: gepetto authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - run: nix build -L .#proxsuite${{ matrix.eigen }} + - run: nix flake check -L + - run: nix build -L ".#${{ matrix.extends }}" check: if: always() @@ -31,7 +32,7 @@ jobs: needs: - nix - runs-on: Ubuntu-latest + runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed diff --git a/.github/workflows/ci-pixi.yml b/.github/workflows/ci-pixi.yml new file mode 100644 index 000000000..bce3a21ac --- /dev/null +++ b/.github/workflows/ci-pixi.yml @@ -0,0 +1,121 @@ +name: CI - Pixi - Windows/Linux/macOS + +on: + push: + branches: + - devel + pull_request: + paths-ignore: + - CHANGELOG.md + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + pixi: + name: Pixi CI - ${{ matrix.os }} - ${{ matrix.build_type }} - C++${{ matrix.cxx_std }} + runs-on: ${{ matrix.os }} + env: + CCACHE_BASEDIR: ${{ github.workspace }} + CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_COMPRESS: true + CCACHE_COMPRESSLEVEL: 6 + # Since pixi will install a compiler, the compiler mtime will be changed. + # This can invalidate the cache (https://ccache.dev/manual/latest.html#config_compiler_check) + CCACHE_COMPILERCHECK: content + CMAKE_BUILD_TYPE: ${{ matrix.build_type }} + PROXSUITE_CXX_STANDARD: ${{ matrix.cxx_std }} + strategy: + fail-fast: false + matrix: + build_type: [Release, Debug] + cxx_std: [17, 20] + pixi_environment: [default] + os: [ubuntu-24.04, macos-15-intel, macos-26, windows-2025] + + steps: + - uses: actions/checkout@v6 + - uses: actions/cache@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-pixi-${{ matrix.pixi_environment }}-${{ matrix.os }}-${{ matrix.build_type }}-${{ matrix.cxx_std }}-${{ github.sha }} + restore-keys: ccache-pixi-${{ matrix.pixi_environment }}-${{ matrix.os }}-${{ matrix.build_type }}-${{ matrix.cxx_std }}- + + - name: Install Pixi + uses: prefix-dev/setup-pixi@v0.9.3 + with: + environments: ${{ matrix.pixi_environment }} + + - name: Configure + run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps configure --fresh --log-level=DEBUG + + - name: Build + run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps build --verbose --parallel 1 + + - name: Run C++ tests + if: ${{ !(startsWith(matrix.os, 'windows-') && matrix.build_type == 'Debug') }} + run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps test + + - name: Install + run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps install + + - name: Test Python import + run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps test-import-python + + - name: Uninstall + run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps uninstall + + - name: Run packaging tests + run: pixi run -e ${{ matrix.pixi_environment }} test-packaging + + # pixi-build: + # name: Pixi Build CI + # strategy: + # fail-fast: false + # matrix: + # os: [ubuntu-24.04, macos-15-intel, macos-26, windows-2025] + # runs-on: ${{ matrix.os }} + # steps: + # - uses: actions/checkout@v6 + + # - name: Install Pixi + # uses: prefix-dev/setup-pixi@v0.9.3 + # with: + # cache: false + # environments: test-pixi-build + + # - name: Run Pixi build test + # run: pixi run -e test-pixi-build test + + lint: + name: Pre-Commit Linting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Install Pixi + uses: prefix-dev/setup-pixi@v0.9.3 + with: + environments: lint + + - name: Run pre-commit checks + run: pixi run -e lint lint + + check: + if: always() + name: check-linux + + needs: + - lint + - pixi + # - pixi-build + + runs-on: ubuntu-latest + + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} + diff --git a/.github/workflows/ci-ros.yml b/.github/workflows/ci-ros.yml new file mode 100644 index 000000000..6e49a02ef --- /dev/null +++ b/.github/workflows/ci-ros.yml @@ -0,0 +1,69 @@ +name: CI - ROS - Linux +on: + push: + branches: + - devel + pull_request: + paths-ignore: + - CHANGELOG.md + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ros: + name: ROS ${{ matrix.ROS_DISTRO }} - ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # ROS2 Humble Hawksbill (May 2022 - May 2027) + - ROS_DISTRO: humble + os: Ubuntu 22.04 (Jammy) + + # ROS2 Jazzy Jalisco (May 2024 - May 2029) + - ROS_DISTRO: jazzy + os: Ubuntu 24.04 (Noble) + + # ROS2 Kilted Kayu (May 2025 - December 2026) + - ROS_DISTRO: kilted + os: Ubuntu 24.04 (Noble) + + # ROS2 Rolling Ridley + - ROS_DISTRO: rolling + os: Ubuntu 26.04 (Resolute) + + # ROS2 Lyrical Luth (May 2026 - May 2031) + - ROS_DISTRO: lyrical + os: Ubuntu 26.04 (Resolute) + env: + CCACHE_DIR: ${{ github.workspace }}/.ccache + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/cache@v6 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-ci-ros-${{ matrix.ROS_DISTRO }}-${{github.run_id}} + restore-keys: ccache-ci-ros-${{ matrix.ROS_DISTRO }}- + - uses: ros-industrial/industrial_ci@125164b9f1883cdf1858897a7146d1bebf2be5c6 + env: + CMAKE_ARGS: -DBUILD_WITH_VECTORIZATION_SUPPORT=ON -DPROXSUITE_BUILD_WITH_SERIALIZATION=ON -DBUILD_PYTHON_INTERFACE=ON -DBUILD_TESTING=ON -DPROXSUITE_BUILD_EXAMPLES=ON -DBUILD_BENCHMARK=ON + VERBOSE_OUTPUT: true + VERBOSE_TESTS: true + ROS_DISTRO: ${{ matrix.ROS_DISTRO }} + + check: + if: always() + name: check-ci-linux-ros + + needs: + - ros + + runs-on: ubuntu-latest + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/conda/environment.yml b/.github/workflows/conda/environment.yml deleted file mode 100644 index f4972dc5f..000000000 --- a/.github/workflows/conda/environment.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: proxsuite -channels: - - conda-forge - - nodefaults -dependencies: - - python-gil - - cmake - - compilers - - make - - pkg-config - - doxygen<1.18 - - ninja - - graphviz - - typing_extensions - - llvm-openmp - - clang - - eigen - - simde - - libmatio - - numpy - - scipy diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index eece799c9..bb403a9c2 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -1,63 +1,33 @@ -name: gh-pages +name: Github Pages Deployment on: release: types: - published jobs: - build: + build_doc: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - with: - submodules: recursive - - - uses: conda-incubator/setup-miniconda@v4 - with: - miniforge-version: latest - activate-environment: doc - channels: conda-forge - conda-remove-defaults: "true" - - - name: Dependencies - shell: bash -l {0} - run: | - # Compilation related dependencies - conda install cmake make pkg-config doxygen graphviz - # Main dependencies - conda install eigen - - - name: Print environment - shell: bash -l {0} - run: | - conda info - conda list - env - - - name: Configure - shell: bash -l {0} - run: | - git submodule update --init - mkdir build - cd build - cmake .. -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON_INTERFACE:BOOL=OFF -DPYTHON_EXECUTABLE=$(which python3) -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON -DBUILD_TESTING:BOOL=OFF -DBUILD_WITH_VECTORIZATION_SUPPORT:BOOL=OFF + - name: Install Pixi + uses: prefix-dev/setup-pixi@v0.9.3 - name: Build documentation - shell: bash -l {0} - run: | - cd build - cmake --build . --config Release --target doc + run: pixi run build-documentation + + - name: Install documentation + run: pixi run install-documentation - name: Archive artifacts uses: actions/upload-artifact@v7 with: name: site - path: build/doc/doxygen-html + path: build/doc/html deploy: - runs-on: ubuntu-22.04 - needs: [build] + runs-on: ubuntu-latest + needs: [build_doc] steps: - name: Download artifacts uses: actions/download-artifact@v8 @@ -68,3 +38,19 @@ jobs: uses: JamesIves/github-pages-deploy-action@v4.9.0 with: folder: site + + check: + if: always() + name: check-linux + + needs: + - build_doc + - deploy + + runs-on: ubuntu-latest + + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 60cfca1ca..2c5ed9077 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,19 @@ -build/* +build*/ +install*/ +dist/ +out/ +.pytest_cache/ +.cache/ +*.conda +.pixi/ +.vs/ +__pycache__/ Xcode* *.pyc -.vscode* \ No newline at end of file +*~ +*.egg-info +*.whl +.ruff_cache +.DS_Store +compile_commands.json +cmake-profiling.json diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 2867bf33b..000000000 --- a/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "bindings/python/external/nanobind"] - path = bindings/python/external/nanobind - url = https://github.com/wjakob/nanobind -[submodule "cmake-module"] - path = cmake-module - url = https://github.com/jrl-umi3218/jrl-cmakemodules.git -[submodule "external/cereal"] - path = external/cereal - url = https://github.com/USCiLab/cereal.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 22e05d25d..4ce0b8f77 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,20 +4,20 @@ ci: autoupdate_schedule: quarterly submodules: true repos: -- repo: https://github.com/BlankSpruce/gersemi - rev: 0.26.1 +- repo: https://github.com/BlankSpruce/gersemi-pre-commit + rev: 0.28.0 hooks: - id: gersemi - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.15.20 hooks: - - id: ruff + - id: ruff-check args: - --fix - --exit-non-zero-on-fix - id: ruff-format - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v22.1.5 + rev: v22.1.8 hooks: - id: clang-format args: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f5a26f19..ba0019485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Upgraded nanobind dependency version (submodule) to v2.9.2 ([#418](https://github.com/Simple-Robotics/proxsuite/pull/418)) - Better dynamic module handling ([#419](https://github.com/Simple-Robotics/proxsuite/pull/419)) - Fix `SyntaxError` on importing `proxsuite.torch.qplayer` caused by invalid escape sequences in the `QPFunction` docstring ([#458](https://github.com/Simple-Robotics/proxsuite/pull/461)) +- Switch to [JRL CMake modules v2](https://github.com/jrl-umi3218/jrl-cmakemodules/pull/798) ([#28](https://github.com/Simple-Robotics/nanoeigenpy/pull/28)) ### Fixed - Correction of the status update for `PROXQP_SOLVED_CLOSEST_PRIMAL_FEASIBLE` ([#432](https://github.com/Simple-Robotics/proxsuite/pull/432)) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30f00c497..4148bb2df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,263 +1,382 @@ -# -# Copyright (c) 2022-2023 INRIA -# +# Copyright (c) 2022-2026 Inria cmake_minimum_required(VERSION 3.22) -if(DEFINED PROJECT_NAME AND NOT PROJECT_WORKSPACE) - set(PROXSUITE_AS_SUBPROJECT ON) +project( + proxsuite + VERSION 0.7.2 + DESCRIPTION "The Advanced Proximal Optimization Toolbox" + HOMEPAGE_URL "https://github.com/Simple-Robotics/proxsuite" +) + +include(cmake/get-jrl-cmakemodules.cmake) + +jrl_configure_defaults() + +# Requires macOS >=10.14 SDK (fixes build issues on macos-15-intel) +# ref: https://github.com/wjakob/nanobind_example/blob/master/pyproject.toml#L43 +set( + CMAKE_OSX_DEPLOYMENT_TARGET + "10.14" + CACHE STRING + "Minimum macOS version supported by proxsuite" + FORCE +) + +set(PROXSUITE_CXX_STANDARD 17 CACHE STRING "C++ standard to be used by proxsuite") +if(PROXSUITE_CXX_STANDARD LESS 17) + message( + FATAL_ERROR + "[proxsuite] PROXSUITE_CXX_STANDARD must be at least 17. + Current value: ${PROXSUITE_CXX_STANDARD}" + ) +elseif(NOT PROXSUITE_CXX_STANDARD) + message( + DEBUG + "[proxsuite] PROXSUITE_CXX_STANDARD passed in the cmd line, but set to nothing. + Defaulting to C++17." + ) + set(PROXSUITE_CXX_STANDARD 17) endif() +message(STATUS "[proxsuite] PROXSUITE_CXX_STANDARD set to '${PROXSUITE_CXX_STANDARD}'") + +jrl_option(PROXSUITE_EXPORT_PACKAGE "Generate the CMake export files" ${PROJECT_IS_TOP_LEVEL}) +jrl_option(BUILD_TESTING "Build the tests" OFF) +jrl_option(PROXSUITE_BUILD_EXAMPLES "Build the examples" OFF) +jrl_option(BUILD_BENCHMARK "Build the benchmarks" OFF) +jrl_option(BUILD_DOCUMENTATION "Build the documentation" OFF) +jrl_option(PROXSUITE_BUILD_MAROS_MESZAROS_TESTS "Build the Maros-Meszaros tests, needs matio library" OFF) +jrl_option(PROXSUITE_ENABLE_WARNINGS_AS_ERRORS "Treat all warnings as errors" OFF) +jrl_option(BUILD_PYTHON_INTERFACE "Build the Python bindings" ON) +jrl_option(INSTALL_DOCUMENTATION "Install the documentation" OFF) +jrl_option(INITIALIZE_EIGEN_WITH_NAN "Initialize Eigen objects with NAN values" OFF) +jrl_option(CHECK_RUNTIME_MALLOC "Check if some memory allocations are performed at runtime" OFF) +jrl_option(BUILD_WITH_VECTORIZATION_SUPPORT "Build the library with the support of modern SIMD instructions" OFF) +jrl_option(BUILD_BINDINGS_WITH_AVX2_SUPPORT "Build the bindings with AVX2 support" ON CONDITION "BUILD_WITH_VECTORIZATION_SUPPORT" FALLBACK OFF) +jrl_option(BUILD_BINDINGS_WITH_AVX512_SUPPORT "Build the bindings with AVX512 support" ON CONDITION "BUILD_WITH_VECTORIZATION_SUPPORT" FALLBACK OFF) +jrl_option(TEST_JULIA_INTERFACE "Run the julia examples as unittest" OFF) +jrl_option(BUILD_WITH_OPENMP_SUPPORT "Build the library with the OpenMP support" OFF) +jrl_option(LINK_PYTHON_INTERFACE_TO_OPENMP "Link OpenMP to the Python interface" ON CONDITION "BUILD_WITH_OPENMP_SUPPORT" FALLBACK OFF) +jrl_option(PROXSUITE_BUILD_WITH_SERIALIZATION "Build with serialization support" ON) +jrl_option(GENERATE_PYTHON_STUBS "Generate Python stubs" OFF) +jrl_option(PROXSUITE_DOXYGEN_USE_MATHJAX "Avoid latex at build time" OFF) -set(PROJECT_NAME proxsuite) -set(PROJECT_DESCRIPTION "The Advanced Proximal Optimization Toolbox") -set(PROJECT_URL "http://github.com/Simple-Robotics/proxsuite") -set(PROJECT_CUSTOM_HEADER_EXTENSION "hpp") -set(PROJECT_USE_CMAKE_EXPORT TRUE) -set(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE) -# To enable jrl-cmakemodules compatibility with workspace we must define the two -# following lines -set(PROJECT_AUTO_RUN_FINALIZE FALSE) -set(PROJECT_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) - -# Check if the submodule cmake have been initialized -set(JRL_CMAKE_MODULES "${CMAKE_CURRENT_LIST_DIR}/cmake-module") -if(EXISTS "${JRL_CMAKE_MODULES}/base.cmake") - message(STATUS "JRL cmakemodules found in 'cmake/' git submodule") -else() - find_package(jrl-cmakemodules QUIET CONFIG) - if(jrl-cmakemodules_FOUND) - get_property( - JRL_CMAKE_MODULES - TARGET jrl-cmakemodules::jrl-cmakemodules - PROPERTY INTERFACE_INCLUDE_DIRECTORIES +# Serialization is required to build the python bindings +if(BUILD_PYTHON_INTERFACE AND NOT PROXSUITE_BUILD_WITH_SERIALIZATION) + message( + FATAL_ERROR + "[proxsuite] PROXSUITE_BUILD_WITH_SERIALIZATION must be ON to build the Python bindings." + ) +endif() + +############################################################ + +# Eigen3 +jrl_find_package(Eigen3 CONFIG REQUIRED EXPECTED_TARGETS Eigen3::Eigen) + +# Catch2 +# NOTE: We have to keep the FetchContent support because: +# - pixi does not have debug symbols for Catch2 on Windows. +# - Ubuntu 22.04 LTS ships Catch2 v2 which is incompatible with our tests. +if(BUILD_TESTING) + if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug") + set(Catch2_USE_FETCHCONTENT ON) + endif() + + if(NOT Catch2_USE_FETCHCONTENT) + jrl_find_package(Catch2 3.0 CONFIG QUIET) + if(Catch2_FOUND) + include(Catch) + else() + message( + WARNING + "[proxsuite] Catch2 version >= 3.0 is required for testing. + Falling back to FetchContent to get Catch2 v3.12.0" + ) + set(Catch2_USE_FETCHCONTENT ON) + endif() + endif() + + if(Catch2_USE_FETCHCONTENT) + include(FetchContent) + FetchContent_Declare( + catch2 + URL https://github.com/catchorg/Catch2/archive/refs/tags/v3.12.0.zip + URL_HASH MD5=f04aa334408d47e37aac534e34d1c861 + EXCLUDE_FROM_ALL ) - message(STATUS "JRL cmakemodules found on system at ${JRL_CMAKE_MODULES}") - elseif(${CMAKE_VERSION} VERSION_LESS "3.14.0") + FetchContent_MakeAvailable(catch2) + include(${catch2_SOURCE_DIR}/extras/Catch.cmake) + endif() +endif() + +# nanobind (Python bindings) +# NOTE: We have to keep the FetchContent support because: +# - Ubuntu 24.04 ships an incompatible 1.9.2 version of nanobind via apt-get. +# - Ubuntu 22.04 does not ship nanobind at all via apt-get. +if(BUILD_PYTHON_INTERFACE) + jrl_find_python(3.10 REQUIRED COMPONENTS Interpreter Development.Module) + jrl_find_nanobind(CONFIG QUIET) + if(NOT nanobind_FOUND) message( - FATAL_ERROR - "\nCan't find jrl-cmakemodules. Please either:\n" - " - use git submodule: 'git submodule update --init'\n" - " - or install https://github.com/jrl-umi3218/jrl-cmakemodules\n" - " - or upgrade your CMake version to >= 3.14 to allow automatic fetching\n" + WARNING + "[proxsuite] nanobind library not found. Falling back to FetchContent to get nanobind v2.11.0" ) - else() - message(STATUS "JRL cmakemodules not found. Let's fetch it.") include(FetchContent) FetchContent_Declare( - "jrl-cmakemodules" - GIT_REPOSITORY "https://github.com/jrl-umi3218/jrl-cmakemodules.git" + nanobind + GIT_REPOSITORY https://github.com/wjakob/nanobind.git + GIT_TAG v2.11.0 + EXCLUDE_FROM_ALL ) - FetchContent_MakeAvailable("jrl-cmakemodules") - FetchContent_GetProperties("jrl-cmakemodules" SOURCE_DIR JRL_CMAKE_MODULES) + FetchContent_MakeAvailable(nanobind) endif() endif() -# Disable -Werror on Unix for now. -set(CXX_DISABLE_WERROR True) -set(CMAKE_VERBOSE_MAKEFILE True) - -# Set CMake Policies -if(POLICY CMP0068) - cmake_policy(SET CMP0068 NEW) -endif(POLICY CMP0068) - -# ---------------------------------------------------- -# --- OPTIONS --------------------------------------- -# Need to be set before including base.cmake -# ---------------------------------------------------- -option(BUILD_DOCUMENTATION "Build the documentation." OFF) -option(BUILD_BENCHMARK "Build the benchmarks" OFF) -option(INSTALL_DOCUMENTATION "Install the documentation" OFF) -option(BUILD_PYTHON_INTERFACE "Build the Python bindings" OFF) -option(PROXSUITE_DOXYGEN_USE_MATHJAX "Avoid latex at build time" OFF) -set(DOXYGEN_USE_TEMPLATE_CSS YES) - -if(PROXSUITE_DOXYGEN_USE_MATHJAX) - set(DOXYGEN_USE_MATHJAX YES) +# cereal (Serialization) +if(PROXSUITE_BUILD_WITH_SERIALIZATION) + jrl_find_package(cereal CONFIG REQUIRED EXPECTED_TARGETS cereal::cereal) endif() -# install() DESTINATION paths are normalized (to remove in 3.31) (copied over -# from Pinocchio) -if(POLICY CMP0177) - cmake_policy(SET CMP0177 NEW) - set(CMAKE_POLICY_DEFAULT_CMP0177 NEW) -endif() -include(${JRL_CMAKE_MODULES}/base.cmake) -COMPUTE_PROJECT_ARGS(PROJECT_ARGS LANGUAGES CXX) -project(${PROJECT_NAME} ${PROJECT_ARGS}) - -include(${JRL_CMAKE_MODULES}/ide.cmake) -include(${JRL_CMAKE_MODULES}/apple.cmake) - -if(NOT ${CMAKE_VERSION} VERSION_GREATER "3.26.0" OR WIN32) - set( - CMAKE_MODULE_PATH - ${JRL_CMAKE_MODULES}/find-external/OpenMP - ${CMAKE_MODULE_PATH} - ) +# simde +if(BUILD_WITH_VECTORIZATION_SUPPORT) + jrl_find_package(simde REQUIRED EXPECTED_TARGETS simde::simde) endif() -include(${JRL_CMAKE_MODULES}/julia.cmake) -include(CMakeDependentOption) - -# If needed, set CMake policy for APPLE systems -APPLY_DEFAULT_APPLE_CONFIGURATION() -SET_DEFAULT_CMAKE_BUILD_TYPE(Release) - -option(INITIALIZE_EIGEN_WITH_NAN "Initialize Eigen objects with NAN values" OFF) -option( - CHECK_RUNTIME_MALLOC - "Check if some memory allocations are performed at runtime" - OFF -) -option(SUFFIX_SO_VERSION "Suffix library name with its version" ON) -option( - BUILD_WITH_VECTORIZATION_SUPPORT - "Build the library with the support of modern SIMD instructions." - ON -) -option( - BUILD_BINDINGS_WITH_AVX2_SUPPORT - "Build the bindings with AVX2 support." - ON -) -option( - BUILD_BINDINGS_WITH_AVX512_SUPPORT - "Build the bindings with AVX512 support." - ON -) -option(TEST_JULIA_INTERFACE "Run the julia examples as unittest" OFF) -option( - BUILD_WITH_OPENMP_SUPPORT - "Build the library with the OpenMP support" - OFF -) -cmake_dependent_option( - LINK_PYTHON_INTERFACE_TO_OPENMP - "Link OpenMP to the Python interface" - ON - BUILD_WITH_OPENMP_SUPPORT - OFF -) +# matio +if(BUILD_TESTING AND PROXSUITE_BUILD_MAROS_MESZAROS_TESTS) + jrl_find_package(matio REQUIRED) +endif() +# OpenMP if(BUILD_WITH_OPENMP_SUPPORT) - find_package(OpenMP REQUIRED) - separate_arguments(OpenMP_CXX_FLAGS UNIX_COMMAND "${OpenMP_CXX_FLAGS}") -endif(BUILD_WITH_OPENMP_SUPPORT) - -set( - CMAKE_MODULE_PATH - "${JRL_CMAKE_MODULES}/find-external/Julia" - ${CMAKE_MODULE_PATH} -) -set( - CMAKE_MODULE_PATH - "${CMAKE_CURRENT_LIST_DIR}/cmake-external" - ${CMAKE_MODULE_PATH} -) - -message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") -if(INITIALIZE_EIGEN_WITH_NAN) - add_definitions(-DEIGEN_INITIALIZE_MATRICES_BY_NAN) -endif(INITIALIZE_EIGEN_WITH_NAN) -if(CHECK_RUNTIME_MALLOC) - message(STATUS "Check if some memory allocations are performed at runtime.") - add_definitions(-DPROXSUITE_EIGEN_CHECK_MALLOC) - add_definitions(-DEIGEN_RUNTIME_NO_MALLOC) -endif(CHECK_RUNTIME_MALLOC) - -# set CXX standard -if(DEFINED CMAKE_CXX_STANDARD) - CHECK_MINIMAL_CXX_STANDARD(14 ENFORCE) -else() - set(CMAKE_CXX_STANDARD 17) + jrl_find_package(OpenMP REQUIRED EXPECTED_TARGETS OpenMP::OpenMP_CXX) endif() -message(STATUS "[Proxsuite] Using C++ standard: ${CMAKE_CXX_STANDARD}") -# Handle Windows context -if(MSVC) - # add_definitions(-D_USE_MATH_DEFINES) - add_definitions(-DNOMINMAX) +# Doxygen + Graphviz (dot) +if(BUILD_DOCUMENTATION) + jrl_find_package(Doxygen REQUIRED COMPONENTS dot) endif() -# Look for dependencies -ADD_PROJECT_DEPENDENCY(Eigen3 REQUIRED PKG_CONFIG_REQUIRES "eigen3 >= 3.0.5") - -set( - SIMDE_HINT_FAILURE - "Set BUILD_WITH_VECTORIZATION_SUPPORT=OFF or install Simde on your system.\n If Simde is already installed, ensure that the CMake variable CMAKE_MODULE_PATH correctly points toward the location of FindSimde.cmake file." -) -if(BUILD_WITH_VECTORIZATION_SUPPORT) - ADD_PROJECT_DEPENDENCY( - Simde - REQUIRED - FIND_EXTERNAL "Simde" - PKG_CONFIG_REQUIRES "simde" - ) -endif() - -# Build the main library -file(GLOB_RECURSE ${PROJECT_NAME}_HEADERS ${PROJECT_SOURCE_DIR}/include/*.hpp) +############################################################ add_library(proxsuite INTERFACE) -if(MSVC) - target_compile_options(proxsuite INTERFACE /permissive-) - target_compile_options(proxsuite INTERFACE $<$:/bigobj>) -endif(MSVC) -target_link_libraries(proxsuite PUBLIC INTERFACE Eigen3::Eigen) +add_library(proxsuite::proxsuite ALIAS proxsuite) +target_compile_features(proxsuite INTERFACE cxx_std_${PROXSUITE_CXX_STANDARD}) +jrl_target_enforce_msvc_conformance(proxsuite INTERFACE) + target_include_directories( proxsuite INTERFACE - "$" - "$" + $ + $ ) -target_include_directories( + +jrl_target_generate_config_header(proxsuite INTERFACE VERSION ${PROJECT_VERSION}) +jrl_target_generate_deprecated_header(proxsuite INTERFACE) +jrl_target_generate_warning_header(proxsuite INTERFACE) + +target_compile_definitions( proxsuite - INTERFACE "$" + INTERFACE + $<$:EIGEN_INITIALIZE_MATRICES_BY_NAN> + $<$:EIGEN_RUNTIME_NO_MALLOC> + $<$:PROXSUITE_EIGEN_CHECK_MALLOC> + $<$:PROXSUITE_PYTHON_INTERFACE_WITH_OPENMP> ) -set(EXPORTED_TARGETS_LIST proxsuite) -ADD_HEADER_GROUP(${PROJECT_NAME}_HEADERS) +target_link_libraries( + proxsuite + INTERFACE Eigen3::Eigen $<$:cereal::cereal> +) if(BUILD_WITH_VECTORIZATION_SUPPORT) add_library(proxsuite-vectorized INTERFACE) - target_link_libraries(proxsuite-vectorized PUBLIC INTERFACE proxsuite) - target_link_libraries(proxsuite-vectorized PUBLIC INTERFACE simde) + add_library(proxsuite::proxsuite-vectorized ALIAS proxsuite-vectorized) + target_link_libraries( + proxsuite-vectorized + INTERFACE proxsuite simde::simde $<$:cereal::cereal> + ) target_compile_definitions(proxsuite-vectorized INTERFACE PROXSUITE_VECTORIZE) - list(APPEND EXPORTED_TARGETS_LIST proxsuite-vectorized) endif() -if(BUILD_TESTING OR BUILD_PYTHON_INTERFACE) - # Download cereal for pything bindings and unittests - find_package(cereal QUIET CONFIG) - if(NOT cereal_FOUND) - set(cereal_dir ${PROJECT_SOURCE_DIR}/external/cereal) - set(cereal ${cereal_dir}/README.md) - find_package(Git REQUIRED) - if(NOT EXISTS ${cereal}) - execute_process( - COMMAND ${GIT_EXECUTABLE} submodule update --init ${cereal_dir} - WORKING_DIRECTORY ${cereal_dir} - COMMAND_ERROR_IS_FATAL ANY - ) - endif() +if(BUILD_WITH_OPENMP_SUPPORT) + add_library(proxsuite-parallel INTERFACE) + add_library(proxsuite::proxsuite-parallel ALIAS proxsuite-parallel) + target_link_libraries(proxsuite-parallel INTERFACE proxsuite OpenMP::OpenMP_CXX) + + if(BUILD_WITH_VECTORIZATION_SUPPORT) + add_library(proxsuite-vectorized-parallel INTERFACE) + add_library(proxsuite::proxsuite-vectorized-parallel ALIAS proxsuite-vectorized-parallel) + target_link_libraries( + proxsuite-vectorized-parallel + INTERFACE proxsuite-vectorized OpenMP::OpenMP_CXX + ) endif() endif() -install( - TARGETS ${EXPORTED_TARGETS_LIST} - EXPORT ${TARGETS_EXPORT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} -) +function(proxsuite_set_default_target_options target_name) + jrl_target_set_default_compile_options(${target_name} PRIVATE) + if(PROXSUITE_ENABLE_WARNINGS_AS_ERRORS) + jrl_target_treat_all_warnings_as_errors(${target_name} PRIVATE) + endif() +endfunction() + +if(BUILD_PYTHON_INTERFACE) + add_subdirectory(bindings/python) +endif() -add_subdirectory(bindings) -if(BUILD_TESTING AND NOT PROXSUITE_AS_SUBPROJECT) +if(BUILD_TESTING) + message(STATUS "[proxsuite] Building tests") + enable_testing() add_subdirectory(test) +endif() + +if(PROXSUITE_BUILD_EXAMPLES) + message(STATUS "[proxsuite] Building examples") add_subdirectory(examples) endif() -add_subdirectory(benchmark) +if(BUILD_BENCHMARK) + message(STATUS "[proxsuite] Building benchmarks") + add_subdirectory(benchmark) +endif() + +if(BUILD_DOCUMENTATION) + message(STATUS "[proxsuite] Building documentation") + add_subdirectory(doc) +endif() + +jrl_target_headers(proxsuite INTERFACE + HEADERS + include/proxsuite/helpers/common.hpp + include/proxsuite/helpers/instruction-set.hpp + include/proxsuite/helpers/optional.hpp + include/proxsuite/helpers/version.hpp + include/proxsuite/linalg/dense/core.hpp + include/proxsuite/linalg/dense/factorize.hpp + include/proxsuite/linalg/dense/ldlt.hpp + include/proxsuite/linalg/dense/modify.hpp + include/proxsuite/linalg/dense/solve.hpp + include/proxsuite/linalg/dense/update.hpp + include/proxsuite/linalg/sparse/core.hpp + include/proxsuite/linalg/sparse/factorize.hpp + include/proxsuite/linalg/sparse/rowmod.hpp + include/proxsuite/linalg/sparse/update.hpp + include/proxsuite/linalg/veg/internal/external/hedley.ext.hpp + include/proxsuite/linalg/veg/internal/external/unhedley.ext.hpp + include/proxsuite/linalg/veg/internal/assert_impl.hpp + include/proxsuite/linalg/veg/internal/collection_algo.hpp + include/proxsuite/linalg/veg/internal/dbg.hpp + include/proxsuite/linalg/veg/internal/delete_special_members.hpp + include/proxsuite/linalg/veg/internal/dyn_index.hpp + include/proxsuite/linalg/veg/internal/epilogue.hpp + include/proxsuite/linalg/veg/internal/fix_index.hpp + include/proxsuite/linalg/veg/internal/has_asan.hpp + include/proxsuite/linalg/veg/internal/integer_seq.hpp + include/proxsuite/linalg/veg/internal/macros.hpp + include/proxsuite/linalg/veg/internal/narrow.hpp + include/proxsuite/linalg/veg/internal/preprocessor.hpp + include/proxsuite/linalg/veg/internal/prologue.hpp + include/proxsuite/linalg/veg/internal/std.hpp + include/proxsuite/linalg/veg/internal/terminate.hpp + include/proxsuite/linalg/veg/internal/typedefs.hpp + include/proxsuite/linalg/veg/memory/address.hpp + include/proxsuite/linalg/veg/memory/alloc.hpp + include/proxsuite/linalg/veg/memory/dynamic_stack.hpp + include/proxsuite/linalg/veg/memory/placement.hpp + include/proxsuite/linalg/veg/memory/stack_alloc.hpp + include/proxsuite/linalg/veg/type_traits/alloc.hpp + include/proxsuite/linalg/veg/type_traits/assignable.hpp + include/proxsuite/linalg/veg/type_traits/constructible.hpp + include/proxsuite/linalg/veg/type_traits/core.hpp + include/proxsuite/linalg/veg/type_traits/invocable.hpp + include/proxsuite/linalg/veg/type_traits/primitives.hpp + include/proxsuite/linalg/veg/type_traits/tags.hpp + include/proxsuite/linalg/veg/util/assert.hpp + include/proxsuite/linalg/veg/util/dbg.hpp + include/proxsuite/linalg/veg/util/defer.hpp + include/proxsuite/linalg/veg/util/dynstack_alloc.hpp + include/proxsuite/linalg/veg/util/get.hpp + include/proxsuite/linalg/veg/util/index.hpp + include/proxsuite/linalg/veg/util/unreachable.hpp + include/proxsuite/linalg/veg/ref.hpp + include/proxsuite/linalg/veg/slice.hpp + include/proxsuite/linalg/veg/tuple.hpp + include/proxsuite/linalg/veg/vec.hpp + include/proxsuite/proxqp/dense/preconditioner/identity.hpp + include/proxsuite/proxqp/dense/preconditioner/ruiz.hpp + include/proxsuite/proxqp/dense/backward_data.hpp + include/proxsuite/proxqp/dense/compute_ECJ.hpp + include/proxsuite/proxqp/dense/dense.hpp + include/proxsuite/proxqp/dense/fwd.hpp + include/proxsuite/proxqp/dense/helpers.hpp + include/proxsuite/proxqp/dense/linesearch.hpp + include/proxsuite/proxqp/dense/model.hpp + include/proxsuite/proxqp/dense/solver.hpp + include/proxsuite/proxqp/dense/utils.hpp + include/proxsuite/proxqp/dense/views.hpp + include/proxsuite/proxqp/dense/workspace.hpp + include/proxsuite/proxqp/dense/wrapper.hpp + include/proxsuite/proxqp/parallel/omp.hpp + include/proxsuite/proxqp/parallel/qp_solve.hpp + include/proxsuite/proxqp/sparse/preconditioner/identity.hpp + include/proxsuite/proxqp/sparse/preconditioner/ruiz.hpp + include/proxsuite/proxqp/sparse/fwd.hpp + include/proxsuite/proxqp/sparse/helpers.hpp + include/proxsuite/proxqp/sparse/model.hpp + include/proxsuite/proxqp/sparse/solver.hpp + include/proxsuite/proxqp/sparse/sparse.hpp + include/proxsuite/proxqp/sparse/utils.hpp + include/proxsuite/proxqp/sparse/views.hpp + include/proxsuite/proxqp/sparse/workspace.hpp + include/proxsuite/proxqp/sparse/wrapper.hpp + include/proxsuite/proxqp/utils/prints.hpp + include/proxsuite/proxqp/utils/random_qp_problems.hpp + include/proxsuite/proxqp/utils/uint128_msvc.hpp + include/proxsuite/proxqp/results.hpp + include/proxsuite/proxqp/settings.hpp + include/proxsuite/proxqp/status.hpp + include/proxsuite/proxqp/timings.hpp + include/proxsuite/fwd.hpp + BASE_DIRS include +) + +if(PROXSUITE_BUILD_WITH_SERIALIZATION) + jrl_target_headers(proxsuite INTERFACE + HEADERS + include/proxsuite/serialization/archive.hpp + include/proxsuite/serialization/eigen.hpp + include/proxsuite/serialization/model.hpp + include/proxsuite/serialization/results.hpp + include/proxsuite/serialization/ruiz.hpp + include/proxsuite/serialization/settings.hpp + include/proxsuite/serialization/workspace.hpp + include/proxsuite/serialization/wrapper.hpp + BASE_DIRS include + ) +endif() + +jrl_add_export_component(NAME proxsuite TARGETS proxsuite) + +if(BUILD_WITH_VECTORIZATION_SUPPORT) + jrl_add_export_component(NAME vectorized TARGETS proxsuite-vectorized) +endif() + +if(BUILD_WITH_OPENMP_SUPPORT) + jrl_add_export_component(NAME parallel TARGETS proxsuite-parallel) + + if(BUILD_WITH_VECTORIZATION_SUPPORT) + jrl_add_export_component(NAME vectorized-parallel TARGETS proxsuite-vectorized-parallel) + endif() +endif() + +jrl_export_package() + +jrl_generate_ros2_package_files( + INSTALL_CPP_PACKAGE_FILES [[NOT BUILD_STANDALONE_PYTHON_INTERFACE]] + INSTALL_PYTHON_PACKAGE_FILES [[BUILD_PYTHON_INTERFACE]] +) -SETUP_PROJECT_FINALIZE() +jrl_print_dependencies_summary() +jrl_print_options_summary() diff --git a/README.md b/README.md index e2a011561..12bed0e0f 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,23 @@ This approach is available on Linux, Windows and Mac OS X. ``` This approach is available on Linux and Mac OS X. +### Develop with `pixi`: + +Install [pixi](https://pixi.prefix.dev/latest), then build with: + +```bash +pixi run build +``` + +To run the tests: + +```bash +pixi run test +``` + +This approach is available on Linux, Windows, and MacOS (Intel and Apple Silicon). + + ### Alternative approaches Installation from source is presented [here](https://github.com/Simple-Robotics/proxsuite/blob/devel/doc/5-installation.md). diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 6f6ea47ef..a96777181 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -1,26 +1,28 @@ -add_custom_target(${PROJECT_NAME}_bench) +function(proxsuite_add_benchmark name) + set(options) + set(oneValueArgs) + set(multiValueArgs LINK_LIBRARIES) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) -macro(proxsuite_benchmark bench_name) - if(BUILD_BENCHMARK) - add_executable(${bench_name} ${bench_name}.cpp) - else(BUILD_BENCHMARK) - add_executable(${bench_name} EXCLUDE_FROM_ALL ${bench_name}.cpp) - endif(BUILD_BENCHMARK) + add_executable(proxsuite-benchmark-${name} ${name}.cpp) + target_link_libraries(proxsuite-benchmark-${name} PRIVATE proxsuite ${arg_LINK_LIBRARIES}) + proxsuite_set_default_target_options(proxsuite-benchmark-${name}) if(BUILD_WITH_VECTORIZATION_SUPPORT) - target_link_libraries(${bench_name} PUBLIC proxsuite-vectorized) - else() - target_link_libraries(${bench_name} PUBLIC proxsuite) + add_executable(proxsuite-vectorized-benchmark-${name} ${name}.cpp) + target_link_libraries( + proxsuite-vectorized-benchmark-${name} + PRIVATE proxsuite-vectorized ${arg_LINK_LIBRARIES} + ) + proxsuite_set_default_target_options(proxsuite-vectorized-benchmark-${name}) endif() - add_dependencies(${PROJECT_NAME}_bench ${bench_name}) -endmacro(proxsuite_benchmark) +endfunction() -proxsuite_benchmark(timings-lp) -proxsuite_benchmark(timings-box-constraints) -proxsuite_benchmark(timings-dense-backend) -proxsuite_benchmark(timings-diagonal-hessian) +proxsuite_add_benchmark(timings-box-constraints) +proxsuite_add_benchmark(timings-dense-backend) +proxsuite_add_benchmark(timings-diagonal-hessian) +proxsuite_add_benchmark(timings-lp) if(BUILD_WITH_OPENMP_SUPPORT) - proxsuite_benchmark(timings-parallel) - target_link_libraries(timings-parallel PRIVATE OpenMP::OpenMP_CXX) -endif(BUILD_WITH_OPENMP_SUPPORT) + proxsuite_add_benchmark(timings-parallel LINK_LIBRARIES proxsuite-parallel) +endif() diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt deleted file mode 100644 index 284d3386b..000000000 --- a/bindings/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -if(BUILD_PYTHON_INTERFACE) - add_subdirectory(python) -endif() diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index cf55a9d47..f37d6714f 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -1,313 +1,167 @@ -if(UNIX) - set(PYTHON_COMPONENTS Interpreter Development.Module) +set( + proxsuite_pywrap_HEADERS + src/algorithms.hpp + src/expose-backward.hpp + src/expose-helpers.hpp + src/expose-model.hpp + src/expose-qpobject.hpp + src/expose-qpvector.hpp + src/expose-results.hpp + src/expose-settings.hpp + src/expose-solve.hpp + src/expose-workspace.hpp + src/optional-eigen-fix.hpp +) +if(BUILD_WITH_OPENMP_SUPPORT) + list(APPEND proxsuite_pywrap_HEADERS src/expose-parallel.hpp) endif() -include(${JRL_CMAKE_MODULES}/python.cmake) -include(${JRL_CMAKE_MODULES}/python-helpers.cmake) +set(proxsuite_pywrap_SOURCES src/expose-all.cpp) -option(GENERATE_PYTHON_STUBS "Generate Python stubs" OFF) +function(create_python_target target_name) + set(options) + set(oneValueArgs) + set(multiValueArgs COMPILE_OPTIONS LINK_LIBRARIES) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) -FINDPYTHON(REQUIRED) -set(Python_INCLUDE_DIRS ${Python3_INCLUDE_DIRS}) -set(Python_VERSION ${Python3_VERSION}) -# Nanobind expects these targets instead of Python3::* -# https://github.com/jrl-umi3218/jrl-cmakemodules/issues/708 -add_library(Python::Module ALIAS Python3::Module) -add_executable(Python::Interpreter ALIAS Python3::Interpreter) + nanobind_add_module(${target_name} NB_STATIC LTO NB_SUPPRESS_WARNINGS ${proxsuite_pywrap_SOURCES} ${proxsuite_pywrap_HEADERS}) + jrl_check_python_module_name(${target_name}) -if(IS_ABSOLUTE ${PYTHON_SITELIB}) - set(${PYWRAP}_INSTALL_DIR ${PYTHON_SITELIB}/${PROJECT_NAME}) -else() - set( - ${PYWRAP}_INSTALL_DIR - ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/${PROJECT_NAME} + target_link_libraries( + ${target_name} + PRIVATE ${arg_LINK_LIBRARIES} $<$:OpenMP::OpenMP_CXX> ) -endif() + target_compile_options(${target_name} PRIVATE ${arg_COMPILE_OPTIONS}) + target_compile_definitions(${target_name} PRIVATE PYTHON_MODULE_NAME=${target_name}) + proxsuite_set_default_target_options(${target_name}) + jrl_target_set_output_directory(${target_name} OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/site-packages/${PROJECT_NAME}) +endfunction() -cmake_policy(PUSH) -cmake_policy(SET CMP0074 NEW) -# Detect the installed nanobind package and import it into CMake -execute_process( - COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE nanobind_ROOT -) -find_package(nanobind CONFIG) -cmake_policy(POP) -if(NOT nanobind_FOUND) - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind) - add_subdirectory( - external/nanobind - ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind - ) - message(STATUS "Will use nanobind submodule.") -else() - message(STATUS "Found installed nanobind.") -endif() +# copy __init_.py and torch files into the build directory (so we can import proxsuite) +file(COPY proxsuite DESTINATION ${CMAKE_BINARY_DIR}/lib/site-packages) + +# The main python binding target +create_python_target(proxsuite_pywrap LINK_LIBRARIES proxsuite) + +# Vectorized python binding targets +if(BUILD_WITH_VECTORIZATION_SUPPORT) + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(AVX_COMPILE_OPTION "/arch:AVX") + set(AVX2_COMPILE_OPTION "/arch:AVX2") + set(FMA_COMPILE_OPTION "/fp:fast") + set(AVX512_COMPILE_OPTION "/arch:AVX512") + else() + set(AVX_COMPILE_OPTION "-mavx") + set(AVX2_COMPILE_OPTION "-mavx2") + set(FMA_COMPILE_OPTION "-mfma") + set(AVX512_COMPILE_OPTION "-mavx512f") + endif() -add_custom_target(${PROJECT_NAME}_python) + if(BUILD_BINDINGS_WITH_AVX2_SUPPORT) + message(STATUS "[proxsuite] Building python bindings with AVX2 support") + create_python_target( + proxsuite_pywrap_avx2 + COMPILE_OPTIONS + "${AVX2_COMPILE_OPTION}" + "${FMA_COMPILE_OPTION}" + LINK_LIBRARIES proxsuite-vectorized + ) + endif() -# Collect files -file(GLOB_RECURSE PYWRAP_HEADERS ${CMAKE_CURRENT_LIST_DIR}/src/*.hpp) -file(GLOB_RECURSE PYWRAP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp) + if(BUILD_BINDINGS_WITH_AVX512_SUPPORT) + message(STATUS "[proxsuite] Building python bindings with AVX512 support") + create_python_target( + proxsuite_pywrap_avx512 + COMPILE_OPTIONS + "${AVX512_COMPILE_OPTION}" + "${FMA_COMPILE_OPTION}" + LINK_LIBRARIES proxsuite-vectorized + ) + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND Eigen3_VERSION VERSION_GREATER_EQUAL 5.0) + # BUG: Eigen5 introduced a new AVX512 GEMM kernel that causes extremely long compilation times on MSVC. + # Disabling it for now. ref: libeigen/eigen#3066 + target_compile_definitions(proxsuite_pywrap_avx512 PRIVATE EIGEN_USE_AVX512_GEMM_KERNELS=0) + endif() + endif() + else() + message( + WARNING + "[proxsuite] AVX2 and AVX512 python bindings are only supported on x86_64. Current architecture is '${CMAKE_SYSTEM_PROCESSOR}'" + ) + endif() +endif() # Add simd feature detectors for current intel CPU if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") - nanobind_add_module(instructionset helpers/instruction-set.cpp) - add_dependencies(${PROJECT_NAME}_python instructionset) + nanobind_add_module(instructionset NB_STATIC LTO NB_SUPPRESS_WARNINGS helpers/instruction-set.cpp) target_link_libraries(instructionset PRIVATE proxsuite) - set_target_properties( + proxsuite_set_default_target_options(instructionset) + jrl_target_set_output_directory( instructionset - PROPERTIES - OUTPUT_NAME instructionset - LIBRARY_OUTPUT_DIRECTORY - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - LIBRARY_OUTPUT_DIRECTORY_RELEASE - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - LIBRARY_OUTPUT_DIRECTORY_DEBUG - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - # On Windows, shared library are treat as binary - RUNTIME_OUTPUT_DIRECTORY - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - RUNTIME_OUTPUT_DIRECTORY_RELEASE - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - RUNTIME_OUTPUT_DIRECTORY_DEBUG - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - ) - if(UNIX AND NOT APPLE) - set_target_properties( - instructionset - PROPERTIES INSTALL_RPATH "\$ORIGIN/../../.." - ) - endif() - install( - TARGETS instructionset - EXPORT ${TARGETS_EXPORT_NAME} - DESTINATION ${${PYWRAP}_INSTALL_DIR} + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/lib/site-packages/${PROJECT_NAME} ) if(GENERATE_PYTHON_STUBS) nanobind_add_stub( instructionset_stub MODULE instructionset - OUTPUT instructionset.pyi + OUTPUT ${CMAKE_BINARY_DIR}/lib/site-packages/${PROJECT_NAME}/instructionset.pyi PYTHON_PATH $ DEPENDS instructionset ) - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/instructionset.pyi - DESTINATION ${${PYWRAP}_INSTALL_DIR} - ) endif() endif() -function(list_filter list regular_expression dest_list) - foreach(elt ${list}) - if(${elt} MATCHES ${regular_expression}) - list(REMOVE_ITEM list ${elt}) - endif() - endforeach(elt ${list}) - set(${dest_list} ${list} PARENT_SCOPE) -endfunction(list_filter) - -function( - create_python_target - target_name - compile_options - dependencies - generate_stubs -) - nanobind_add_module(${target_name} ${PYWRAP_SOURCES} ${PYWRAP_HEADERS}) - add_dependencies(${PROJECT_NAME}_python ${target_name}) - - target_link_libraries(${target_name} PUBLIC ${dependencies}) - target_compile_options(${target_name} PRIVATE ${compile_options}) - target_link_libraries(${target_name} PRIVATE proxsuite) - target_compile_definitions( - ${target_name} - PRIVATE PYTHON_MODULE_NAME=${target_name} - ) - - if(BUILD_WITH_OPENMP_SUPPORT) - target_compile_options(${target_name} PRIVATE ${OpenMP_CXX_FLAGS}) - target_compile_definitions( - ${target_name} - PRIVATE -DPROXSUITE_PYTHON_INTERFACE_WITH_OPENMP - ) - target_include_directories( - ${target_name} - SYSTEM - PRIVATE ${OpenMP_CXX_INCLUDE_DIR} - ) - if(LINK_PYTHON_INTERFACE_TO_OPENMP) - target_link_libraries(${target_name} PRIVATE ${OpenMP_CXX_LIBRARIES}) - endif(LINK_PYTHON_INTERFACE_TO_OPENMP) - else() - list_filter("${PYWRAP_HEADERS}" "expose-parallel" PYWRAP_HEADERS) - endif(BUILD_WITH_OPENMP_SUPPORT) - - if(cereal_FOUND) - target_link_libraries(${target_name} PRIVATE cereal::cereal) - else() - target_include_directories( - ${target_name} - SYSTEM - PRIVATE ${PROJECT_SOURCE_DIR}/external/cereal/include - ) - endif() - set_target_properties( - ${target_name} - PROPERTIES - OUTPUT_NAME ${target_name} - LIBRARY_OUTPUT_DIRECTORY - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - LIBRARY_OUTPUT_DIRECTORY_RELEASE - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - LIBRARY_OUTPUT_DIRECTORY_DEBUG - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - # On Windows, shared library are treat as binary - RUNTIME_OUTPUT_DIRECTORY - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - RUNTIME_OUTPUT_DIRECTORY_RELEASE - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - RUNTIME_OUTPUT_DIRECTORY_DEBUG - "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" - ) - - if(UNIX AND NOT APPLE) - set_target_properties( - ${target_name} - PROPERTIES INSTALL_RPATH "\$ORIGIN/../../.." - ) +if(GENERATE_PYTHON_STUBS) + if(TARGET proxsuite_pywrap_avx2) + set(avx2_lib proxsuite_pywrap_avx2) endif() - - install(TARGETS ${target_name} DESTINATION ${${PYWRAP}_INSTALL_DIR}) - if(${generate_stubs}) - set( - stub_outputs - ${target_name}/__init__.pyi - ${target_name}/helpers.pyi - ${target_name}/proxqp/__init__.pyi - ${target_name}/proxqp/dense.pyi - ${target_name}/proxqp/sparse.pyi - ) - nanobind_add_stub( - ${target_name}_stub - MODULE ${target_name} - OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} - OUTPUT ${stub_outputs} - RECURSIVE - PYTHON_PATH $ - DEPENDS ${target_name} - ) - install( - DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${target_name} - DESTINATION ${${PYWRAP}_INSTALL_DIR} - ) + if(TARGET proxsuite_pywrap_avx512) + set(avx512_lib proxsuite_pywrap_avx512) endif() -endfunction() -if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) - set(AVX_COMPILE_OPTION "/arch:AVX") - set(AVX2_COMPILE_OPTION "/arch:AVX2") - set(FMA_COMPILE_OPTION "/fp:fast,") - set(AVX512_COMPILE_OPTION "/arch:AVX512") -else() - set(AVX_COMPILE_OPTION "-mavx") - set(AVX2_COMPILE_OPTION "-mavx2") - set(FMA_COMPILE_OPTION "-mfma") - set(AVX512_COMPILE_OPTION "-mavx512f") -endif() - -create_python_target(proxsuite_pywrap "" proxsuite ${GENERATE_PYTHON_STUBS}) -if( - BUILD_WITH_VECTORIZATION_SUPPORT - AND ${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)" -) - if(BUILD_BINDINGS_WITH_AVX2_SUPPORT) - create_python_target( - proxsuite_pywrap_avx2 - "${AVX2_COMPILE_OPTION};${FMA_COMPILE_OPTION}" - proxsuite-vectorized - FALSE - ) - endif(BUILD_BINDINGS_WITH_AVX2_SUPPORT) - if(BUILD_BINDINGS_WITH_AVX512_SUPPORT) - create_python_target( - proxsuite_pywrap_avx512 - "${AVX512_COMPILE_OPTION};${FMA_COMPILE_OPTION}" - proxsuite-vectorized - FALSE - ) - endif(BUILD_BINDINGS_WITH_AVX512_SUPPORT) + nanobind_add_stub( + proxsuite_pywrap_stub + MODULE proxsuite + VERBOSE + OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib/site-packages/${PROJECT_NAME} + OUTPUT + __init__.pyi + helpers.pyi + proxqp/__init__.pyi + proxqp/dense.pyi + proxqp/sparse.pyi + RECURSIVE + PYTHON_PATH ${CMAKE_BINARY_DIR}/lib/site-packages + DEPENDS proxsuite_pywrap ${avx2_lib} ${avx512_lib} + ) endif() -ADD_HEADER_GROUP(PYWRAP_HEADERS) -ADD_SOURCE_GROUP(PYWRAP_SOURCES) -# --- INSTALL SCRIPTS - -# On Windows, we need to enforce the environment variable KMP_DUPLICATE_LIB_OK -# to True to to allow the program to continue to execute with OpenMP support -if( - WIN32 - AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" - AND BUILD_WITH_OPENMP_SUPPORT +jrl_python_compile_all( + DIRECTORY ${CMAKE_BINARY_DIR}/lib/site-packages ) - set( - OPENMP_KMP_DUPLICATE_LIB_OK_SCRIPT - "import os\n" - "os.environ[\"KMP_DUPLICATE_LIB_OK\"] = \"1\"\n\n" - ) - if(CMAKE_GENERATOR MATCHES "Visual Studio|Xcode") - set(PYTHON_MODULE_DIR "${CMAKE_CURRENT_BINARY_DIR}/proxsuite/$") - else() - set(PYTHON_MODULE_DIR "${CMAKE_CURRENT_BINARY_DIR}/proxsuite") - endif() - - set(original_init_dot_py_file ${CMAKE_CURRENT_LIST_DIR}/proxsuite/__init__.py) - set( - generated_init_dot_py_file - ${CMAKE_CURRENT_BINARY_DIR}/proxsuite/__init__.py - ) - set(generated_init_dot_pyc_file ${PYTHON_MODULE_DIR}/__init__.pyc) - - # Copy content of the __init__.py file - file(READ ${original_init_dot_py_file} INIT_CONTENT) - # Create a new __init__.py file containing both the content of __init__.py - # prepended with the OPENMP_KMP_DUPLICATE_LIB_OK_SCRIPT content - file( - WRITE ${generated_init_dot_py_file} - ${OPENMP_KMP_DUPLICATE_LIB_OK_SCRIPT} - ) - file(APPEND ${generated_init_dot_py_file} ${INIT_CONTENT}) - - PYTHON_BUILD_FILE( - ${generated_init_dot_py_file} - ${generated_init_dot_pyc_file} - ) - install( - FILES "${generated_init_dot_py_file}" - DESTINATION ${${PYWRAP}_INSTALL_DIR} - ) -else() - PYTHON_BUILD(${PROJECT_NAME} __init__.py) - install( - FILES "${CMAKE_CURRENT_SOURCE_DIR}/proxsuite/__init__.py" - DESTINATION ${${PYWRAP}_INSTALL_DIR} - ) +set(targets_to_install proxsuite_pywrap) +if(TARGET proxsuite_pywrap_avx2) + list(APPEND targets_to_install proxsuite_pywrap_avx2) +endif() +if(TARGET proxsuite_pywrap_avx512) + list(APPEND targets_to_install proxsuite_pywrap_avx512) +endif() +if(TARGET instructionset) + list(APPEND targets_to_install instructionset) endif() -PYTHON_BUILD_GET_TARGET(compile_pyc) -add_dependencies(${PROJECT_NAME}_python ${compile_pyc}) - -set(PYTHON_FILES torch/__init__.py torch/qplayer.py torch/utils.py) - -file(MAKE_DIRECTORY ${${PYWRAP}_INSTALL_DIR}/torch) - -foreach(python ${PYTHON_FILES}) - PYTHON_BUILD(${PROJECT_NAME} ${python}) - get_filename_component(pysubmodule ${python} PATH) - get_filename_component(pyname ${python} NAME) - set(MODULE_NAME ${PROJECT_NAME}/${pysubmodule}) - PYTHON_INSTALL_ON_SITE(${MODULE_NAME} ${pyname}) -endforeach(python) +# Install the whole python package directory +jrl_python_compute_install_dir(python_install_dir) +install(TARGETS ${targets_to_install} DESTINATION ${python_install_dir}/${PROJECT_NAME}) +install( + DIRECTORY ${CMAKE_BINARY_DIR}/lib/site-packages/${PROJECT_NAME} + DESTINATION ${python_install_dir} + FILES_MATCHING + PATTERN "*.py" + PATTERN "*.pyc" + PATTERN "*.pyi" + PATTERN "*.typed" +) diff --git a/bindings/python/external/nanobind b/bindings/python/external/nanobind deleted file mode 160000 index 22acf11a2..000000000 --- a/bindings/python/external/nanobind +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 22acf11a2dac212e857f0d06ce80f808cac8fdad diff --git a/bindings/python/proxsuite/__init__.py b/bindings/python/proxsuite/__init__.py index 22e535961..eb79e4acb 100644 --- a/bindings/python/proxsuite/__init__.py +++ b/bindings/python/proxsuite/__init__.py @@ -8,6 +8,12 @@ if TYPE_CHECKING: from .proxsuite_pywrap import * # noqa F403 +import os + +os.environ["KMP_DUPLICATE_LIB_OK"] = ( + "True" # to avoid issues with OpenMP in some environments +) + def _load_main_module(): import platform diff --git a/cmake-external/FindMatio.cmake b/cmake-external/FindMatio.cmake deleted file mode 100644 index 935aad504..000000000 --- a/cmake-external/FindMatio.cmake +++ /dev/null @@ -1,38 +0,0 @@ -# ============================================================================= -# SPDX-FileCopyrightText: 2021 Stefan Gerlach -# -# SPDX-License-Identifier: BSD-3-Clause -# ============================================================================= - -find_library(MATIO_LIBRARIES NAMES matio libmatio) - -find_path(MATIO_INCLUDE_DIR matio.h) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - Matio - FOUND_VAR MATIO_FOUND - REQUIRED_VARS MATIO_LIBRARIES MATIO_INCLUDE_DIR -) - -if(MATIO_FOUND) - add_library(matio UNKNOWN IMPORTED) - set_target_properties( - matio - PROPERTIES - IMPORTED_LOCATION "${MATIO_LIBRARIES}" - INTERFACE_INCLUDE_DIRECTORIES "${MATIO_INCLUDE_DIR}" - ) -else() - set(MATIO_LIBRARIES "") -endif() - -mark_as_advanced(MATIO_LIBRARIES MATIO_INCLUDE_DIR) - -include(FeatureSummary) -set_package_properties( - Matio - PROPERTIES - DESCRIPTION "Reading and writing binary MATLAB MAT files" - URL "https://github.com/tbeu/matio" -) diff --git a/cmake-external/FindSphinx.cmake b/cmake-external/FindSphinx.cmake deleted file mode 100644 index c00f3720d..000000000 --- a/cmake-external/FindSphinx.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# Look for an executable called sphinx-build -find_program( - SPHINX_EXECUTABLE - NAMES sphinx-build - DOC "Path to sphinx-build executable" -) - -include(FindPackageHandleStandardArgs) -# Handle standard arguments to find_package like REQUIRED and QUIET -find_package_handle_standard_args( - Sphinx - "Failed to find sphinx-build executable" - SPHINX_EXECUTABLE -) diff --git a/cmake-external/compiler_warnings.cmake b/cmake-external/compiler_warnings.cmake deleted file mode 100644 index da63eaf57..000000000 --- a/cmake-external/compiler_warnings.cmake +++ /dev/null @@ -1,91 +0,0 @@ -# from here: -# -# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Avai -# lable.md - -function(set_project_warnings project_name) - option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) - - set( - MSVC_WARNINGS - /W4 # Baseline reasonable warnings - /w14242 # 'identfier': conversion from 'type1' to 'type1', possible loss - # of data - /w14254 # 'operator': conversion from 'type1:field_bits' to - # 'type2:field_bits', possible loss of data - /w14263 # 'function': member function does not override any base class - # virtual member function - /w14265 # 'classname': class has virtual functions, but destructor is not - # virtual instances of this class may not be destructed correctly - /w14287 # 'operator': unsigned/negative constant mismatch - /we4289 # nonstandard extension used: 'variable': loop control variable - # declared in the for-loop is used outside the for-loop scope - /w14296 # 'operator': expression is always 'boolean_value' - /w14311 # 'variable': pointer truncation from 'type1' to 'type2' - /w14545 # expression before comma evaluates to a function which is missing - # an argument list - /w14546 # function call before comma missing argument list - /w14547 # 'operator': operator before comma has no effect; expected - # operator with side-effect - /w14549 # 'operator': operator before comma has no effect; did you intend - # 'operator'? - /w14555 # expression has no effect; expected expression with side- effect - /w14619 # pragma warning: there is no warning number 'number' - /w14640 # Enable warning on thread un-safe static member initialization - /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may - # cause unexpected runtime behavior. - /w14905 # wide string literal cast to 'LPSTR' - /w14906 # string literal cast to 'LPWSTR' - /w14928 # illegal copy-initialization; more than one user-defined - # conversion has been implicitly applied - ) - - set( - CLANG_WARNINGS - -Wall - -Wextra # reasonable and standard - -Wshadow # warn the user if a variable declaration shadows one from a - # parent context - -Wnon-virtual-dtor # warn the user if a class with virtual functions has a - # non-virtual destructor. This helps catch hard to - # track down memory errors - -Wold-style-cast # warn for c-style casts - -Wcast-align # warn for potential performance problem casts - -Wunused # warn on anything being unused - -Woverloaded-virtual # warn if you overload (not override) a virtual - # function - -Wpedantic # warn if non-standard C++ is used - -Wconversion # warn on type conversions that may lose data - -Wsign-conversion # warn on sign conversions - -Wnull-dereference # warn if a null dereference is detected - -Wdouble-promotion # warn if float is implicit promoted to double - -Wformat=2 # warn on security issues around functions that format output - # (ie printf) - ) - - if(WARNINGS_AS_ERRORS) - set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) - set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX) - endif() - - set( - GCC_WARNINGS - ${CLANG_WARNINGS} - -Wmisleading-indentation # warn if identation implies blocks where blocks - # do not exist - -Wduplicated-cond # warn if if / else chain has duplicated conditions - -Wduplicated-branches # warn if if / else branches have duplicated code - -Wlogical-op # warn about logical operations being used where bitwise were - # probably wanted - ) - - if(MSVC) - set(PROJECT_WARNINGS ${MSVC_WARNINGS}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - set(PROJECT_WARNINGS ${CLANG_WARNINGS}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(PROJECT_WARNINGS ${GCC_WARNINGS}) - endif() - - target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS}) -endfunction() diff --git a/cmake-external/doctest.cmake b/cmake-external/doctest.cmake deleted file mode 100644 index 6e10cd31a..000000000 --- a/cmake-external/doctest.cmake +++ /dev/null @@ -1,178 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -doctest ------ - -This module defines a function to help use the doctest test framework. - -The :command:`doctest_discover_tests` discovers tests by asking the compiled test -executable to enumerate its tests. This does not require CMake to be re-run -when tests change. However, it may not work in a cross-compiling environment, -and setting test properties is less convenient. - -This command is intended to replace use of :command:`add_test` to register -tests, and will create a separate CTest test for each doctest test case. Note -that this is in some cases less efficient, as common set-up and tear-down logic -cannot be shared by multiple test cases executing in the same instance. -However, it provides more fine-grained pass/fail information to CTest, which is -usually considered as more beneficial. By default, the CTest test name is the -same as the doctest name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. - -.. command:: doctest_discover_tests - - Automatically add tests with CTest by querying the compiled test executable - for available tests:: - - doctest_discover_tests(target - [TEST_SPEC arg1...] - [EXTRA_ARGS arg1...] - [WORKING_DIRECTORY dir] - [TEST_PREFIX prefix] - [TEST_SUFFIX suffix] - [PROPERTIES name1 value1...] - [TEST_LIST var] - ) - - ``doctest_discover_tests`` sets up a post-build command on the test executable - that generates the list of tests by parsing the output from running the test - with the ``--list-test-cases`` argument. This ensures that the full - list of tests is obtained. Since test discovery occurs at build time, it is - not necessary to re-run CMake when the list of tests changes. - However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set - in order to function in a cross-compiling environment. - - Additionally, setting properties on tests is somewhat less convenient, since - the tests are not available at CMake time. Additional test properties may be - assigned to the set of tests as a whole using the ``PROPERTIES`` option. If - more fine-grained test control is needed, custom content may be provided - through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES` - directory property. The set of discovered tests is made accessible to such a - script via the ``_TESTS`` variable. - - The options are: - - ``target`` - Specifies the doctest executable, which must be a known CMake executable - target. CMake will substitute the location of the built executable when - running the test. - - ``TEST_SPEC arg1...`` - Specifies test cases, wildcarded test cases, tags and tag expressions to - pass to the doctest executable with the ``--list-test-cases`` argument. - - ``EXTRA_ARGS arg1...`` - Any extra arguments to pass on the command line to each test case. - - ``WORKING_DIRECTORY dir`` - Specifies the directory in which to run the discovered test cases. If this - option is not provided, the current binary directory is used. - - ``TEST_PREFIX prefix`` - Specifies a ``prefix`` to be prepended to the name of each discovered test - case. This can be useful when the same test executable is being used in - multiple calls to ``doctest_discover_tests()`` but with different - ``TEST_SPEC`` or ``EXTRA_ARGS``. - - ``TEST_SUFFIX suffix`` - Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of - every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may - be specified. - - ``PROPERTIES name1 value1...`` - Specifies additional properties to be set on all tests discovered by this - invocation of ``doctest_discover_tests``. - - ``TEST_LIST var`` - Make the list of tests available in the variable ``var``, rather than the - default ``_TESTS``. This can be useful when the same test - executable is being used in multiple calls to ``doctest_discover_tests()``. - Note that this variable is only available in CTest. - -#]=======================================================================] - -# ------------------------------------------------------------------------------ -function(doctest_discover_tests TARGET) - cmake_parse_arguments( - "" - "" - "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST" - "TEST_SPEC;EXTRA_ARGS;PROPERTIES" - ${ARGN} - ) - - if(NOT _WORKING_DIRECTORY) - set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - endif() - if(NOT _TEST_LIST) - set(_TEST_LIST ${TARGET}_TESTS) - endif() - - # Generate a unique name based on the extra arguments - string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}") - string(SUBSTRING ${args_hash} 0 7 args_hash) - - # Define rule to generate test list for aforementioned test executable - set( - ctest_include_file - "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake" - ) - set( - ctest_tests_file - "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake" - ) - get_property( - crosscompiling_emulator - TARGET ${TARGET} - PROPERTY CROSSCOMPILING_EMULATOR - ) - add_custom_command( - TARGET ${TARGET} - POST_BUILD - BYPRODUCTS "${ctest_tests_file}" - COMMAND - "${CMAKE_COMMAND}" -D "TEST_TARGET=${TARGET}" -D - "TEST_EXECUTABLE=$" -D - "TEST_EXECUTOR=${crosscompiling_emulator}" -D - "TEST_WORKING_DIR=${_WORKING_DIRECTORY}" -D "TEST_SPEC=${_TEST_SPEC}" -D - "TEST_EXTRA_ARGS=${_EXTRA_ARGS}" -D "TEST_PROPERTIES=${_PROPERTIES}" -D - "TEST_PREFIX=${_TEST_PREFIX}" -D "TEST_SUFFIX=${_TEST_SUFFIX}" -D - "TEST_LIST=${_TEST_LIST}" -D "CTEST_FILE=${ctest_tests_file}" -P - "${_DOCTEST_DISCOVER_TESTS_SCRIPT}" - VERBATIM - ) - - file( - WRITE "${ctest_include_file}" - "if(EXISTS \"${ctest_tests_file}\")\n" - " include(\"${ctest_tests_file}\")\n" - "else()\n" - " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n" - "endif()\n" - ) - - if(NOT CMAKE_VERSION VERSION_LESS 3.10) - # Add discovered tests to directory TEST_INCLUDE_FILES - set_property( - DIRECTORY - APPEND - PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" - ) - else() - # Add discovered tests as directory TEST_INCLUDE_FILE if possible - get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET) - if(NOT ${test_include_file_set}) - set_property(DIRECTORY PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}") - else() - message(FATAL_ERROR "Cannot set more than one TEST_INCLUDE_FILE") - endif() - endif() -endfunction() - -# ############################################################################## - -set( - _DOCTEST_DISCOVER_TESTS_SCRIPT - ${CMAKE_CURRENT_LIST_DIR}/doctestAddTests.cmake -) diff --git a/cmake-external/doctestAddTests.cmake b/cmake-external/doctestAddTests.cmake deleted file mode 100644 index 689ec75de..000000000 --- a/cmake-external/doctestAddTests.cmake +++ /dev/null @@ -1,91 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -set(prefix "${TEST_PREFIX}") -set(suffix "${TEST_SUFFIX}") -set(spec ${TEST_SPEC}) -set(extra_args ${TEST_EXTRA_ARGS}) -set(properties ${TEST_PROPERTIES}) -set(script) -set(suite) -set(tests) - -function(add_command NAME) - set(_args "") - foreach(_arg ${ARGN}) - if(_arg MATCHES "[^-./:a-zA-Z0-9_]") - set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument - else() - set(_args "${_args} ${_arg}") - endif() - endforeach() - set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) -endfunction() - -# Run test executable to get list of available tests -if(NOT EXISTS "${TEST_EXECUTABLE}") - message( - FATAL_ERROR - "Specified test executable '${TEST_EXECUTABLE}' does not exist" - ) -endif() - -if("${spec}" MATCHES .) - set(spec "--test-case=${spec}") -endif() - -execute_process( - COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-cases - OUTPUT_VARIABLE output - RESULT_VARIABLE result -) -if(NOT ${result} EQUAL 0) - message( - FATAL_ERROR - "Error running test executable '${TEST_EXECUTABLE}':\n" - " Result: ${result}\n" - " Output: ${output}\n" - ) -endif() - -string(REPLACE "\n" ";" output "${output}") - -# Parse output -foreach(line ${output}) - if( - "${line}" - STREQUAL - "===============================================================================" - OR "${line}" MATCHES [==[^\[doctest\] ]==] - ) - continue() - endif() - set(test ${line}) - # use escape commas to handle properly test cases with commas inside the name - string(REPLACE "," "\\," test_name ${test}) - # ...and add to script - add_command( - add_test - "${prefix}${test}${suffix}" - ${TEST_EXECUTOR} - "${TEST_EXECUTABLE}" - "--test-case=${test_name}" - ${extra_args} - ) - add_command( - set_tests_properties - "${prefix}${test}${suffix}" - PROPERTIES - WORKING_DIRECTORY - "${TEST_WORKING_DIR}" - ${properties} - ) - list(APPEND tests "${prefix}${test}${suffix}") -endforeach() - -# Create a list of all discovered tests, which users may use to e.g. set -# properties on the tests -add_command(set ${TEST_LIST} ${tests}) - -# Write CTest script -file(WRITE "${CTEST_FILE}" "${script}") diff --git a/cmake-external/extra_local_settings.cmake b/cmake-external/extra_local_settings.cmake deleted file mode 100644 index 7e1687e4f..000000000 --- a/cmake-external/extra_local_settings.cmake +++ /dev/null @@ -1,58 +0,0 @@ -option( - ENABLE_IPO - "Enable Iterprocedural Optimization, aka Link Time Optimization (LTO)" - OFF -) -option(ARCH_NATIVE "Build with -march=native" OFF) -option(USE_LIBCXX "Use the libc++ STL" OFF) - -option( - ENABLE_BUILD_WITH_TIME_TRACE - "Enable -ftime-trace to generate time tracing .json files on clang" - OFF -) -if(ENABLE_BUILD_WITH_TIME_TRACE AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") - add_compile_options("-ftime-trace") -endif() - -if(USE_LLD) - add_link_options("-fuse-ld=lld") -elseif(USE_GOLD) - add_link_options("-fuse-ld=gold") -endif() - -if(USE_LIBCXX) - if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") - add_compile_options("-stdlib=libc++") - add_link_options("-stdlib=libc++ -lc++abi") - else() - message(SEND_ERROR "libc++ only available with clang") - endif() -endif() - -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to 'Debug' as none was specified.") - set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) - set_property( - CACHE CMAKE_BUILD_TYPE - PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo" - ) -endif() - -if(ENABLE_IPO) - include(CheckIPOSupported) - check_ipo_supported(RESULT result OUTPUT output) - if(result) - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) - else() - message(SEND_ERROR "IPO is not supported: ${output}") - endif() -endif() - -include(CheckCXXCompilerFlag) -if(ARCH_NATIVE) - check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) - if(COMPILER_SUPPORTS_MARCH_NATIVE) - add_compile_options("-march=native") - endif() -endif() diff --git a/cmake-external/sanitizers.cmake b/cmake-external/sanitizers.cmake deleted file mode 100644 index 7c54c8eb4..000000000 --- a/cmake-external/sanitizers.cmake +++ /dev/null @@ -1,76 +0,0 @@ -function(enable_sanitizers project_name) - if( - CMAKE_CXX_COMPILER_ID STREQUAL "GNU" - OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" - ) - option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE) - - if(ENABLE_COVERAGE) - target_compile_options(${project_name} INTERFACE --coverage -O0 -g) - target_link_libraries(${project_name} INTERFACE --coverage) - endif() - - set(SANITIZERS "") - - option(ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" OFF) - if(ENABLE_SANITIZER_ADDRESS) - list(APPEND SANITIZERS "address") - target_compile_options( - ${project_name} - INTERFACE -fsanitize-address-use-after-scope - ) - target_link_libraries( - ${project_name} - INTERFACE -fsanitize-address-use-after-scope - ) - endif() - - option(ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" OFF) - if(ENABLE_SANITIZER_MEMORY) - list(APPEND SANITIZERS "memory") - target_compile_options( - ${project_name} - INTERFACE -fsanitize-memory-track-origins=2 - ) - target_link_libraries( - ${project_name} - INTERFACE -fsanitize-memory-track-origins=2 - ) - endif() - - option( - ENABLE_SANITIZER_UNDEFINED_BEHAVIOR - "Enable undefined behavior sanitizer" - OFF - ) - if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR) - list(APPEND SANITIZERS "undefined") - endif() - - option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" OFF) - if(ENABLE_SANITIZER_THREAD) - list(APPEND SANITIZERS "thread") - endif() - - list(JOIN SANITIZERS "," LIST_OF_SANITIZERS) - endif() - - if(LIST_OF_SANITIZERS) - if(NOT "${LIST_OF_SANITIZERS}" STREQUAL "") - target_compile_options( - ${project_name} - INTERFACE - -fsanitize=${LIST_OF_SANITIZERS} - -fno-omit-frame-pointer - -fno-optimize-sibling-calls - ) - target_link_libraries( - ${project_name} - INTERFACE - -fsanitize=${LIST_OF_SANITIZERS} - -fno-omit-frame-pointer - -fno-optimize-sibling-calls - ) - endif() - endif() -endfunction() diff --git a/cmake-external/static_analyzers.cmake b/cmake-external/static_analyzers.cmake deleted file mode 100644 index 255478f11..000000000 --- a/cmake-external/static_analyzers.cmake +++ /dev/null @@ -1,33 +0,0 @@ -option(ENABLE_CPPCHECK "Enable static analysis with cppcheck" OFF) -option(ENABLE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF) -if(ENABLE_CPPCHECK) - find_program(CPPCHECK cppcheck) - if(CPPCHECK) - set( - CMAKE_CXX_CPPCHECK - ${CPPCHECK} - --suppress=missingInclude - --enable=all - --inconclusive - -i - ${CMAKE_SOURCE_DIR}/imgui/lib - ) - else() - message(SEND_ERROR "cppcheck requested but executable not found") - endif() -endif() - -if(ENABLE_CLANG_TIDY AND (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) - find_program(CLANGTIDY clang-tidy) - find_program(UNBUFFER unbuffer) - if(CLANGTIDY) - if(UNBUFFER) - set(CMAKE_CXX_CLANG_TIDY unbuffer ${CLANGTIDY}) - else() - message(WARNING "unbuffer not found") - set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY}) - endif() - else() - message(SEND_ERROR "clang-tidy requested but executable not found") - endif() -endif() diff --git a/cmake-module b/cmake-module deleted file mode 160000 index 648efca10..000000000 --- a/cmake-module +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 648efca10ffc9081c633e5d23d8b069e89eee341 diff --git a/cmake/get-jrl-cmakemodules.cmake b/cmake/get-jrl-cmakemodules.cmake new file mode 100644 index 000000000..9d55b6733 --- /dev/null +++ b/cmake/get-jrl-cmakemodules.cmake @@ -0,0 +1,49 @@ +# Get jrl-cmakemodules package + +# Option 1: pass -DJRL_CMAKEMODULES_SOURCE_DIR=... to cmake command line +if(JRL_CMAKEMODULES_SOURCE_DIR) + message( + DEBUG + "JRL_CMAKEMODULES_SOURCE_DIR variable set, adding jrl-cmakemodules from source directory: ${JRL_CMAKEMODULES_SOURCE_DIR}" + ) + add_subdirectory(${JRL_CMAKEMODULES_SOURCE_DIR} jrl-cmakemodules) + return() +endif() + +# Option 2: use JRL_CMAKEMODULES_SOURCE_DIR environment variable (pixi might unset it, prefer option 1) +if(ENV{JRL_CMAKEMODULES_SOURCE_DIR}) + message( + DEBUG + "JRL_CMAKEMODULES_SOURCE_DIR environement variable set, adding jrl-cmakemodules from source directory: ${JRL_CMAKEMODULES_SOURCE_DIR}" + ) + add_subdirectory(${JRL_CMAKEMODULES_SOURCE_DIR} jrl-cmakemodules) + return() +endif() + +# Try to look for the installed package +message(DEBUG "Looking for jrl-cmakemodules using find_package().") +find_package(jrl-cmakemodules 2.2.0 CONFIG QUIET) + +# If we have the package, we are done. +if(jrl-cmakemodules_FOUND) + message(DEBUG "Found jrl-cmakemodules package via find_package().") + return() +else() + message(DEBUG "jrl-cmakemodules package not found using find_package().") +endif() + +# Fallback to FetchContent if not found +set(JRL_GIT_REPOSITORY "https://github.com/jrl-umi3218/jrl-cmakemodules.git") +set(JRL_GIT_TAG "master") + +message( + DEBUG + "Fetching jrl-cmakemodules using FetchContent: + GIT_REPOSITORY: ${JRL_GIT_REPOSITORY} + GIT_TAG : ${JRL_GIT_TAG} +" +) + +include(FetchContent) +FetchContent_Declare(jrl-cmakemodules GIT_REPOSITORY ${JRL_GIT_REPOSITORY} GIT_TAG ${JRL_GIT_TAG}) +FetchContent_MakeAvailable(jrl-cmakemodules) diff --git a/development/build.md b/development/build.md index 47c18c94e..b146fbe99 100644 --- a/development/build.md +++ b/development/build.md @@ -1,5 +1,3 @@ -**Pixi will soon be available** - # Build and develop with pixi The easiest way to set up a development environment is to use [pixi](https://pixi.sh/latest/#installation). diff --git a/development/release.md b/development/release.md new file mode 100644 index 000000000..afb8505a5 --- /dev/null +++ b/development/release.md @@ -0,0 +1,28 @@ +# Release with Pixi + +To create a release with Pixi run the following commands on the **devel** branch: + +```bash +pixi shell -e new-version +jrl-release --update-version X.Y.Z --git-commit --git-tag --sign-tag +git push origin +git push origin vX.Y.Z +``` + +Where `X.Y.Z` is the new version. +Be careful to follow the [Semantic Versioning](https://semver.org/spec/v2.0.0.html) rules. + +Then, create a new release on [GitHub](https://github.com/Simple-Robotics/proxsuite/releases/new) with: + +* Tag: vX.Y.Z +* Title: ProxSuite X.Y.Z +* Body: +``` +## What's Changed + +CHANGELOG CONTENT + +**Full Changelog**: https://github.com/Simple-Robotics/proxsuite/compare/vXX.YY.ZZ...vX.Y.Z +``` + +Where `XX.YY.ZZ` is the last release version. diff --git a/development/scripts/pixi/activation.bat b/development/scripts/pixi/activation.bat new file mode 100644 index 000000000..d20fd526b --- /dev/null +++ b/development/scripts/pixi/activation.bat @@ -0,0 +1,6 @@ +:: Set default build value only if not previously set +if not defined PROXSUITE_BUILD_TYPE (set PROXSUITE_BUILD_TYPE=Release) +if not defined PROXSUITE_BUILD_VECTORIZATION (set PROXSUITE_BUILD_VECTORIZATION=ON) +if not defined PROXSUITE_BUILD_PYTHON_INTERFACE (set PROXSUITE_BUILD_PYTHON_INTERFACE=OFF) +if not defined PROXSUITE_BUILD_TESTING (set PROXSUITE_BUILD_TESTING=ON) +if not defined PROXSUITE_BUILD_MAROS_MESZAROS_TESTS (set PROXSUITE_BUILD_MAROS_MESZAROS_TESTS=OFF) diff --git a/development/scripts/pixi/activation.sh b/development/scripts/pixi/activation.sh new file mode 100644 index 000000000..f91224c01 --- /dev/null +++ b/development/scripts/pixi/activation.sh @@ -0,0 +1,18 @@ +#! /bin/bash +# Activation script + +if [[ $PIXI_ENVIRONMENT_PLATFORMS == *"linux"* ]]; +then + # Conda compiler is named x86_64-conda-linux-gnu-c++, ccache can't resolve it + # (https://ccache.dev/manual/latest.html#config_compiler_type) + export CCACHE_COMPILERTYPE=gcc +fi +# Without -isystem, some LSP can't find headers +export PROXSUITE_CXX_FLAGS="$PROXSUITE_CXX_FLAGS -isystem $CONDA_PREFIX/include" + +# Set default build value only if not previously set +export PROXSUITE_BUILD_TYPE=${PROXSUITE_BUILD_TYPE:=Release} +export PROXSUITE_BUILD_VECTORIZATION=${PROXSUITE_BUILD_VECTORIZATION:=ON} +export PROXSUITE_BUILD_PYTHON_INTERFACE=${PROXSUITE_BUILD_PYTHON_INTERFACE:=OFF} +export PROXSUITE_BUILD_TESTING=${PROXSUITE_BUILD_TESTING:=ON} +export PROXSUITE_BUILD_MAROS_MESZAROS_TESTS=${PROXSUITE_BUILD_MAROS_MESZAROS_TESTS:=OFF} diff --git a/doc/2-ProxQP_api.md b/doc/2-ProxQP_api.md index c909ba29b..599c893b7 100644 --- a/doc/2-ProxQP_api.md +++ b/doc/2-ProxQP_api.md @@ -698,11 +698,11 @@ It is important to notice that some other solvers API have made different choice \subsection OverviewArchitectureOptions Architecture options when compiling ProxSuite -We highly encourage you to enable the vectorization of the underlying linear algebra for the best performance. You just need to activate the cmake option `BUILD_WITH_SIMD_SUPPORT=ON`, like: +We highly encourage you to enable the vectorization of the underlying linear algebra for the best performance. You just need to activate the cmake option `BUILD_WITH_VECTORIZATION_SUPPORT=ON`, like: \code mkdir build && cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DBUILD_WITH_SIMD_SUPPORT=ON +cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DBUILD_WITH_VECTORIZATION_SUPPORT=ON make make install \endcode diff --git a/doc/5-installation.md b/doc/5-installation.md index 67dc810af..48b22067c 100644 --- a/doc/5-installation.md +++ b/doc/5-installation.md @@ -15,16 +15,15 @@ The following dependencies are required at compile time: 1. Clone this repository with: ```bash -git clone https://github.com/Simple-Robotics/proxsuite.git --recursive +git clone https://github.com/Simple-Robotics/proxsuite.git ``` 2. Create a build tree using CMake, build and install: ```bash -mkdir build && cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -make -make install +cmake -S proxsuite -B proxsuite-build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF +cmake --build proxsuite-build +cmake --install proxsuite-build --prefix proxsuite-install ``` Note: if you are building Proxsuite within a conda environment, consider passing `-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX`. @@ -34,10 +33,9 @@ Note: if you are building Proxsuite within a conda environment, consider passing You just need to ensure that Python3 is indeed present on your system and activate the cmake option `BUILD_PYTHON_INTERFACE=ON` by replacing: ```bash -mkdir build && cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DBUILD_PYTHON_INTERFACE=ON -make -make install +cmake -S proxsuite -B proxsuite-build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DBUILD_PYTHON_INTERFACE=ON +cmake --build proxsuite-build +cmake --install proxsuite-build --prefix proxsuite-install ``` 4. Generate the doc @@ -57,10 +55,9 @@ Yet, some CPU architectures may not support such operations. You just need to deactivate the cmake option `BUILD_WITH_VECTORIZATION_SUPPORT=OFF`, like: ```bash -mkdir build && cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DBUILD_WITH_VECTORIZATION_SUPPORT=OFF -make -make install +cmake -S proxsuite -B proxsuite-build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DBUILD_WITH_VECTORIZATION_SUPPORT=OFF +cmake --build proxsuite-build +cmake --install proxsuite-build --prefix proxsuite-install ``` #### Testing diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 000000000..44995312b --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,73 @@ +# Set Doxygen module options +set(DOXYGEN_GENERATE_HTML YES) +set(DOXYGEN_GENERATE_LATEX NO) +set(DOXYGEN_QUIET YES) +set(DOXYGEN_WARN_IF_UNDOCUMENTED NO) +set(DOXYGEN_WARN_NO_PARAMDOC NO) + +if(PROXSUITE_DOXYGEN_USE_MATHJAX) + set(DOXYGEN_USE_MATHJAX YES) +endif() + +# Set Doxygen options +set( + DOXYGEN_FILE_PATTERNS + *.cc + *.cpp + *.h + *.hpp + *.dox + *.md + *.py +) +set(DOXYGEN_RECURSIVE YES) +set(DOXYGEN_SORT_MEMBER_DOCS NO) +set(DOXYGEN_SORT_BRIEF_DOCS NO) +set(DOXYGEN_SORT_MEMBERS_CTORS_1ST YES) +set(DOXYGEN_GENERATE_TESTLIST YES) +set(DOXYGEN_EXTRACT_STATIC YES) +set(DOXYGEN_EXTRACT_PRIV_VIRTUAL YES) +set(DOXYGEN_ENABLE_PREPROCESSING YES) +set(DOXYGEN_MACRO_EXPANSION YES) +set(DOXYGEN_EXPAND_ONLY_PREDEF YES) +set(DOXYGEN_PREDEFINED "EIGEN_MAKE_ALIGNED_OPERATOR_NEW") +set(DOXYGEN_FULL_PATH_NAMES YES) +set(DOXYGEN_EXCLUDE_SYMBOLS "*::internal, internal::*, *::internal::*") +set(DOXYGEN_EXCLUDE_PATTERNS "*.hxx") +set(DOXYGEN_INCLUDE_PATH ${PROJECT_SOURCE_DIR}/include) +set(DOXYGEN_EXCLUDE_SYMLINKS YES) +set(DOXYGEN_EXAMPLE_PATH ${PROJECT_SOURCE_DIR}/examples) +set(DOXYGEN_EXTRA_PACKAGES "{bm stmaryrd amsmath amssymb}") +set(DOXYGEN_GENERATE_TREEVIEW YES) +set(DOXYGEN_VERBATIM_HEADERS YES) +set(DOXYGEN_HTML_HEADER ${PROJECT_SOURCE_DIR}/doc/header.html) +set(DOXYGEN_TAGFILES "") +set(DOXYGEN_SHOW_FILES YES) +set(DOXYGEN_SHOW_NAMESPACES YES) +set(DOXYGEN_MATHJAX_FORMAT SVG) +set(DOXYGEN_SOURCE_BROWSER YES) +set(DOXYGEN_ALPHABETICAL_INDEX YES) +set(DOXYGEN_USE_MDFILE_AS_MAINPAGE ${PROJECT_SOURCE_DIR}/doc/1-Overview.md) +set(DOXYGEN_BUILTIN_STL_SUPPORT YES) +set(DOXYGEN_HAVE_DOT YES) +set(DOXYGEN_DOT_IMAGE_FORMAT SVG) +set(DOXYGEN_DOT_TRANSPARENT YES) +set(DOXYGEN_HTML_OUTPUT html) + +# Configure Doxygen +doxygen_add_docs( + proxsuite-doc + ALL + ${PROJECT_SOURCE_DIR}/doc + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/bindings/python/proxsuite + COMMENT "Generating API documentation with Doxygen" +) + +if(INSTALL_DOCUMENTATION) + install( + DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${DOXYGEN_HTML_OUTPUT} + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT doc + ) +endif() diff --git a/doc/Doxyfile.extra.in b/doc/Doxyfile.extra.in deleted file mode 100644 index 7e8e5f303..000000000 --- a/doc/Doxyfile.extra.in +++ /dev/null @@ -1,59 +0,0 @@ -INPUT = @PROJECT_SOURCE_DIR@/doc \ - @PROJECT_SOURCE_DIR@/include \ - @PROJECT_SOURCE_DIR@/bindings/python/proxsuite \ - -RECURSIVE = YES - -FILE_PATTERNS = *.cc *.cpp *.h *.hpp *.dox *.md *.py - -# Document members in declaration order -SORT_MEMBER_DOCS = NO -SORT_BRIEF_DOCS = NO -SORT_MEMBERS_CTORS_1ST = YES - -GENERATE_TESTLIST = YES -EXTRACT_STATIC = YES - -EXTRACT_PRIV_VIRTUAL = YES -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = YES -EXPAND_ONLY_PREDEF = YES -PREDEFINED += EIGEN_MAKE_ALIGNED_OPERATOR_NEW \ - -FULL_PATH_NAMES = YES -EXCLUDE_SYMBOLS = *::internal, internal::*, *::internal::* -# Do not show source files -EXCLUDE_PATTERNS = *.hxx - -INCLUDE_PATH = @PROJECT_SOURCE_DIR@/include - -EXCLUDE_SYMLINKS = YES - -EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/examples - -EXTRA_PACKAGES = bm stmaryrd amsmath amssymb - -GENERATE_TREEVIEW = YES - -VERBATIM_HEADERS = YES - - -HTML_HEADER = @PROJECT_SOURCE_DIR@/doc/header.html - - -TAGFILES = - -SHOW_FILES = YES -SHOW_NAMESPACES = YES - -MATHJAX_FORMAT = SVG - -SOURCE_BROWSER = YES - -ALPHABETICAL_INDEX = YES - -USE_MDFILE_AS_MAINPAGE = @PROJECT_SOURCE_DIR@/doc/1-Overview.md - -BUILTIN_STL_SUPPORT = YES -HAVE_DOT = YES -DOT_IMAGE_FORMAT = SVG diff --git a/doc/images/proxsuite-logo-transparent.png b/doc/images/proxsuite-logo-transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..51835c07a513cd354c71a56b7057908a86d0d505 GIT binary patch literal 67400 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 z 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%0DOQN*URPYO+lC6Xsmr~XbQugW37t%% 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 literal 67400 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 z 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%0DOQN*URPYO+lC6Xsmr~XbQugW37t%% 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" + "PYTHONPATH=$/.." +) diff --git a/examples/julia/overview-simple.jl b/examples/julia/overview-simple.jl index 163eaa445..aada706d0 100644 --- a/examples/julia/overview-simple.jl +++ b/examples/julia/overview-simple.jl @@ -1,5 +1,8 @@ import Pkg Pkg.add("PyCall") +if haskey(ENV, "PYTHON") + Pkg.build("PyCall") +end using PyCall using Printf diff --git a/examples/python/CMakeLists.txt b/examples/python/CMakeLists.txt index 31f46b63d..83d9e6f9e 100644 --- a/examples/python/CMakeLists.txt +++ b/examples/python/CMakeLists.txt @@ -1,11 +1,46 @@ -file(GLOB_RECURSE ${PROJECT_NAME}_PYTHON_EXAMPLES *.py) +add_custom_target(proxsuite-examples-python) -foreach(EXAMPLE_FILE ${${PROJECT_NAME}_PYTHON_EXAMPLES}) - get_filename_component(EXAMPLE_NAME ${EXAMPLE_FILE} NAME_WE) - string(REGEX REPLACE "${PROJECT_SOURCE_DIR}" "" EXAMPLE_FILE ${EXAMPLE_FILE}) - ADD_PYTHON_UNIT_TEST( - "${PROJECT_NAME}-example-py-${EXAMPLE_NAME}" - "${EXAMPLE_FILE}" - "bindings/python" +function(proxsuite_add_python_example name) + add_custom_target( + proxsuite-example-py-${name} + COMMAND $ ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py + DEPENDS proxsuite_pywrap ) -endforeach() + if(BUILD_TESTING) + add_test( + NAME proxsuite-example-python.${name} + COMMAND $ ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py + ) + set_tests_properties( + proxsuite-example-python.${name} + PROPERTIES + ENVIRONMENT_MODIFICATION + "PYTHONPATH=path_list_prepend:$/.." + LABELS python + ) + endif() + add_dependencies(proxsuite-examples-python proxsuite-example-py-${name}) +endfunction() + +proxsuite_add_python_example(estimate_nonconvex_eigenvalue) +proxsuite_add_python_example(init_dense_qp_with_box) +proxsuite_add_python_example(init_dense_qp_with_other_options) +proxsuite_add_python_example(init_dense_qp_with_timings) +proxsuite_add_python_example(init_dense_qp) +proxsuite_add_python_example(init_with_default_options) +proxsuite_add_python_example(initializing_with_none_without_api) +proxsuite_add_python_example(initializing_with_none) +proxsuite_add_python_example(loading_dense_qp_with_box_ineq) +proxsuite_add_python_example(loading_dense_qp_with_different_backend_choice) +proxsuite_add_python_example(loading_dense_qp) +proxsuite_add_python_example(loading_sparse_qp) +proxsuite_add_python_example(overview-simple) +proxsuite_add_python_example(qplayer_sudoku) +proxsuite_add_python_example(solve_dense_lp) +proxsuite_add_python_example(solve_dense_qp_with_setting) +proxsuite_add_python_example(solve_dense_qp) +proxsuite_add_python_example(solve_without_api_and_option) +proxsuite_add_python_example(solve_without_api) +proxsuite_add_python_example(update_dense_qp_ws_previous_result) +proxsuite_add_python_example(update_dense_qp) +proxsuite_add_python_example(update_sparse_qp) diff --git a/examples/python/estimate_nonconvex_eigenvalue.py b/examples/python/estimate_nonconvex_eigenvalue.py index 7b6ecac59..d023f845c 100644 --- a/examples/python/estimate_nonconvex_eigenvalue.py +++ b/examples/python/estimate_nonconvex_eigenvalue.py @@ -1,6 +1,6 @@ import proxsuite import numpy as np -import scipy.sparse as spa +import scipy.sparse.linalg as spla from util import generate_mixed_qp @@ -18,7 +18,7 @@ ) ) qp.init(H, g, A, b, C, l, u, manual_minimal_H_eigenvalue=estimate_minimal_eigen_value) -vals, _ = spa.linalg.eigs(H, which="SR") +vals, _ = spla.eigs(H, which="SR") min_eigenvalue = float(np.min(vals)) # print the estimates print(f"{min_eigenvalue=}") diff --git a/external/cereal b/external/cereal deleted file mode 160000 index ddd467244..000000000 --- a/external/cereal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ddd467244713ea4fe63733628992efcdd6a9187d diff --git a/flake.lock b/flake.lock index 98cd8d948..0f7b12019 100644 --- a/flake.lock +++ b/flake.lock @@ -1,15 +1,31 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1769996383, - "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", + "lastModified": 1788450739, + "narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", + "rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993", "type": "github" }, "original": { @@ -18,13 +34,282 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "gepetto", + "system-manager", + "userborn", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768135262, + "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakoboros": { + "inputs": { + "flake-parts": "flake-parts", + "nix-ros-overlay": "nix-ros-overlay", + "nixpkgs": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "nix-ros-overlay", + "nixpkgs" + ], + "systems": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "nix-ros-overlay", + "flake-utils", + "systems" + ], + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1790033047, + "narHash": "sha256-MQnxpVvB2JU26FHpSzLHBbeykxQQ1v0kiTMOgAY8P0s=", + "owner": "gepetto", + "repo": "flakoboros", + "rev": "865dc5fa218facdd8d2591267d882ca845d93a60", + "type": "github" + }, + "original": { + "owner": "gepetto", + "repo": "flakoboros", + "type": "github" + } + }, + "gazebros2nix": { + "inputs": { + "flake-parts": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "flake-parts" + ], + "flakoboros": "flakoboros", + "nix-ros-overlay": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "nix-ros-overlay" + ], + "nixpkgs": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "nixpkgs" + ], + "rosdistro": [ + "gepetto", + "gazebros2nix", + "nix-ros-overlay", + "rosdistro" + ], + "systems": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "systems" + ], + "treefmt-nix": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "treefmt-nix" + ] + }, + "locked": { + "lastModified": 1790037511, + "narHash": "sha256-rvn/mhSk9U9xz9/wrePBhLfAP08goeOJo+TB5XqIxkA=", + "owner": "gepetto", + "repo": "gazebros2nix", + "rev": "40f26646058e1d04a78bad48922aabb233efd507", + "type": "github" + }, + "original": { + "owner": "gepetto", + "repo": "gazebros2nix", + "type": "github" + } + }, + "gepetto": { + "inputs": { + "flake-parts": [ + "gepetto", + "gazebros2nix", + "flake-parts" + ], + "flakoboros": [ + "gepetto", + "gazebros2nix", + "flakoboros" + ], + "gazebros2nix": "gazebros2nix", + "home-manager": "home-manager", + "nix-ros-overlay": [ + "gepetto", + "gazebros2nix", + "nix-ros-overlay" + ], + "nix-system-graphics": "nix-system-graphics", + "nixpkgs": [ + "gepetto", + "gazebros2nix", + "nixpkgs" + ], + "nixpkgs-update": "nixpkgs-update", + "system-manager": "system-manager", + "systems": [ + "gepetto", + "gazebros2nix", + "systems" + ], + "treefmt-nix": [ + "gepetto", + "gazebros2nix", + "treefmt-nix" + ] + }, + "locked": { + "lastModified": 1790038031, + "narHash": "sha256-+pVZsxf2i9pNTs0G2O+6wusFqO47o1se0mBAfZbp1Tc=", + "owner": "gepetto", + "repo": "nix", + "rev": "658d5655ab34972c6c4fbe415b15e66a42eaf617", + "type": "github" + }, + "original": { + "owner": "gepetto", + "repo": "nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "gepetto", + "system-manager", + "userborn", + "pre-commit-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "gepetto", + "nixpkgs-update" + ] + }, + "locked": { + "lastModified": 1790021793, + "narHash": "sha256-wXAdaLBAjbQK/OfESV/i0pgolkz+Uo4SbBP/MbfGLHU=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "a3dfb887d40d134af29fa8e924ba85a3e3a99194", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nix-ros-overlay": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rosdistro": "rosdistro" + }, + "locked": { + "lastModified": 1789934487, + "narHash": "sha256-4+5xM4FuLlUd9BaqOryHIoOLP3fFJqhFCAkdtgzAftk=", + "owner": "lopsided98", + "repo": "nix-ros-overlay", + "rev": "26787be7438dca718f12f4f1d10460214f59b72b", + "type": "github" + }, + "original": { + "owner": "lopsided98", + "ref": "develop", + "repo": "nix-ros-overlay", + "type": "github" + } + }, + "nix-system-graphics": { + "inputs": { + "nixpkgs": [ + "gepetto", + "nixpkgs-update" + ] + }, + "locked": { + "lastModified": 1763296639, + "narHash": "sha256-K9JBscC7ApwCnl0wR0sVkxrKFsoDYVqXN5fOujvyBWA=", + "owner": "soupglasses", + "repo": "nix-system-graphics", + "rev": "ac37f0f3ec0cb15d63a520918433c794d01d9dac", + "type": "github" + }, + "original": { + "owner": "soupglasses", + "repo": "nix-system-graphics", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1770562336, - "narHash": "sha256-ub1gpAONMFsT/GU2hV6ZWJjur8rJ6kKxdm9IlCT0j84=", + "lastModified": 1787736819, + "narHash": "sha256-cV5xEJJK3BvhU8rEd4mC9UsmDi5qscv/kzGPhBRC5WA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d6c71932130818840fc8fe9509cf50be8c64634f", + "rev": "9fbb54b33e91ee4ca368e35a78e0613c720600b3", "type": "github" }, "original": { @@ -36,11 +321,11 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1769909678, - "narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=", + "lastModified": 1788057806, + "narHash": "sha256-DTQSMxzDWmT0zhguthvegnVkn7CFqGCv4IHCzk5ZUpM=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "72716169fe93074c333e8d0173151350670b824c", + "rev": "596e2e3940e09b2abbeb03f75fa1828c57fcd72c", "type": "github" }, "original": { @@ -49,10 +334,178 @@ "type": "github" } }, + "nixpkgs-update": { + "locked": { + "lastModified": 1789921291, + "narHash": "sha256-Ft/BRnIqw1MywFoXydKobjjWmDFgDdYtSpJliE8+yUw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "44a91898084f46797b5fac650c7e8c9ac38c43d4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": [ + "gepetto", + "system-manager", + "userborn", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "gepetto", + "system-manager", + "userborn", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769069492, + "narHash": "sha256-Efs3VUPelRduf3PpfPP2ovEB4CXT7vHf8W+xc49RL/U=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs" + "gepetto": "gepetto" + } + }, + "rosdistro": { + "flake": false, + "locked": { + "lastModified": 1789691456, + "narHash": "sha256-cN+nrUBDp0VDftxTKL6PQetPvWIp1wv+zdcl2yL3x7k=", + "owner": "ros", + "repo": "rosdistro", + "rev": "8bc9618ed66325b4f0a63699369048427e104393", + "type": "github" + }, + "original": { + "owner": "ros", + "repo": "rosdistro", + "type": "github" + } + }, + "system-manager": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "gepetto", + "nixpkgs-update" + ], + "userborn": "userborn" + }, + "locked": { + "lastModified": 1789999438, + "narHash": "sha256-Gm7Xy8QwnqGG9JFxtHrvvLo9hsCJ+VigtdiFUAKE1Tk=", + "owner": "numtide", + "repo": "system-manager", + "rev": "a92eb76cb0de5370d6a5ee12ac11b379c76d49a3", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "system-manager", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "gepetto", + "gazebros2nix", + "flakoboros", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1786901030, + "narHash": "sha256-WSFCsDSE5ffgD2MqzkM2CYjeFiKhRF/dJUN8uedb6YE=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "27b3b12a8e6375f28ebe122f07d230ca5459bbfa", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "userborn": { + "inputs": { + "flake-compat": [ + "gepetto", + "system-manager", + "flake-compat" + ], + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "gepetto", + "system-manager", + "nixpkgs" + ], + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "systems": "systems_2" + }, + "locked": { + "lastModified": 1770377964, + "narHash": "sha256-q2pnlX2IW0kg80GLFnwWd/GigIpkuZnyKPLhrgJql3E=", + "owner": "jfroche", + "repo": "userborn", + "rev": "55c2cd7952c207a62736a5bbd9499ea73da18d24", + "type": "github" + }, + "original": { + "owner": "jfroche", + "ref": "system-manager", + "repo": "userborn", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 920c5e304..fc95f7613 100644 --- a/flake.nix +++ b/flake.nix @@ -1,81 +1,58 @@ { description = "Advanced Proximal Optimization Toolbox"; - inputs = { - flake-parts.url = "github:hercules-ci/flake-parts"; - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - }; + inputs.gepetto.url = "github:gepetto/nix"; outputs = inputs: - inputs.flake-parts.lib.mkFlake { inherit inputs; } ( - { self, lib, ... }: + inputs.gepetto.lib.mkFlakoboros inputs ( + { lib, ... }: { - systems = inputs.nixpkgs.lib.systems.flakeExposed; - flake.overlays = { - default = final: prev: { - proxsuite = prev.proxsuite.overrideAttrs { - src = lib.fileset.toSource { - root = ./.; - fileset = lib.fileset.unions [ - ./benchmark - ./bindings - ./cmake-external - ./CMakeLists.txt - ./doc - ./examples - ./include - ./package.xml - ./test - ]; - }; - postPatch = ""; - }; - }; - eigen_5 = final: prev: { - eigen = final.eigen_5; - pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [ - (python-final: python-prev: { - scipy = python-prev.scipy.overrideAttrs { - # broken on linux arm - doInstallCheck = false; - }; - }) + extraDevPyPackages = [ "proxsuite" ]; + overrideAttrs.proxsuite = { drv-prev, pkgs-final, ... }: { + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./benchmark + ./bindings + ./cmake + ./CMakeLists.txt + ./doc + ./examples + ./include + ./package.xml + ./test ]; }; + patches = [ ]; + cmakeFlags = drv-prev.cmakeFlags ++ [ + (lib.cmakeBool "BUILD_TESTING" true) + (lib.cmakeBool "PROXSUITE_BUILD_EXAMPLES" true) + (lib.cmakeBool "BUILD_BENCHMARK" true) + (lib.cmakeBool "BUILD_WITH_OPENMP_SUPPORT" true) + (lib.cmakeBool "PROXSUITE_BUILD_MAROS_MESZAROS_TESTS" true) + (lib.cmakeBool "GENERATE_PYTHON_STUBS" true) + ]; + buildInputs = + drv-prev.buildInputs + ++ lib.optionals pkgs-final.stdenv.cc.isClang [ + pkgs-final.llvmPackages.openmp + ]; + checkInputs = drv-prev.checkInputs ++ [ + pkgs-final.catch2_3 + ]; }; - perSystem = - { - pkgs, - pkgs-eigen_5, - self', - system, - ... - }: - { - _module.args = { - pkgs = import inputs.nixpkgs { - inherit system; - overlays = [ self.overlays.default ]; + extends.eigen5 = final: prev: { + eigen = final.eigen_5; + pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [ + (_python-final: python-prev: { + scipy = python-prev.scipy.overrideAttrs { + # broken on linux arm + doInstallCheck = false; }; - pkgs-eigen_5 = import inputs.nixpkgs { - inherit system; - overlays = [ - self.overlays.eigen_5 - self.overlays.default - ]; - }; - }; - apps.default = { - type = "app"; - program = pkgs.python3.withPackages (_: [ self'.packages.default ]); - }; - packages = { - default = self'.packages.proxsuite; - proxsuite = pkgs.python3Packages.proxsuite; - proxsuite-eigen_5 = pkgs-eigen_5.python3Packages.proxsuite; - }; - }; + }) + ]; + }; } ); } diff --git a/include/proxsuite/helpers/tl-optional.hpp b/include/proxsuite/helpers/tl-optional.hpp deleted file mode 100644 index 65859cbb7..000000000 --- a/include/proxsuite/helpers/tl-optional.hpp +++ /dev/null @@ -1,2471 +0,0 @@ - -/// -// optional - An implementation of std::optional with extensions -// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama) -// -// Documentation available at https://tl.tartanllama.xyz/ -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to the -// public domain worldwide. This software is distributed without any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. If not, see -// . -/// - -#ifndef TL_OPTIONAL_HPP -#define TL_OPTIONAL_HPP - -#define TL_OPTIONAL_VERSION_MAJOR 1 -#define TL_OPTIONAL_VERSION_MINOR 1 -#define TL_OPTIONAL_VERSION_PATCH 0 - -#include -#include -#include -#include -#include - -#if (defined(_MSC_VER) && _MSC_VER == 1900) -#define TL_OPTIONAL_MSVC2015 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ - !defined(__clang__)) -#define TL_OPTIONAL_GCC49 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ - !defined(__clang__)) -#define TL_OPTIONAL_GCC54 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ - !defined(__clang__)) -#define TL_OPTIONAL_GCC55 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ - !defined(__clang__)) -// GCC < 5 doesn't support overloading on const&& for member functions -#define TL_OPTIONAL_NO_CONSTRR - -// GCC < 5 doesn't support some standard C++11 type traits -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ - std::has_trivial_copy_constructor::value -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ - std::has_trivial_copy_assign::value - -// This one will be different for GCC 5.7 if it's ever supported -#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \ - std::is_trivially_destructible::value - -// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks -// std::vector for non-copyable types -#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) -#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX -#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX -namespace tl { -namespace detail { -template -struct is_trivially_copy_constructible : std::is_trivially_copy_constructible -{}; -#ifdef _GLIBCXX_VECTOR -template -struct is_trivially_copy_constructible> - : std::is_trivially_copy_constructible -{}; -#endif -} -} -#endif - -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ - tl::detail::is_trivially_copy_constructible::value -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ - std::is_trivially_copy_assignable::value -#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \ - std::is_trivially_destructible::value -#else -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ - std::is_trivially_copy_constructible::value -#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ - std::is_trivially_copy_assignable::value -#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \ - std::is_trivially_destructible::value -#endif - -#if __cplusplus > 201103L -#define TL_OPTIONAL_CXX14 -#endif - -// constexpr implies const in C++11, not C++14 -#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || \ - defined(TL_OPTIONAL_GCC49)) -#define TL_OPTIONAL_11_CONSTEXPR -#else -#define TL_OPTIONAL_11_CONSTEXPR constexpr -#endif - -namespace tl { -#ifndef TL_MONOSTATE_INPLACE_MUTEX -#define TL_MONOSTATE_INPLACE_MUTEX -/// Used to represent an optional with no data; essentially a bool -class monostate -{}; - -/// A tag type to tell optional to construct its value in-place -struct in_place_t -{ - explicit in_place_t() = default; -}; -/// A tag to tell optional to construct its value in-place -static constexpr in_place_t in_place{}; -#endif - -template -class optional; - -namespace detail { -#ifndef TL_TRAITS_MUTEX -#define TL_TRAITS_MUTEX -// C++14-style aliases for brevity -template -using remove_const_t = typename std::remove_const::type; -template -using remove_reference_t = typename std::remove_reference::type; -template -using decay_t = typename std::decay::type; -template -using enable_if_t = typename std::enable_if::type; -template -using conditional_t = typename std::conditional::type; - -// std::conjunction from C++17 -template -struct conjunction : std::true_type -{}; -template -struct conjunction : B -{}; -template -struct conjunction - : std::conditional, B>::type -{}; - -#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L -#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND -#endif - -// In C++11 mode, there's an issue in libc++'s std::mem_fn -// which results in a hard-error when using it in a noexcept expression -// in some cases. This is a check to workaround the common failing case. -#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND -template -struct is_pointer_to_non_const_member_func : std::false_type -{}; -template -struct is_pointer_to_non_const_member_func : std::true_type -{}; -template -struct is_pointer_to_non_const_member_func - : std::true_type -{}; -template -struct is_pointer_to_non_const_member_func - : std::true_type -{}; -template -struct is_pointer_to_non_const_member_func - : std::true_type -{}; -template -struct is_pointer_to_non_const_member_func - : std::true_type -{}; -template -struct is_pointer_to_non_const_member_func - : std::true_type -{}; - -template -struct is_const_or_const_ref : std::false_type -{}; -template -struct is_const_or_const_ref : std::true_type -{}; -template -struct is_const_or_const_ref : std::true_type -{}; -#endif - -// std::invoke from C++17 -// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround -template< - typename Fn, - typename... Args, -#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND - typename = enable_if_t::value && - is_const_or_const_ref::value)>, -#endif - typename = enable_if_t>::value>, - int = 0> -constexpr auto -invoke(Fn&& f, Args&&... args) noexcept( - noexcept(std::mem_fn(f)(std::forward(args)...))) - -> decltype(std::mem_fn(f)(std::forward(args)...)) -{ - return std::mem_fn(f)(std::forward(args)...); -} - -template>::value>> -constexpr auto -invoke(Fn&& f, Args&&... args) noexcept( - noexcept(std::forward(f)(std::forward(args)...))) - -> decltype(std::forward(f)(std::forward(args)...)) -{ - return std::forward(f)(std::forward(args)...); -} - -// std::invoke_result from C++17 -template -struct invoke_result_impl; - -template -struct invoke_result_impl< - F, - decltype(detail::invoke(std::declval(), std::declval()...), void()), - Us...> -{ - using type = - decltype(detail::invoke(std::declval(), std::declval()...)); -}; - -template -using invoke_result = invoke_result_impl; - -template -using invoke_result_t = typename invoke_result::type; - -#if defined(_MSC_VER) && _MSC_VER <= 1900 -// TODO make a version which works with MSVC 2015 -template -struct is_swappable : std::true_type -{}; - -template -struct is_nothrow_swappable : std::true_type -{}; -#else -// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept -namespace swap_adl_tests { -// if swap ADL finds this then it would call std::swap otherwise (same -// signature) -struct tag -{}; - -template -tag -swap(T&, T&); -template -tag swap(T (&a)[N], T (&b)[N]); - -// helper functions to test if an unqualified swap is possible, and if it -// becomes std::swap -template -std::false_type -can_swap(...) noexcept(false); -template(), std::declval()))> -std::true_type -can_swap(int) noexcept(noexcept(swap(std::declval(), std::declval()))); - -template -std::false_type -uses_std(...); -template -std::is_same(), std::declval())), tag> -uses_std(int); - -template -struct is_std_swap_noexcept - : std::integral_constant::value && - std::is_nothrow_move_assignable::value> -{}; - -template -struct is_std_swap_noexcept : is_std_swap_noexcept -{}; - -template -struct is_adl_swap_noexcept - : std::integral_constant(0))> -{}; -} // namespace swap_adl_tests - -template -struct is_swappable - : std::integral_constant< - bool, - decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype(detail::swap_adl_tests::uses_std(0))::value || - (std::is_move_assignable::value && - std::is_move_constructible::value))> -{}; - -template -struct is_swappable - : std::integral_constant< - bool, - decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype(detail::swap_adl_tests::uses_std(0))::value || - is_swappable::value)> -{}; - -template -struct is_nothrow_swappable - : std::integral_constant< - bool, - is_swappable::value && - ((decltype(detail::swap_adl_tests::uses_std(0))::value && - detail::swap_adl_tests::is_std_swap_noexcept::value) || - (!decltype(detail::swap_adl_tests::uses_std(0))::value && - detail::swap_adl_tests::is_adl_swap_noexcept::value))> -{}; -#endif -#endif - -// std::void_t from C++17 -template -struct voider -{ - using type = void; -}; -template -using void_t = typename voider::type; - -// Trait for checking if a type is a tl::optional -template -struct is_optional_impl : std::false_type -{}; -template -struct is_optional_impl> : std::true_type -{}; -template -using is_optional = is_optional_impl>; - -// Change void to tl::monostate -template -using fixup_void = conditional_t::value, monostate, U>; - -template> -using get_map_return = optional>>; - -// Check if invoking F for some Us returns void -template -struct returns_void_impl; -template -struct returns_void_impl>, U...> - : std::is_void> -{}; -template -using returns_void = returns_void_impl; - -template -using enable_if_ret_void = enable_if_t::value>; - -template -using disable_if_ret_void = enable_if_t::value>; - -template -using enable_forward_value = - detail::enable_if_t::value && - !std::is_same, in_place_t>::value && - !std::is_same, detail::decay_t>::value>; - -template -using enable_from_other = - detail::enable_if_t::value && - !std::is_constructible&>::value && - !std::is_constructible&&>::value && - !std::is_constructible&>::value && - !std::is_constructible&&>::value && - !std::is_convertible&, T>::value && - !std::is_convertible&&, T>::value && - !std::is_convertible&, T>::value && - !std::is_convertible&&, T>::value>; - -template -using enable_assign_forward = detail::enable_if_t< - !std::is_same, detail::decay_t>::value && - !detail::conjunction, - std::is_same>>::value && - std::is_constructible::value && std::is_assignable::value>; - -template -using enable_assign_from_other = - detail::enable_if_t::value && - std::is_assignable::value && - !std::is_constructible&>::value && - !std::is_constructible&&>::value && - !std::is_constructible&>::value && - !std::is_constructible&&>::value && - !std::is_convertible&, T>::value && - !std::is_convertible&&, T>::value && - !std::is_convertible&, T>::value && - !std::is_convertible&&, T>::value && - !std::is_assignable&>::value && - !std::is_assignable&&>::value && - !std::is_assignable&>::value && - !std::is_assignable&&>::value>; - -// The storage base manages the actual storage, and correctly propagates -// trivial destruction from T. This case is for when T is not trivially -// destructible. -template::value> -struct optional_storage_base -{ - TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept - : m_dummy() - , m_has_value(false) - { - } - - template - TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) - : m_value(std::forward(u)...) - , m_has_value(true) - { - } - - ~optional_storage_base() - { - if (m_has_value) { - m_value.~T(); - m_has_value = false; - } - } - - struct dummy - {}; - union - { - dummy m_dummy; - T m_value; - }; - - bool m_has_value; -}; - -// This case is for when T is trivially destructible. -template -struct optional_storage_base -{ - TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept - : m_dummy() - , m_has_value(false) - { - } - - template - TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) - : m_value(std::forward(u)...) - , m_has_value(true) - { - } - - // No destructor, so this class is trivially destructible - - struct dummy - {}; - union - { - dummy m_dummy; - T m_value; - }; - - bool m_has_value = false; -}; - -// This base class provides some handy member functions which can be used in -// further derived classes -template -struct optional_operations_base : optional_storage_base -{ - using optional_storage_base::optional_storage_base; - - void hard_reset() noexcept - { - get().~T(); - this->m_has_value = false; - } - - template - void construct(Args&&... args) - { - new (std::addressof(this->m_value)) T(std::forward(args)...); - this->m_has_value = true; - } - - template - void assign(Opt&& rhs) - { - if (this->has_value()) { - if (rhs.has_value()) { - this->m_value = std::forward(rhs).get(); - } else { - this->m_value.~T(); - this->m_has_value = false; - } - } - - else if (rhs.has_value()) { - construct(std::forward(rhs).get()); - } - } - - bool has_value() const { return this->m_has_value; } - - TL_OPTIONAL_11_CONSTEXPR T& get() & { return this->m_value; } - TL_OPTIONAL_11_CONSTEXPR const T& get() const& { return this->m_value; } - TL_OPTIONAL_11_CONSTEXPR T&& get() && { return std::move(this->m_value); } -#ifndef TL_OPTIONAL_NO_CONSTRR - constexpr const T&& get() const&& { return std::move(this->m_value); } -#endif -}; - -// This class manages conditionally having a trivial copy constructor -// This specialization is for when T is trivially copy constructible -template -struct optional_copy_base : optional_operations_base -{ - using optional_operations_base::optional_operations_base; -}; - -// This specialization is for when T is not trivially copy constructible -template -struct optional_copy_base : optional_operations_base -{ - using optional_operations_base::optional_operations_base; - - optional_copy_base() = default; - optional_copy_base(const optional_copy_base& rhs) - : optional_operations_base() - { - if (rhs.has_value()) { - this->construct(rhs.get()); - } else { - this->m_has_value = false; - } - } - - optional_copy_base(optional_copy_base&& rhs) = default; - optional_copy_base& operator=(const optional_copy_base& rhs) = default; - optional_copy_base& operator=(optional_copy_base&& rhs) = default; -}; - -// This class manages conditionally having a trivial move constructor -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_constructible. We -// have to make do with a non-trivial move constructor even if T is trivially -// move constructible -#ifndef TL_OPTIONAL_GCC49 -template::value> -struct optional_move_base : optional_copy_base -{ - using optional_copy_base::optional_copy_base; -}; -#else -template -struct optional_move_base; -#endif -template -struct optional_move_base : optional_copy_base -{ - using optional_copy_base::optional_copy_base; - - optional_move_base() = default; - optional_move_base(const optional_move_base& rhs) = default; - - optional_move_base(optional_move_base&& rhs) noexcept( - std::is_nothrow_move_constructible::value) - { - if (rhs.has_value()) { - this->construct(std::move(rhs.get())); - } else { - this->m_has_value = false; - } - } - optional_move_base& operator=(const optional_move_base& rhs) = default; - optional_move_base& operator=(optional_move_base&& rhs) = default; -}; - -// This class manages conditionally having a trivial copy assignment operator -template -struct optional_copy_assign_base : optional_move_base -{ - using optional_move_base::optional_move_base; -}; - -template -struct optional_copy_assign_base : optional_move_base -{ - using optional_move_base::optional_move_base; - - optional_copy_assign_base() = default; - optional_copy_assign_base(const optional_copy_assign_base& rhs) = default; - - optional_copy_assign_base(optional_copy_assign_base&& rhs) = default; - optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) - { - this->assign(rhs); - return *this; - } - optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = - default; -}; - -// This class manages conditionally having a trivial move assignment operator -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_assignable. We have -// to make do with a non-trivial move assignment operator even if T is trivially -// move assignable -#ifndef TL_OPTIONAL_GCC49 -template::value && - std::is_trivially_move_constructible::value && - std::is_trivially_move_assignable::value> -struct optional_move_assign_base : optional_copy_assign_base -{ - using optional_copy_assign_base::optional_copy_assign_base; -}; -#else -template -struct optional_move_assign_base; -#endif - -template -struct optional_move_assign_base : optional_copy_assign_base -{ - using optional_copy_assign_base::optional_copy_assign_base; - - optional_move_assign_base() = default; - optional_move_assign_base(const optional_move_assign_base& rhs) = default; - - optional_move_assign_base(optional_move_assign_base&& rhs) = default; - - optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = - default; - - optional_move_assign_base& - operator=(optional_move_assign_base&& rhs) noexcept( - std::is_nothrow_move_constructible::value && - std::is_nothrow_move_assignable::value) - { - this->assign(std::move(rhs)); - return *this; - } -}; - -// optional_delete_ctor_base will conditionally delete copy and move -// constructors depending on whether T is copy/move constructible -template::value, - bool EnableMove = std::is_move_constructible::value> -struct optional_delete_ctor_base -{ - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = - default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = - default; -}; - -template -struct optional_delete_ctor_base -{ - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = - default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = - default; -}; - -template -struct optional_delete_ctor_base -{ - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = - default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = - default; -}; - -template -struct optional_delete_ctor_base -{ - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = - default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = - default; -}; - -// optional_delete_assign_base will conditionally delete copy and move -// constructors depending on whether T is copy/move constructible + assignable -template::value && - std::is_copy_assignable::value), - bool EnableMove = (std::is_move_constructible::value && - std::is_move_assignable::value)> -struct optional_delete_assign_base -{ - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = - default; - optional_delete_assign_base& operator=( - optional_delete_assign_base&&) noexcept = default; -}; - -template -struct optional_delete_assign_base -{ - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = - default; - optional_delete_assign_base& operator=( - optional_delete_assign_base&&) noexcept = delete; -}; - -template -struct optional_delete_assign_base -{ - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = - delete; - optional_delete_assign_base& operator=( - optional_delete_assign_base&&) noexcept = default; -}; - -template -struct optional_delete_assign_base -{ - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = - delete; - optional_delete_assign_base& operator=( - optional_delete_assign_base&&) noexcept = delete; -}; - -} // namespace detail - -/// A tag type to represent an empty optional -struct nullopt_t -{ - struct do_not_use - {}; - constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {} -}; -/// Represents an empty optional -static constexpr nullopt_t nullopt{ nullopt_t::do_not_use{}, - nullopt_t::do_not_use{} }; - -class bad_optional_access : public std::exception -{ -public: - bad_optional_access() = default; - const char* what() const noexcept { return "Optional has no value"; } -}; - -/// An optional object is an object that contains the storage for another -/// object and manages the lifetime of this contained object, if any. The -/// contained object may be initialized after the optional object has been -/// initialized, and may be destroyed before the optional object has been -/// destroyed. The initialization state of the contained object is tracked by -/// the optional object. -template -class optional - : private detail::optional_move_assign_base - , private detail::optional_delete_ctor_base - , private detail::optional_delete_assign_base -{ - using base = detail::optional_move_assign_base; - - static_assert(!std::is_same::value, - "instantiation of optional with in_place_t is ill-formed"); - static_assert(!std::is_same, nullopt_t>::value, - "instantiation of optional with nullopt_t is ill-formed"); - -public: -// The different versions for C++14 and 11 are needed because deduced return -// types are not SFINAE-safe. This provides better support for things like -// generic lambdas. C.f. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// Carries out some operation which returns an optional on the stored - /// object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - template - TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } - - template - constexpr auto and_then(F&& f) const& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr auto and_then(F&& f) const&& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } -#endif -#else - /// Carries out some operation which returns an optional on the stored - /// object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) & - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) && - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } - - template - constexpr detail::invoke_result_t and_then(F&& f) const& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr detail::invoke_result_t and_then(F&& f) const&& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } -#endif -#endif - -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & - { - return optional_map_impl(*this, std::forward(f)); - } - - template - TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && - { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto map(F&& f) const& - { - return optional_map_impl(*this, std::forward(f)); - } - - template - constexpr auto map(F&& f) const&& - { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval(), - std::declval())) - map(F&& f) & - { - return optional_map_impl(*this, std::forward(f)); - } - - template - TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl( - std::declval(), - std::declval())) - map(F&& f) && - { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(optional_map_impl(std::declval(), - std::declval())) - map(F&& f) const& - { - return optional_map_impl(*this, std::forward(f)); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr decltype(optional_map_impl(std::declval(), - std::declval())) map(F&& f) const&& - { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & - { - return optional_map_impl(*this, std::forward(f)); - } - - template - TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && - { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto transform(F&& f) const& - { - return optional_map_impl(*this, std::forward(f)); - } - - template - constexpr auto transform(F&& f) const&& - { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval(), - std::declval())) - transform(F&& f) & - { - return optional_map_impl(*this, std::forward(f)); - } - - template - TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl( - std::declval(), - std::declval())) - transform(F&& f) && - { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(optional_map_impl(std::declval(), - std::declval())) - transform(F&& f) const& - { - return optional_map_impl(*this, std::forward(f)); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr decltype(optional_map_impl(std::declval(), - std::declval())) transform(F&& f) - const&& - { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - - /// Calls `f` if the optional is empty - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & - { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & - { - return has_value() ? *this : std::forward(f)(); - } - - template* = nullptr> - optional or_else(F&& f) && - { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && - { - return has_value() ? std::move(*this) : std::forward(f)(); - } - - template* = nullptr> - optional or_else(F&& f) const& - { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& - { - return has_value() ? *this : std::forward(f)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template* = nullptr> - optional or_else(F&& f) const&& - { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional or_else(F&& f) const&& - { - return has_value() ? std::move(*this) : std::forward(f)(); - } -#endif - - /// Maps the stored value with `f` if there is one, otherwise returns `u`. - template - U map_or(F&& f, U&& u) & - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - - template - U map_or(F&& f, U&& u) && - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } - - template - U map_or(F&& f, U&& u) const& - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - U map_or(F&& f, U&& u) const&& - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } -#endif - - /// Maps the stored value with `f` if there is one, otherwise calls - /// `u` and returns the result. - template - detail::invoke_result_t map_or_else(F&& f, U&& u) & - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - - template - detail::invoke_result_t map_or_else(F&& f, U&& u) && - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } - - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const& - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const&& - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } -#endif - - /// Returns `u` if `*this` has a value, otherwise an empty optional. - template - constexpr optional::type> conjunction(U&& u) const - { - using result = optional>; - return has_value() ? result{ u } : result{ nullopt }; - } - - /// Returns `rhs` if `*this` is empty, otherwise the current value. - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & - { - return has_value() ? *this : rhs; - } - - constexpr optional disjunction(const optional& rhs) const& - { - return has_value() ? *this : rhs; - } - - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && - { - return has_value() ? std::move(*this) : rhs; - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - constexpr optional disjunction(const optional& rhs) const&& - { - return has_value() ? std::move(*this) : rhs; - } -#endif - - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & - { - return has_value() ? *this : std::move(rhs); - } - - constexpr optional disjunction(optional&& rhs) const& - { - return has_value() ? *this : std::move(rhs); - } - - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && - { - return has_value() ? std::move(*this) : std::move(rhs); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - constexpr optional disjunction(optional&& rhs) const&& - { - return has_value() ? std::move(*this) : std::move(rhs); - } -#endif - - /// Takes the value out of the optional, leaving it empty - optional take() - { - optional ret = std::move(*this); - reset(); - return ret; - } - - using value_type = T; - - /// Constructs an optional that does not contain a value. - constexpr optional() noexcept = default; - - constexpr optional(nullopt_t) noexcept {} - - /// Copy constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) = default; - - /// Move constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; - - /// Constructs the stored value in-place using the given arguments. - template - constexpr explicit optional( - detail::enable_if_t::value, in_place_t>, - Args&&... args) - : base(in_place, std::forward(args)...) - { - } - - template - TL_OPTIONAL_11_CONSTEXPR explicit optional( - detail::enable_if_t< - std::is_constructible&, Args&&...>::value, - in_place_t>, - std::initializer_list il, - Args&&... args) - { - this->construct(il, std::forward(args)...); - } - - /// Constructs the stored value with `u`. - template::value>* = nullptr, - detail::enable_forward_value* = nullptr> - constexpr optional(U&& u) - : base(in_place, std::forward(u)) - { - } - - template::value>* = nullptr, - detail::enable_forward_value* = nullptr> - constexpr explicit optional(U&& u) - : base(in_place, std::forward(u)) - { - } - - /// Converting copy constructor. - template< - class U, - detail::enable_from_other* = nullptr, - detail::enable_if_t::value>* = nullptr> - optional(const optional& rhs) - { - if (rhs.has_value()) { - this->construct(*rhs); - } - } - - template< - class U, - detail::enable_from_other* = nullptr, - detail::enable_if_t::value>* = nullptr> - explicit optional(const optional& rhs) - { - if (rhs.has_value()) { - this->construct(*rhs); - } - } - - /// Converting move constructor. - template* = nullptr, - detail::enable_if_t::value>* = nullptr> - optional(optional&& rhs) - { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - } - - template* = nullptr, - detail::enable_if_t::value>* = nullptr> - explicit optional(optional&& rhs) - { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - } - - /// Destroys the stored value if there is one. - ~optional() = default; - - /// Assignment to empty. - /// - /// Destroys the current value if there is one. - optional& operator=(nullopt_t) noexcept - { - if (has_value()) { - this->m_value.~T(); - this->m_has_value = false; - } - - return *this; - } - - /// Copy assignment. - /// - /// Copies the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - optional& operator=(const optional& rhs) = default; - - /// Move assignment. - /// - /// Moves the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - optional& operator=(optional&& rhs) = default; - - /// Assigns the stored value from `u`, destroying the old value if there was - /// one. - template* = nullptr> - optional& operator=(U&& u) - { - if (has_value()) { - this->m_value = std::forward(u); - } else { - this->construct(std::forward(u)); - } - - return *this; - } - - /// Converting copy assignment operator. - /// - /// Copies the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - template* = nullptr> - optional& operator=(const optional& rhs) - { - if (has_value()) { - if (rhs.has_value()) { - this->m_value = *rhs; - } else { - this->hard_reset(); - } - } - - else if (rhs.has_value()) { - this->construct(*rhs); - } - - return *this; - } - - // TODO check exception guarantee - /// Converting move assignment operator. - /// - /// Moves the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - template* = nullptr> - optional& operator=(optional&& rhs) - { - if (has_value()) { - if (rhs.has_value()) { - this->m_value = std::move(*rhs); - } else { - this->hard_reset(); - } - } - - else if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - - return *this; - } - - /// Constructs the value in-place, destroying the current one if there is - /// one. - template - T& emplace(Args&&... args) - { - static_assert(std::is_constructible::value, - "T must be constructible with Args"); - - *this = nullopt; - this->construct(std::forward(args)...); - return value(); - } - - template - detail::enable_if_t< - std::is_constructible&, Args&&...>::value, - T&> - emplace(std::initializer_list il, Args&&... args) - { - *this = nullopt; - this->construct(il, std::forward(args)...); - return value(); - } - - /// Swaps this optional with the other. - /// - /// If neither optionals have a value, nothing happens. - /// If both have a value, the values are swapped. - /// If one has a value, it is moved to the other and the movee is left - /// valueless. - void swap(optional& rhs) noexcept( - std::is_nothrow_move_constructible::value && - detail::is_nothrow_swappable::value) - { - using std::swap; - if (has_value()) { - if (rhs.has_value()) { - swap(**this, *rhs); - } else { - new (std::addressof(rhs.m_value)) T(std::move(this->m_value)); - this->m_value.T::~T(); - } - } else if (rhs.has_value()) { - new (std::addressof(this->m_value)) T(std::move(rhs.m_value)); - rhs.m_value.T::~T(); - } - swap(this->m_has_value, rhs.m_has_value); - } - - /// Returns a pointer to the stored value - constexpr const T* operator->() const - { - return std::addressof(this->m_value); - } - - TL_OPTIONAL_11_CONSTEXPR T* operator->() - { - return std::addressof(this->m_value); - } - - /// Returns the stored value - TL_OPTIONAL_11_CONSTEXPR T& operator*() & { return this->m_value; } - - constexpr const T& operator*() const& { return this->m_value; } - - TL_OPTIONAL_11_CONSTEXPR T&& operator*() && - { - return std::move(this->m_value); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - constexpr const T&& operator*() const&& { return std::move(this->m_value); } -#endif - - /// Returns whether or not the optional has a value - constexpr bool has_value() const noexcept { return this->m_has_value; } - - constexpr explicit operator bool() const noexcept - { - return this->m_has_value; - } - - /// Returns the contained value if there is one, otherwise throws - /// bad_optional_access - TL_OPTIONAL_11_CONSTEXPR T& value() & - { - if (has_value()) - return this->m_value; - throw bad_optional_access(); - } - TL_OPTIONAL_11_CONSTEXPR const T& value() const& - { - if (has_value()) - return this->m_value; - throw bad_optional_access(); - } - TL_OPTIONAL_11_CONSTEXPR T&& value() && - { - if (has_value()) - return std::move(this->m_value); - throw bad_optional_access(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& - { - if (has_value()) - return std::move(this->m_value); - throw bad_optional_access(); - } -#endif - - /// Returns the stored value if there is one, otherwise returns `u` - template - constexpr T value_or(U&& u) const& - { - static_assert(std::is_copy_constructible::value && - std::is_convertible::value, - "T must be copy constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - template - TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && - { - static_assert(std::is_move_constructible::value && - std::is_convertible::value, - "T must be move constructible and convertible from U"); - return has_value() ? std::move(**this) : static_cast(std::forward(u)); - } - - /// Destroys the stored value if one exists, making the optional empty - void reset() noexcept - { - if (has_value()) { - this->m_value.~T(); - this->m_has_value = false; - } - } -}; // namespace tl - -/// Compares two optional objects -template -inline constexpr bool -operator==(const optional& lhs, const optional& rhs) -{ - return lhs.has_value() == rhs.has_value() && - (!lhs.has_value() || *lhs == *rhs); -} -template -inline constexpr bool -operator!=(const optional& lhs, const optional& rhs) -{ - return lhs.has_value() != rhs.has_value() || - (lhs.has_value() && *lhs != *rhs); -} -template -inline constexpr bool -operator<(const optional& lhs, const optional& rhs) -{ - return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs); -} -template -inline constexpr bool -operator>(const optional& lhs, const optional& rhs) -{ - return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs); -} -template -inline constexpr bool -operator<=(const optional& lhs, const optional& rhs) -{ - return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs); -} -template -inline constexpr bool -operator>=(const optional& lhs, const optional& rhs) -{ - return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs); -} - -/// Compares an optional to a `nullopt` -template -inline constexpr bool -operator==(const optional& lhs, nullopt_t) noexcept -{ - return !lhs.has_value(); -} -template -inline constexpr bool -operator==(nullopt_t, const optional& rhs) noexcept -{ - return !rhs.has_value(); -} -template -inline constexpr bool -operator!=(const optional& lhs, nullopt_t) noexcept -{ - return lhs.has_value(); -} -template -inline constexpr bool -operator!=(nullopt_t, const optional& rhs) noexcept -{ - return rhs.has_value(); -} -template -inline constexpr bool -operator<(const optional&, nullopt_t) noexcept -{ - return false; -} -template -inline constexpr bool -operator<(nullopt_t, const optional& rhs) noexcept -{ - return rhs.has_value(); -} -template -inline constexpr bool -operator<=(const optional& lhs, nullopt_t) noexcept -{ - return !lhs.has_value(); -} -template -inline constexpr bool -operator<=(nullopt_t, const optional&) noexcept -{ - return true; -} -template -inline constexpr bool -operator>(const optional& lhs, nullopt_t) noexcept -{ - return lhs.has_value(); -} -template -inline constexpr bool -operator>(nullopt_t, const optional&) noexcept -{ - return false; -} -template -inline constexpr bool -operator>=(const optional&, nullopt_t) noexcept -{ - return true; -} -template -inline constexpr bool -operator>=(nullopt_t, const optional& rhs) noexcept -{ - return !rhs.has_value(); -} - -/// Compares the optional with a value. -template -inline constexpr bool -operator==(const optional& lhs, const U& rhs) -{ - return lhs.has_value() ? *lhs == rhs : false; -} -template -inline constexpr bool -operator==(const U& lhs, const optional& rhs) -{ - return rhs.has_value() ? lhs == *rhs : false; -} -template -inline constexpr bool -operator!=(const optional& lhs, const U& rhs) -{ - return lhs.has_value() ? *lhs != rhs : true; -} -template -inline constexpr bool -operator!=(const U& lhs, const optional& rhs) -{ - return rhs.has_value() ? lhs != *rhs : true; -} -template -inline constexpr bool -operator<(const optional& lhs, const U& rhs) -{ - return lhs.has_value() ? *lhs < rhs : true; -} -template -inline constexpr bool -operator<(const U& lhs, const optional& rhs) -{ - return rhs.has_value() ? lhs < *rhs : false; -} -template -inline constexpr bool -operator<=(const optional& lhs, const U& rhs) -{ - return lhs.has_value() ? *lhs <= rhs : true; -} -template -inline constexpr bool -operator<=(const U& lhs, const optional& rhs) -{ - return rhs.has_value() ? lhs <= *rhs : false; -} -template -inline constexpr bool -operator>(const optional& lhs, const U& rhs) -{ - return lhs.has_value() ? *lhs > rhs : false; -} -template -inline constexpr bool -operator>(const U& lhs, const optional& rhs) -{ - return rhs.has_value() ? lhs > *rhs : true; -} -template -inline constexpr bool -operator>=(const optional& lhs, const U& rhs) -{ - return lhs.has_value() ? *lhs >= rhs : false; -} -template -inline constexpr bool -operator>=(const U& lhs, const optional& rhs) -{ - return rhs.has_value() ? lhs >= *rhs : true; -} - -template::value>* = nullptr, - detail::enable_if_t::value>* = nullptr> -void -swap(optional& lhs, optional& rhs) noexcept(noexcept(lhs.swap(rhs))) -{ - return lhs.swap(rhs); -} - -namespace detail { -struct i_am_secret -{}; -} // namespace detail - -template< - class T = detail::i_am_secret, - class U, - class Ret = detail::conditional_t::value, - detail::decay_t, - T>> -inline constexpr optional -make_optional(U&& v) -{ - return optional(std::forward(v)); -} - -template -inline constexpr optional -make_optional(Args&&... args) -{ - return optional(in_place, std::forward(args)...); -} -template -inline constexpr optional -make_optional(std::initializer_list il, Args&&... args) -{ - return optional(in_place, il, std::forward(args)...); -} - -#if __cplusplus >= 201703L -template -optional(T) -> optional; -#endif - -/// \exclude -namespace detail { -#ifdef TL_OPTIONAL_CXX14 -template(), - *std::declval())), - detail::enable_if_t::value>* = nullptr> -constexpr auto -optional_map_impl(Opt&& opt, F&& f) -{ - return opt.has_value() - ? detail::invoke(std::forward(f), *std::forward(opt)) - : optional(nullopt); -} - -template(), - *std::declval())), - detail::enable_if_t::value>* = nullptr> -auto -optional_map_impl(Opt&& opt, F&& f) -{ - if (opt.has_value()) { - detail::invoke(std::forward(f), *std::forward(opt)); - return make_optional(monostate{}); - } - - return optional(nullopt); -} -#else -template(), - *std::declval())), - detail::enable_if_t::value>* = nullptr> - -constexpr auto -optional_map_impl(Opt&& opt, F&& f) -> optional -{ - return opt.has_value() - ? detail::invoke(std::forward(f), *std::forward(opt)) - : optional(nullopt); -} - -template(), - *std::declval())), - detail::enable_if_t::value>* = nullptr> - -auto -optional_map_impl(Opt&& opt, F&& f) -> optional -{ - if (opt.has_value()) { - detail::invoke(std::forward(f), *std::forward(opt)); - return monostate{}; - } - - return nullopt; -} -#endif -} // namespace detail - -/// Specialization for when `T` is a reference. `optional` acts similarly -/// to a `T*`, but provides more operations and shows intent more clearly. -template -class optional -{ -public: -// The different versions for C++14 and 11 are needed because deduced return -// types are not SFINAE-safe. This provides better support for things like -// generic lambdas. C.f. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - - /// Carries out some operation which returns an optional on the stored - /// object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - template - TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - template - constexpr auto and_then(F&& f) const& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr auto and_then(F&& f) const&& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } -#endif -#else - /// Carries out some operation which returns an optional on the stored - /// object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) & - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) && - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - - template - constexpr detail::invoke_result_t and_then(F&& f) const& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr detail::invoke_result_t and_then(F&& f) const&& - { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, - "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(nullopt); - } -#endif -#endif - -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & - { - return detail::optional_map_impl(*this, std::forward(f)); - } - - template - TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto map(F&& f) const& - { - return detail::optional_map_impl(*this, std::forward(f)); - } - - template - constexpr auto map(F&& f) const&& - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl( - std::declval(), - std::declval())) - map(F&& f) & - { - return detail::optional_map_impl(*this, std::forward(f)); - } - - template - TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl( - std::declval(), - std::declval())) - map(F&& f) && - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(detail::optional_map_impl(std::declval(), - std::declval())) - map(F&& f) const& - { - return detail::optional_map_impl(*this, std::forward(f)); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr decltype(detail::optional_map_impl(std::declval(), - std::declval())) map(F&& f) - const&& - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - -#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \ - !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55) - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & - { - return detail::optional_map_impl(*this, std::forward(f)); - } - - template - TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr auto transform(F&& f) const& - { - return detail::optional_map_impl(*this, std::forward(f)); - } - - template - constexpr auto transform(F&& f) const&& - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// Carries out some operation on the stored object if there is one. - template - TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl( - std::declval(), - std::declval())) - transform(F&& f) & - { - return detail::optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template auto transform(F &&f) &&; - template - TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl( - std::declval(), - std::declval())) - transform(F&& f) && - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - template - constexpr decltype(detail::optional_map_impl(std::declval(), - std::declval())) - transform(F&& f) const& - { - return detail::optional_map_impl(*this, std::forward(f)); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - constexpr decltype(detail::optional_map_impl( - std::declval(), - std::declval())) transform(F&& f) const&& - { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - - /// Calls `f` if the optional is empty - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & - { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & - { - return has_value() ? *this : std::forward(f)(); - } - - template* = nullptr> - optional or_else(F&& f) && - { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && - { - return has_value() ? std::move(*this) : std::forward(f)(); - } - - template* = nullptr> - optional or_else(F&& f) const& - { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& - { - return has_value() ? *this : std::forward(f)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template* = nullptr> - optional or_else(F&& f) const&& - { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - template* = nullptr> - optional or_else(F&& f) const&& - { - return has_value() ? std::move(*this) : std::forward(f)(); - } -#endif - - /// Maps the stored value with `f` if there is one, otherwise returns `u` - template - U map_or(F&& f, U&& u) & - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - - template - U map_or(F&& f, U&& u) && - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } - - template - U map_or(F&& f, U&& u) const& - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - U map_or(F&& f, U&& u) const&& - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u); - } -#endif - - /// Maps the stored value with `f` if there is one, otherwise calls - /// `u` and returns the result. - template - detail::invoke_result_t map_or_else(F&& f, U&& u) & - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - - template - detail::invoke_result_t map_or_else(F&& f, U&& u) && - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } - - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const& - { - return has_value() ? detail::invoke(std::forward(f), **this) - : std::forward(u)(); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const&& - { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : std::forward(u)(); - } -#endif - - /// Returns `u` if `*this` has a value, otherwise an empty optional. - template - constexpr optional::type> conjunction(U&& u) const - { - using result = optional>; - return has_value() ? result{ u } : result{ nullopt }; - } - - /// Returns `rhs` if `*this` is empty, otherwise the current value. - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & - { - return has_value() ? *this : rhs; - } - - constexpr optional disjunction(const optional& rhs) const& - { - return has_value() ? *this : rhs; - } - - TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && - { - return has_value() ? std::move(*this) : rhs; - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - constexpr optional disjunction(const optional& rhs) const&& - { - return has_value() ? std::move(*this) : rhs; - } -#endif - - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & - { - return has_value() ? *this : std::move(rhs); - } - - constexpr optional disjunction(optional&& rhs) const& - { - return has_value() ? *this : std::move(rhs); - } - - TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && - { - return has_value() ? std::move(*this) : std::move(rhs); - } - -#ifndef TL_OPTIONAL_NO_CONSTRR - constexpr optional disjunction(optional&& rhs) const&& - { - return has_value() ? std::move(*this) : std::move(rhs); - } -#endif - - /// Takes the value out of the optional, leaving it empty - optional take() - { - optional ret = std::move(*this); - reset(); - return ret; - } - - using value_type = T&; - - /// Constructs an optional that does not contain a value. - constexpr optional() noexcept - : m_value(nullptr) - { - } - - constexpr optional(nullopt_t) noexcept - : m_value(nullptr) - { - } - - /// Copy constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) noexcept = default; - - /// Move constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; - - /// Constructs the stored value with `u`. - template>::value>* = nullptr> - constexpr optional(U&& u) noexcept - : m_value(std::addressof(u)) - { - static_assert(std::is_lvalue_reference::value, "U must be an lvalue"); - } - - template - constexpr explicit optional(const optional& rhs) noexcept - : optional(*rhs) - { - } - - /// No-op - ~optional() = default; - - /// Assignment to empty. - /// - /// Destroys the current value if there is one. - optional& operator=(nullopt_t) noexcept - { - m_value = nullptr; - return *this; - } - - /// Copy assignment. - /// - /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise - /// resets the stored value in `*this`. - optional& operator=(const optional& rhs) = default; - - /// Rebinds this optional to `u`. - template>::value>* = nullptr> - optional& operator=(U&& u) - { - static_assert(std::is_lvalue_reference::value, "U must be an lvalue"); - m_value = std::addressof(u); - return *this; - } - - /// Converting copy assignment operator. - /// - /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise - /// resets the stored value in `*this`. - template - optional& operator=(const optional& rhs) noexcept - { - m_value = std::addressof(rhs.value()); - return *this; - } - - /// Rebinds this optional to `u`. - template>::value>* = nullptr> - optional& emplace(U&& u) noexcept - { - return *this = std::forward(u); - } - - void swap(optional& rhs) noexcept { std::swap(m_value, rhs.m_value); } - - /// Returns a pointer to the stored value - constexpr const T* operator->() const noexcept { return m_value; } - - TL_OPTIONAL_11_CONSTEXPR T* operator->() noexcept { return m_value; } - - /// Returns the stored value - TL_OPTIONAL_11_CONSTEXPR T& operator*() noexcept { return *m_value; } - - constexpr const T& operator*() const noexcept { return *m_value; } - - constexpr bool has_value() const noexcept { return m_value != nullptr; } - - constexpr explicit operator bool() const noexcept - { - return m_value != nullptr; - } - - /// Returns the contained value if there is one, otherwise throws - /// bad_optional_access - TL_OPTIONAL_11_CONSTEXPR T& value() - { - if (has_value()) - return *m_value; - throw bad_optional_access(); - } - TL_OPTIONAL_11_CONSTEXPR const T& value() const - { - if (has_value()) - return *m_value; - throw bad_optional_access(); - } - - /// Returns the stored value if there is one, otherwise returns `u` - template - constexpr T value_or(U&& u) const& noexcept - { - static_assert(std::is_copy_constructible::value && - std::is_convertible::value, - "T must be copy constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// \group value_or - template - TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && noexcept - { - static_assert(std::is_move_constructible::value && - std::is_convertible::value, - "T must be move constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// Destroys the stored value if one exists, making the optional empty - void reset() noexcept { m_value = nullptr; } - -private: - T* m_value; -}; // namespace tl - -} // namespace tl - -namespace std { -// TODO SFINAE -template -struct hash> -{ - ::std::size_t operator()(const tl::optional& o) const - { - if (!o.has_value()) - return 0; - - return std::hash>()(*o); - } -}; -} // namespace std - -#endif diff --git a/include/proxsuite/linalg/sparse/factorize.hpp b/include/proxsuite/linalg/sparse/factorize.hpp index 225a82f7b..78ade7863 100644 --- a/include/proxsuite/linalg/sparse/factorize.hpp +++ b/include/proxsuite/linalg/sparse/factorize.hpp @@ -392,7 +392,7 @@ ereach(usize& count, usize(len) * sizeof(I)); // move down the top of the stack - top = util::wrapping_plus(top, -len); + top -= len; } for (usize q = top; q < n; ++q) { diff --git a/include/proxsuite/linalg/veg/tuple.hpp b/include/proxsuite/linalg/veg/tuple.hpp index 6e7dc1ca2..a3ad0e3e7 100644 --- a/include/proxsuite/linalg/veg/tuple.hpp +++ b/include/proxsuite/linalg/veg/tuple.hpp @@ -754,16 +754,9 @@ struct cat proxsuite::linalg::veg::meta::false_type /*unused*/, Tuples&&... tups) VEG_NOEXCEPT -> Concat { -#if defined(_MSC_VER) || (defined(__clang__) && __clang_major__ >= 19) || \ - (defined(__APPLE__) && defined(__clang__) && __clang_major__ >= 17) return cat::from_ref_to_result( Tag>{}, cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); -#else - return cat::template from_ref_to_result( - Tag>{}, - cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); -#endif } template diff --git a/include/proxsuite/linalg/veg/type_traits/constructible.hpp b/include/proxsuite/linalg/veg/type_traits/constructible.hpp index a0ad2772f..d8813dc11 100644 --- a/include/proxsuite/linalg/veg/type_traits/constructible.hpp +++ b/include/proxsuite/linalg/veg/type_traits/constructible.hpp @@ -21,7 +21,7 @@ VEG_DEF_CONCEPT_FROM_BUILTIN_OR_STD(typename T, empty, T); VEG_DEF_CONCEPT(typename T, nothrow_destructible, - noexcept(static_cast(nullptr)->~T())); + std::is_nothrow_destructible::value); VEG_DEF_CONCEPT(typename T, trivially_destructible, diff --git a/include/proxsuite/proxqp/dense/backward_data.hpp b/include/proxsuite/proxqp/dense/backward_data.hpp index 7ebe8734b..00f6aefbd 100644 --- a/include/proxsuite/proxqp/dense/backward_data.hpp +++ b/include/proxsuite/proxqp/dense/backward_data.hpp @@ -8,7 +8,6 @@ #define PROXSUITE_PROXQP_DENSE_BACKWARD_DATA_HPP #include -#include #include "proxsuite/linalg/veg/type_traits/core.hpp" #include "proxsuite/proxqp/dense/fwd.hpp" diff --git a/include/proxsuite/proxqp/dense/solver.hpp b/include/proxsuite/proxqp/dense/solver.hpp index 336393dba..294cb98f3 100644 --- a/include/proxsuite/proxqp/dense/solver.hpp +++ b/include/proxsuite/proxqp/dense/solver.hpp @@ -650,7 +650,7 @@ Martinez_update(const Settings& qpsettings, ) { - bcl_eta_in = std::max(bcl_eta_in * 0.1, eps_in_min); + bcl_eta_in = std::max(bcl_eta_in * T(0.1), eps_in_min); if (primal_feasibility_lhs_new <= 0.95 * primal_feasibility_lhs_old) { /* TO PUT IN DEBUG MODE if (qpsettings.verbose) { diff --git a/include/proxsuite/proxqp/sparse/workspace.hpp b/include/proxsuite/proxqp/sparse/workspace.hpp index 5d763e3ad..5bc485dcf 100644 --- a/include/proxsuite/proxqp/sparse/workspace.hpp +++ b/include/proxsuite/proxqp/sparse/workspace.hpp @@ -491,12 +491,12 @@ struct Workspace } } - auto lnnz = isize(zero_extend(ldl.col_ptrs[n_tot])); + const auto local_lnnz = isize(zero_extend(ldl.col_ptrs[n_tot])); // if ldlt is too sparse - // do_ldlt = !overflow && lnnz < (10000000); + // do_ldlt = !overflow && local_lnnz < (10000000); if (settings.sparse_backend == SparseBackend::Automatic) { - do_ldlt = !overflow && lnnz < 10000000; + do_ldlt = !overflow && local_lnnz < 10000000; } else if (settings.sparse_backend == SparseBackend::SparseCholesky) { do_ldlt = true; } else { diff --git a/include/proxsuite/proxqp/utils/random_qp_problems.hpp b/include/proxsuite/proxqp/utils/random_qp_problems.hpp index e08641d47..9c83a5597 100644 --- a/include/proxsuite/proxqp/utils/random_qp_problems.hpp +++ b/include/proxsuite/proxqp/utils/random_qp_problems.hpp @@ -12,6 +12,11 @@ #include #include #include +#include + +#if defined(_MSC_VER) +#include +#endif namespace proxsuite { namespace proxqp { @@ -67,41 +72,11 @@ namespace rand { using proxqp::u32; using proxqp::u64; -#ifdef _MSC_VER -/* Using the MSCV compiler on Windows causes problems because the type uint128 -is not available. Therefore, we use a random number generator from the stdlib -instead of our custom Lehmer random number generator. The necessary lehmer -functions used in in our code are remplaced with calls to the stdlib.*/ -std::mt19937 gen(1234); -std::uniform_real_distribution<> uniform_dist(0.0, 1.0); -std::normal_distribution normal_dist; -using u128 = u64; -inline auto -uniform_rand() -> double -{ - double output = double(uniform_dist(gen)); - return output; -} -inline auto -lehmer_global() -> u128& -{ - static u64 output = gen(); - return output; -} - -inline void -set_seed(u64 seed) -{ - gen.seed(seed); -} - -inline auto -normal_rand() -> double -{ - return normal_dist(gen); -} +#if defined(_MSC_VER) +using u128 = uint128_t; #else using u128 = __uint128_t; +#endif constexpr u128 lehmer64_constant(0xda942042e4dd58b5); inline auto @@ -145,7 +120,6 @@ normal_rand() -> double return sqrt * std::cos(pi2 * u2); } -#endif template auto @@ -297,7 +271,7 @@ sparse_positive_definite_rand_compressed(isize n, Scalar rho, Scalar p) H_dense.template selfadjointView().eigenvalues(); Scalar min = eigh.minCoeff(); for (isize i = 0; i < n; ++i) { - H.coeffRef(i, i) += (rho + abs(min)); + H.coeffRef(i, i) += (rho + std::fabs(min)); } H.makeCompressed(); @@ -328,7 +302,7 @@ sparse_positive_definite_rand_not_compressed(isize n, Scalar rho, Scalar p) // H.array() /= 2.; Vec eigh = H.template selfadjointView().eigenvalues(); Scalar min = eigh.minCoeff(); - H.diagonal().array() += (rho + abs(min)); + H.diagonal().array() += (rho + std::fabs(min)); return H; } diff --git a/include/proxsuite/proxqp/utils/uint128_msvc.hpp b/include/proxsuite/proxqp/utils/uint128_msvc.hpp new file mode 100644 index 000000000..4a96c3366 --- /dev/null +++ b/include/proxsuite/proxqp/utils/uint128_msvc.hpp @@ -0,0 +1,234 @@ +// +// Copyright (c) 2026 INRIA +// +// This helper implements uint128 on msvc. +// NOTE: Meant for testing purposes only, NOT for production use. + +#pragma once + +#if !defined(_MSC_VER) +#error "This file is only compatible with the MSVC compiler" +#endif + +#if !defined(_M_X64) && !defined(_M_AMD64) +#error "This file requires x64 architecture" +#endif + +#include +#include +#include +#include + +class uint128_t +{ +public: + uint64_t low = 0; + uint64_t high = 0; + + constexpr uint128_t(uint64_t l) + : low(l) + , high(0) + { + } + constexpr uint128_t(uint64_t l, uint64_t h) + : low(l) + , high(h) + { + } + + // --- Type Conversions --- + constexpr explicit operator bool() const { return low || high; } + constexpr explicit operator uint64_t() const { return low; } + constexpr explicit operator int64_t() const + { + return static_cast(low); + } + + // --- Arithmetic Operators --- + + uint128_t operator+(const uint128_t& rhs) const + { + uint128_t result = 0; + const unsigned char carry = _addcarry_u64(0, low, rhs.low, &result.low); + std::ignore = _addcarry_u64(carry, high, rhs.high, &result.high); + return result; + } + + uint128_t& operator+=(const uint128_t& rhs) + { + *this = *this + rhs; + return *this; + } + + uint128_t operator-(const uint128_t& rhs) const + { + uint128_t result = 0; + const unsigned char borrow = _subborrow_u64(0, low, rhs.low, &result.low); + _subborrow_u64(borrow, high, rhs.high, &result.high); + return result; + } + + uint128_t& operator-=(const uint128_t& rhs) + { + *this = *this - rhs; + return *this; + } + + uint128_t operator*(const uint128_t& rhs) const + { + uint64_t product_high = 0; + const uint64_t product_low = _umul128(low, rhs.low, &product_high); + product_high += (low * rhs.high) + (high * rhs.low); + return uint128_t(product_low, product_high); + } + + uint128_t& operator*=(const uint128_t& rhs) + { + *this = *this * rhs; + return *this; + } + + // Division by a 64-bit divisor uses _udiv128. For a full 128-bit divisor, + // falls back to binary long division. + uint128_t operator/(const uint128_t& rhs) const + { + if (!rhs) { + throw std::domain_error("uint128 division by zero"); + } + if (rhs.high == 0) { + if (high > 0) { + const uint64_t quotient_high = high / rhs.low; + const uint64_t r_high = high % rhs.low; + uint64_t remainder = 0; + const uint64_t quotient_low = + _udiv128(r_high, low, rhs.low, &remainder); + return uint128_t(quotient_low, quotient_high); + } + return uint128_t(low / rhs.low, 0); + } + // Binary long division for 128-bit divisor + if (rhs > *this) + return uint128_t(0); + if (rhs == *this) + return uint128_t(1); + + uint128_t temp = *this; + uint128_t quot = 0; + while (temp >= rhs) { + uint128_t shift_rhs = rhs; + uint128_t shift_count = 1; + while ((shift_rhs.high & 0x8000000000000000) == 0 && + (shift_rhs << 1) <= temp) { + shift_rhs <<= 1; + shift_count <<= 1; + } + temp -= shift_rhs; + quot += shift_count; + } + return quot; + } + + uint128_t operator%(const uint128_t& rhs) const + { + return *this - (*this / rhs) * rhs; + } + + uint128_t& operator%=(const uint128_t& rhs) + { + *this = *this % rhs; + return *this; + } + + // --- Bitwise Operators --- + constexpr uint128_t operator<<(int32_t shift) const + { + shift &= 127; // wrap modulo 128, matching hardware behavior + if (shift == 0) + return *this; + if (shift >= 64) { + return uint128_t(0, low << (shift - 64)); + } + return uint128_t((low << shift), (high << shift) | (low >> (64 - shift))); + } + + constexpr uint128_t operator>>(int32_t shift) const + { + shift &= 127; // wrap modulo 128, matching hardware behavior + if (shift == 0) + return *this; + if (shift >= 64) { + return uint128_t(high >> (shift - 64), 0); + } + return uint128_t((low >> shift) | (high << (64 - shift)), (high >> shift)); + } + + // --- Shift by uint128_t Overloads --- + constexpr uint128_t operator>>(const uint128_t& shift) const + { + return *this >> static_cast(shift.low & 127u); + } + + constexpr uint128_t operator<<(const uint128_t& shift) const + { + return *this << static_cast(shift.low & 127u); + } + + constexpr uint128_t& operator<<=(int32_t shift) + { + *this = *this << shift; + return *this; + } + constexpr uint128_t& operator>>=(int32_t shift) + { + *this = *this >> shift; + return *this; + } + + constexpr uint128_t& operator<<=(const uint128_t& shift) + { + *this = *this << shift; + return *this; + } + constexpr uint128_t& operator>>=(const uint128_t& shift) + { + *this = *this >> shift; + return *this; + } + + constexpr uint128_t operator|(const uint128_t& rhs) const + { + return uint128_t(low | rhs.low, high | rhs.high); + } + constexpr uint128_t operator&(const uint128_t& rhs) const + { + return uint128_t(low & rhs.low, high & rhs.high); + } + constexpr uint128_t operator^(const uint128_t& rhs) const + { + return uint128_t(low ^ rhs.low, high ^ rhs.high); + } + constexpr uint128_t operator~() const { return uint128_t(~low, ~high); } + + // --- Comparison Operators --- + constexpr bool operator==(const uint128_t& rhs) const + { + return low == rhs.low && high == rhs.high; + } + constexpr bool operator!=(const uint128_t& rhs) const + { + return !(*this == rhs); + } + constexpr bool operator<(const uint128_t& rhs) const + { + return high < rhs.high || (high == rhs.high && low < rhs.low); + } + constexpr bool operator>(const uint128_t& rhs) const { return rhs < *this; } + constexpr bool operator<=(const uint128_t& rhs) const + { + return !(*this > rhs); + } + constexpr bool operator>=(const uint128_t& rhs) const + { + return !(*this < rhs); + } +}; diff --git a/package.xml b/package.xml index 4d9f4f2e5..ecf3b8748 100644 --- a/package.xml +++ b/package.xml @@ -23,15 +23,18 @@ https://github.com/Simple-Robotics/proxsuite https://github.com/Simple-Robotics/proxsuite/issues + python3-dev git doxygen + libcereal-dev + graphviz eigen simde - python-numpy - python3-numpy - python-scipy - python3-scipy + python3-numpy + python3-scipy + matio + catch2 catkin diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 000000000..a9bfc6481 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,11190 @@ +version: 7 +platforms: +- name: linux-64 + virtual-packages: + - __unix=0=0 + - __linux=4.18 + - __glibc=2.28 + - __archspec=0=x86_64 +- name: osx-64 + virtual-packages: + - __unix=0=0 + - __osx=13.0 + - __archspec=0=x86_64 +- name: osx-arm64 + virtual-packages: + - __unix=0=0 + - __osx=13.0 + - __archspec=0=m1 +- name: win-64 + virtual-packages: + - __win=10.0 + - __archspec=0=x86_64 +environments: + all-clang: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.46.1-default_h4852527_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/catch2-3.16.0-h4dbf13b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ccache-4.14.1-h420ae53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-23-23.1.2-default_hfab3205_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-23.1.2-default_cfg_hc1abcf6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-scan-deps-23.1.2-default_h0acdd01_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang_impl_linux-64-23.1.2-default_he0f7a93_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clangxx-23.1.2-default_cfg_hbe11dda_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clangxx_impl_linux-64-23.1.2-default_h165e814_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.4.4-hff7ac6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-23.1.2-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/compiler-rt23-23.1.2-h7148c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.3.0-h8846f6e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-2.0.0-hdab9b82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-5.0.1-h19c2612_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.3.0-h6ad849d_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.3.0-h90d9265_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-11_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-11_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp23.1-23.1.2-default_h0acdd01_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-23.1.2-default_hfab3205_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcompiler-rt-23.1.2-h7148c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.22.0-ha042cf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhiredis-1.3.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-11_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm23-23.1.3-h474f4eb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.30-he0a2e19_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.34-pthreads_hf13c14d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.23.1-hd9e3e90_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.3.0-h54950a5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hf3af7cc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-h7df9aa5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lld-23.1.2-h5985d43_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-23.1.2-h7148c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.3-py314hd3a7d6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.1-py314h36f0660_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hec8ed23_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_linux-64-23.1.2-h0e38de2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-23.1.2-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.3.0-h2b852eb_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.3.0-hb2c5482_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-64-21.1.8-h8d5f570_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-1.0.0-h87af9f7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-1.0.2-had63097_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-1.0.0-h71a5ee5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-1.0.0-h3af93c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-1.0.0-he02826c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-1.0.0-h704dcf7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/catch2-3.16.0-h66869c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ccache-4.14.1-hfd753c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm21_1_he201b2c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm21_1_hd9d6719_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-4.4.4-haddf760_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt21-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-2.0.0-h94bea0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-5.0.1-h8a113fb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-2.2.0-nompi_ha76ad8a_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h69064fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm21_1_h2eed689_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm21_1_hb373d2a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libaec-1.1.5-he7c3a48_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-11_he492b99_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-11_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp21.1-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.22.0-h5318221_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-21.1.8-h7c275be_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20260512-pl5321hba2e2ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-16.2.0-h13771c8_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-16.2.0-h7e5c614_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-16.2.0-h2539e6c_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libhiredis-1.3.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-11_h859234e_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm21-21.1.8-hd11396f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.3-hd11396f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.30-ha0ad728_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.34-openmp_h5c7ac21_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpsl-0.23.1-h7ff43d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hd53bb72_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h8376fb4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-hb56241c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lld-23.1.2-h9313d6c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21-21.1.8-h36529c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21.1.8-h8c1e6b9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.13.2-hebe015c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.5.3-py314he0ba898_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.6-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/s2n-1.7.7-h6035f5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.18.1-py314hefcf020_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simde-0.8.2-h37c8870_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xxhash-0.8.3-hd5b56d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-arm64-21.1.8-hb8825d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-1.0.0-h7ad4001_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-1.0.2-h74c22ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-1.0.0-h7b2e6b5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-1.0.0-h49e100f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-1.0.0-hffd187b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-1.0.0-h50d513f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/catch2-3.16.0-hfbe1efa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ccache-4.14.1-h0e49cae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm21_1_h8e84c17_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm21_1_h2e2604f_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.4.4-hf91ab31_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt21-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-2.0.0-he3883d0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-5.0.1-hdb59ae0_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-2.2.0-nompi_h9376f17_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm21_1_h5d6df6c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm21_1_h1a10cc4_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-11_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-11_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp21.1-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.22.0-h6651222_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-21.1.8-h6dc3340_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20260512-pl5321h26f1114_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhiredis-1.3.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-11_hd9741b5_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm21-21.1.8-h759d1ac_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.3-h759d1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmatio-1.5.30-h41674cd_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.34-openmp_h5e6e99c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpsl-0.23.1-hdb0c161_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-hbf2880b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lld-23.1.2-h98a3de6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21-21.1.8-h79441dc_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21.1.8-hdb3d66b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h3feff0a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.3-py314he06036b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/s2n-1.7.7-h430f396_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.18.1-py314hd9f3d4e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simde-0.8.2-h7b3277c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xxhash-0.8.3-h579eaed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_win-64-22.1.8-h49e36cd_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-ha8204d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/catch2-3.16.0-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ccache-4.14.1-h7fd822b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-22-22.1.8-default_hac490eb_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-22.1.8-default_nocfg_hbb9487a_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clangxx-22.1.8-default_nocfg_hbb9487a_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.4.4-hde52c71_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/compiler-rt22-22.1.8-h49e36cd_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-2.0.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/eigen-5.0.1-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_hae35d4c_110.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libaec-1.1.5-haf901d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-11_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-11_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.22.0-hdb0ef4a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhiredis-1.3.0-he0c23c2_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.15.0-default_hae90fe0_1001.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-11_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libllvm22-22.1.8-h830ff33_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmatio-1.5.30-hbeb426f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpsl-0.23.1-h9b16d47_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.8-h4f90d01_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h734d217_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.52.1-h6a83c73_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lld-23.1.2-he13e66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-tools-22.1.8-he5be12e_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_235.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.5.3-py314h02f10f6_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.8-h53f6dd8_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.18.1-py314h67d5eaa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simde-0.8.2-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.1.0-h272cf33_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xxhash-0.8.3-h39ac402_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + clang: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.46.1-default_h4852527_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/catch2-3.16.0-h4dbf13b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ccache-4.14.1-h420ae53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-23-23.1.2-default_hfab3205_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-23.1.2-default_cfg_hc1abcf6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-scan-deps-23.1.2-default_h0acdd01_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang_impl_linux-64-23.1.2-default_he0f7a93_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clangxx-23.1.2-default_cfg_hbe11dda_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clangxx_impl_linux-64-23.1.2-default_h165e814_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.4.4-hff7ac6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-23.1.2-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/compiler-rt23-23.1.2-h7148c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.3.0-h8846f6e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-2.0.0-hdab9b82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-5.0.1-h19c2612_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.3.0-h6ad849d_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.3.0-h90d9265_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-11_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-11_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp23.1-23.1.2-default_h0acdd01_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-23.1.2-default_hfab3205_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcompiler-rt-23.1.2-h7148c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.22.0-ha042cf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhiredis-1.3.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-11_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm23-23.1.3-h474f4eb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.30-he0a2e19_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.34-pthreads_hf13c14d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.23.1-hd9e3e90_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.3.0-h54950a5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hf3af7cc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-h7df9aa5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lld-23.1.2-h5985d43_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-23.1.2-h7148c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.3-py314hd3a7d6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.1-py314h36f0660_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hec8ed23_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_linux-64-23.1.2-h0e38de2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-23.1.2-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.3.0-h2b852eb_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.3.0-hb2c5482_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_osx-64-23.1.2-h8d5f570_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-23.1.2-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-23.1.3-h707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sdkroot_env_osx-64-26.0-h62b880e_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-1.0.0-h87af9f7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-1.0.2-had63097_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-1.0.0-h71a5ee5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-1.0.0-h3af93c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-1.0.0-he02826c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-1.0.0-h704dcf7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/binutils-1.0.1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/catch2-3.16.0-h66869c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ccache-4.14.1-hfd753c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm23_1_h254e556_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-1030.6.3-llvm23_1_h254e556_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-23-23.1.2-default_h3065a3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-23.1.2-default_cfg_hcbdff81_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_osx-64-23.1.2-h11c87bf_34.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-23.1.2-default_cfg_h2b485f0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-23.1.2-default_hf9996f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-23.1.2-h11c87bf_34.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-4.4.4-haddf760_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-23.1.2-h694c41f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt23-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.0.1-h04f5b5a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-5.0.1-h8a113fb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-2.2.0-nompi_ha76ad8a_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h69064fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm23_1_h0b736ef_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm23_1_h484b24f_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libaec-1.1.5-he7c3a48_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-11_he492b99_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-11_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.22.0-h5318221_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-23.1.3-h7c275be_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20260512-pl5321hba2e2ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-16.2.0-h13771c8_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-16.2.0-h7e5c614_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-16.2.0-h2539e6c_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libhiredis-1.3.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-11_h859234e_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.2-hd11396f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.30-ha0ad728_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.34-openmp_h5c7ac21_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpsl-0.23.1-h7ff43d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hd53bb72_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h8376fb4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-hb56241c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lld-23.1.2-h9313d6c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23-23.1.2-h36529c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.13.2-hebe015c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.5.3-py314he0ba898_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.6-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/s2n-1.7.7-h6035f5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.18.1-py314hefcf020_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simde-0.8.2-h37c8870_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xxhash-0.8.3-hd5b56d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-arm64-21.1.8-hb8825d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-1.0.0-h7ad4001_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-1.0.2-h74c22ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-1.0.0-h7b2e6b5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-1.0.0-h49e100f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-1.0.0-hffd187b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-1.0.0-h50d513f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/catch2-3.16.0-hfbe1efa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ccache-4.14.1-h0e49cae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm21_1_h8e84c17_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm21_1_h2e2604f_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.4.4-hf91ab31_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt21-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-2.0.0-he3883d0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-5.0.1-hdb59ae0_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-2.2.0-nompi_h9376f17_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm21_1_h5d6df6c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm21_1_h1a10cc4_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-11_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-11_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp21.1-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.22.0-h6651222_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-21.1.8-h6dc3340_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20260512-pl5321h26f1114_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhiredis-1.3.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-11_hd9741b5_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm21-21.1.8-h759d1ac_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.3-h759d1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmatio-1.5.30-h41674cd_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.34-openmp_h5e6e99c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpsl-0.23.1-hdb0c161_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-hbf2880b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lld-23.1.2-h98a3de6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21-21.1.8-h79441dc_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21.1.8-hdb3d66b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h3feff0a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.3-py314he06036b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/s2n-1.7.7-h430f396_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.18.1-py314hd9f3d4e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simde-0.8.2-h7b3277c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xxhash-0.8.3-h579eaed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_win-64-22.1.8-h49e36cd_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-ha8204d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/catch2-3.16.0-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ccache-4.14.1-h7fd822b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-22-22.1.8-default_hac490eb_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-22.1.8-default_nocfg_hbb9487a_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clangxx-22.1.8-default_nocfg_hbb9487a_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.4.4-hde52c71_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/compiler-rt22-22.1.8-h49e36cd_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-2.0.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/eigen-5.0.1-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_hae35d4c_110.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libaec-1.1.5-haf901d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-11_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-11_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.22.0-hdb0ef4a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhiredis-1.3.0-he0c23c2_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.15.0-default_hae90fe0_1001.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-11_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libllvm22-22.1.8-h830ff33_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmatio-1.5.30-hbeb426f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpsl-0.23.1-h9b16d47_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.8-h4f90d01_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h734d217_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.52.1-h6a83c73_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lld-23.1.2-he13e66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-tools-22.1.8-he5be12e_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_235.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.5.3-py314h02f10f6_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.8-h53f6dd8_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.18.1-py314h67d5eaa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simde-0.8.2-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.1.0-h272cf33_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xxhash-0.8.3-h39ac402_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/catch2-3.16.0-h4dbf13b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ccache-4.14.1-h420ae53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.4.4-hff7ac6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.3.0-h8846f6e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-2.0.0-hdab9b82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-5.0.1-h19c2612_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.3.0-h6ad849d_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.3.0-h90d9265_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-11_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-11_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.22.0-ha042cf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhiredis-1.3.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-11_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.30-he0a2e19_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.34-pthreads_hf13c14d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.23.1-hd9e3e90_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.3.0-h54950a5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.3-py314hd3a7d6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.1-py314h36f0660_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hec8ed23_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.3.0-h2b852eb_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.3.0-hb2c5482_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-64-21.1.8-h8d5f570_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-1.0.0-h87af9f7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-1.0.2-had63097_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-1.0.0-h71a5ee5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-1.0.0-h3af93c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-1.0.0-he02826c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-1.0.0-h704dcf7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/catch2-3.16.0-h66869c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ccache-4.14.1-hfd753c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm21_1_he201b2c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm21_1_hd9d6719_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-4.4.4-haddf760_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt21-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-2.0.0-h94bea0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-5.0.1-h8a113fb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-2.2.0-nompi_ha76ad8a_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h69064fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm21_1_h2eed689_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm21_1_hb373d2a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libaec-1.1.5-he7c3a48_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-11_he492b99_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-11_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp21.1-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.22.0-h5318221_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-21.1.8-h7c275be_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20260512-pl5321hba2e2ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-16.2.0-h13771c8_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-16.2.0-h7e5c614_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-16.2.0-h2539e6c_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libhiredis-1.3.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-11_h859234e_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm21-21.1.8-hd11396f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.3-hd11396f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.30-ha0ad728_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.34-openmp_h5c7ac21_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpsl-0.23.1-h7ff43d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hd53bb72_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h8376fb4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-hb56241c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21-21.1.8-h36529c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21.1.8-h8c1e6b9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.13.2-hebe015c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.5.3-py314he0ba898_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.6-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/s2n-1.7.7-h6035f5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.18.1-py314hefcf020_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simde-0.8.2-h37c8870_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xxhash-0.8.3-hd5b56d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-arm64-21.1.8-hb8825d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-1.0.0-h7ad4001_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-1.0.2-h74c22ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-1.0.0-h7b2e6b5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-1.0.0-h49e100f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-1.0.0-hffd187b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-1.0.0-h50d513f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/catch2-3.16.0-hfbe1efa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ccache-4.14.1-h0e49cae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm21_1_h8e84c17_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm21_1_h2e2604f_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.4.4-hf91ab31_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt21-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-2.0.0-he3883d0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-5.0.1-hdb59ae0_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-2.2.0-nompi_h9376f17_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm21_1_h5d6df6c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm21_1_h1a10cc4_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-11_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-11_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp21.1-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.22.0-h6651222_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-21.1.8-h6dc3340_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20260512-pl5321h26f1114_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhiredis-1.3.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-11_hd9741b5_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm21-21.1.8-h759d1ac_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.3-h759d1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmatio-1.5.30-h41674cd_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.34-openmp_h5e6e99c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpsl-0.23.1-hdb0c161_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-hbf2880b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21-21.1.8-h79441dc_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21.1.8-hdb3d66b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h3feff0a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.3-py314he06036b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/s2n-1.7.7-h430f396_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.18.1-py314hd9f3d4e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simde-0.8.2-h7b3277c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xxhash-0.8.3-h579eaed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-ha8204d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/catch2-3.16.0-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ccache-4.14.1-h7fd822b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.4.4-hde52c71_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-2.0.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/eigen-5.0.1-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_hae35d4c_110.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libaec-1.1.5-haf901d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-11_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-11_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.22.0-hdb0ef4a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhiredis-1.3.0-he0c23c2_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.15.0-default_hae90fe0_1001.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-11_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmatio-1.5.30-hbeb426f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpsl-0.23.1-h9b16d47_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.8-h4f90d01_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h734d217_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.52.1-h6a83c73_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_235.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.5.3-py314h02f10f6_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.8-h53f6dd8_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.18.1-py314h67d5eaa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simde-0.8.2-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.1.0-h272cf33_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xxhash-0.8.3-h39ac402_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + doc: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.6-h3c89d7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ccache-4.14.1-h420ae53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.4.4-hff7ac6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.3.0-h8846f6e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-2.0.0-hdab9b82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-he8c428d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.18.0-py310hb664d3d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-5.0.1-h19c2612_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/epoxy-1.5.10-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.3-h4db4eae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.17-h7cc23a3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.3.0-h6ad849d_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.8-h68053f1_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.90.0-h3d503d9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.15-h54a6638_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.52-ha5ea40c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.3.0-h90d9265_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.6.0-ha770c72_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.2.0-hdb68285_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.22.0-ha042cf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-hd45a770_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.129-h7cc23a3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h5e6c136_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgd-2.3.3-h5fbf134_12.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.90.0-h569388d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-14.6.0-h23af247_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-devel-14.6.0-h23af247_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhiredis-1.3.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.59-h922cc85_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.23.1-hd9e3e90_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.62.4-ha427ee3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.3.0-h54950a5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.2.0-hdf11a46_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.2-hcc2c06a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-hb83e432_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.13.2-h51789e4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hf3af7cc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-h7df9aa5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.58.2-h7bb47b9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-h8b3dc9c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-h7cc23a3_1004.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.26.0-hc1c935e_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.48-h280c20c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-h280c20c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-h0d788c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-h7cc23a3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.7-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-h7cc23a3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxinerama-1.1.6-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-h7cc23a3_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.7-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xorgproto-2025.1-hebe6cf0_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hec8ed23_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-51.0-unix_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.3.0-h2b852eb_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.3.0-hb2c5482_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-51.0-unix_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-64-21.1.8-h8d5f570_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cairo-1.18.6-h5791faa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ccache-4.14.1-hfd753c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm21_1_he201b2c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm21_1_hd9d6719_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-4.4.4-haddf760_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt21-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-2.0.0-h94bea0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.18.0-py310h9e984d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-5.0.1-h8a113fb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/epoxy-1.5.10-h8616949_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fontconfig-2.18.3-h7f3b9c9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.14.3-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.17-hd115831_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.8-ha3e70bd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.90.0-he718cb3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.15-h2fb4741_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gtk3-3.24.52-hf2d442a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gts-0.7.6-h53e17e3_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/harfbuzz-14.6.0-h694c41f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h69064fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm21_1_h2eed689_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm21_1_hb373d2a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.2.0-h35c7297_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp21.1-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.22.0-h5318221_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-21.1.8-h7c275be_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.25-h7ad9622_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20260512-pl5321hba2e2ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.3-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype6-2.14.3-h8afe040_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgd-2.3.3-hb2c11ec_12.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.90.0-h7e55108_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libharfbuzz-14.6.0-h2974713_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libharfbuzz-devel-14.6.0-h2974713_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libhiredis-1.3.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h98e67c8_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.2.0-ha1e9b39_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm21-21.1.8-hd11396f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.3-hd11396f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.59-h4382c61_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpsl-0.23.1-h7ff43d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/librsvg-2.62.4-h43ae438_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hd53bb72_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.2-h01c3a8c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb276fe9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h8376fb4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-hb56241c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21-21.1.8-h36529c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21.1.8-h8c1e6b9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.13.2-hebe015c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pango-1.58.2-hc5a6962_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pcre2-10.47-h31793e3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pixman-0.46.4-h2fb4741_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.6-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simde-0.8.2-h37c8870_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xxhash-0.8.3-hd5b56d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-51.0-unix_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-arm64-21.1.8-hb8825d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.6-h580cee5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ccache-4.14.1-h0e49cae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm21_1_h8e84c17_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm21_1_h2e2604f_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.4.4-hf91ab31_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt21-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-2.0.0-he3883d0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.18.0-py310h3226bdb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-5.0.1-hdb59ae0_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/epoxy-1.5.10-hc919400_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.18.3-h81aa574_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.14.3-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.17-hb001647_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gdk-pixbuf-2.44.8-h5867e2c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.90.0-h06d1d6c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.15-h784d473_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gtk3-3.24.52-hc0f3e19_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gts-0.7.6-he42f4ea_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/harfbuzz-14.6.0-hce30654_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hicolor-icon-theme-0.17-hce30654_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm21_1_h5d6df6c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm21_1_h1a10cc4_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.2.0-h1eee2c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp21.1-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.22.0-h6651222_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-21.1.8-h6dc3340_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-he7e0567_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20260512-pl5321h26f1114_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.3-h2ed5691_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgd-2.3.3-h05bcc79_12.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.90.0-hccd281b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libharfbuzz-14.6.0-hcda0f7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libharfbuzz-devel-14.6.0-hcda0f7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhiredis-1.3.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-hae62183_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.2.0-h84a0fba_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm21-21.1.8-h759d1ac_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.3-h759d1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.59-hf5e6511_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpsl-0.23.1-hdb0c161_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/librsvg-2.62.4-hc8ac265_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-hbf2880b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.2-hf67920b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h202fb40_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21-21.1.8-h79441dc_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21.1.8-hdb3d66b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h3feff0a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pango-1.58.2-hf9b25ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.47-he63d830_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.4-h784d473_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simde-0.8.2-h7b3277c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xxhash-0.8.3-h579eaed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-ha8204d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cairo-1.18.6-h477c42c_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ccache-4.14.1-h7fd822b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.4.4-hde52c71_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-2.0.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.18.0-py312pl5321h3ecd741_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/eigen-5.0.1-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fontconfig-2.18.3-hd47e2ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fribidi-1.0.17-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/getopt-win32-0.1-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/graphite2-1.3.15-h5112557_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/graphviz-14.1.2-h4c50273_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gts-0.7.6-h6b5321d_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lerc-4.2.0-hd936e49_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.22.0-hdb0ef4a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libdeflate-1.25-h1a1d4e4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype-2.14.3-h57928b3_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype6-2.14.3-hdbac1cb_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgcc-16.2.0-h110b43a_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgd-2.3.3-h4974f7c_12.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libglib-2.90.0-ha564072_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgomp-16.2.0-h8ee18e1_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libharfbuzz-14.6.0-h03b5201_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhiredis-1.3.0-he0c23c2_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libintl-0.22.5-h5728263_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libjpeg-turbo-3.2.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.59-hdc8cecf_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpsl-0.23.1-h9b16d47_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h734d217_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libtiff-4.7.2-h8f73337_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.52.1-h6a83c73_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxcb-1.17.0-h874e120_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pango-1.58.2-h13911b6_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pcre2-10.47-h8466c1e_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pixman-0.46.4-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pthread-stubs-0.4-hfa92662_1004.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simde-0.8.2-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libice-1.1.2-hd74fcf3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libsm-1.2.6-hd74fcf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libx11-1.8.13-hfa52320_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxau-1.0.12-hfa92662_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxdmcp-1.1.5-hfa92662_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxext-1.3.7-hfa92662_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxpm-3.5.19-hba3369d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxt-1.3.1-hfa92662_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xxhash-0.8.3-h39ac402_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + lint: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.1.1-py314h8d76f0c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py314h9891dd4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-hebe6cf0_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.12.3-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.6.1-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.14.5-pyh5ded981_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.12.3-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.6.1-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.14.5-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.1.1-py314h0656537_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_103.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py314h10d0514_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.1.0-py314h473ef84_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-had63097_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.12.3-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.6.1-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.14.5-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.1.1-py314h618e29d_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_103.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.1.0-py314h6cfcd04_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h74c22ad_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-4.0.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.20-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.12.3-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.6.1-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.14.5-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.1.1-py314h5a2d7ad_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.8-h4f90d01_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.8-h53f6dd8_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py314h909e829_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + maros-meszaros: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/catch2-3.16.0-h4dbf13b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ccache-4.14.1-h420ae53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.4.4-hff7ac6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.3.0-h8846f6e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-2.0.0-hdab9b82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-5.0.1-h19c2612_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.3.0-h6ad849d_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.3.0-h90d9265_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-11_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-11_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.22.0-ha042cf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhiredis-1.3.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-11_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.30-he0a2e19_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.34-pthreads_hf13c14d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.23.1-hd9e3e90_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.3.0-h54950a5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.3-py314hd3a7d6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.1-py314h36f0660_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hec8ed23_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.3.0-h2b852eb_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.3.0-hb2c5482_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-64-21.1.8-h8d5f570_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-1.0.0-h87af9f7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-1.0.2-had63097_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-1.0.0-h71a5ee5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-1.0.0-h3af93c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-1.0.0-he02826c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-1.0.0-h704dcf7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/catch2-3.16.0-h66869c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ccache-4.14.1-hfd753c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm21_1_he201b2c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm21_1_hd9d6719_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-4.4.4-haddf760_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt21-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-2.0.0-h94bea0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-5.0.1-h8a113fb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-2.2.0-nompi_ha76ad8a_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h69064fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm21_1_h2eed689_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm21_1_hb373d2a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libaec-1.1.5-he7c3a48_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-11_he492b99_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-11_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp21.1-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.22.0-h5318221_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-21.1.8-h7c275be_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20260512-pl5321hba2e2ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-16.2.0-h13771c8_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-16.2.0-h7e5c614_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-16.2.0-h2539e6c_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libhiredis-1.3.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-11_h859234e_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm21-21.1.8-hd11396f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.3-hd11396f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.30-ha0ad728_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.34-openmp_h5c7ac21_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpsl-0.23.1-h7ff43d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hd53bb72_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h8376fb4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-hb56241c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21-21.1.8-h36529c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21.1.8-h8c1e6b9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.13.2-hebe015c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.5.3-py314he0ba898_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.6-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/s2n-1.7.7-h6035f5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.18.1-py314hefcf020_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simde-0.8.2-h37c8870_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xxhash-0.8.3-hd5b56d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-arm64-21.1.8-hb8825d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-1.0.0-h7ad4001_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-1.0.2-h74c22ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-1.0.0-h7b2e6b5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-1.0.0-h49e100f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-1.0.0-hffd187b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-1.0.0-h50d513f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/catch2-3.16.0-hfbe1efa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ccache-4.14.1-h0e49cae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm21_1_h8e84c17_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm21_1_h2e2604f_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.4.4-hf91ab31_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt21-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-2.0.0-he3883d0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-5.0.1-hdb59ae0_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-2.2.0-nompi_h9376f17_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm21_1_h5d6df6c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm21_1_h1a10cc4_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-11_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-11_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp21.1-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.22.0-h6651222_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-21.1.8-h6dc3340_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20260512-pl5321h26f1114_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhiredis-1.3.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-11_hd9741b5_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm21-21.1.8-h759d1ac_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.3-h759d1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmatio-1.5.30-h41674cd_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.34-openmp_h5e6e99c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpsl-0.23.1-hdb0c161_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-hbf2880b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21-21.1.8-h79441dc_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21.1.8-hdb3d66b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h3feff0a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.3-py314he06036b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/s2n-1.7.7-h430f396_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.18.1-py314hd9f3d4e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simde-0.8.2-h7b3277c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xxhash-0.8.3-h579eaed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-ha8204d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/catch2-3.16.0-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ccache-4.14.1-h7fd822b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.4.4-hde52c71_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-2.0.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/eigen-5.0.1-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_hae35d4c_110.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libaec-1.1.5-haf901d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-11_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-11_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.22.0-hdb0ef4a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhiredis-1.3.0-he0c23c2_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.15.0-default_hae90fe0_1001.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-11_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmatio-1.5.30-hbeb426f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpsl-0.23.1-h9b16d47_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.8-h4f90d01_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h734d217_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.52.1-h6a83c73_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_235.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.5.3-py314h02f10f6_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.8-h53f6dd8_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.18.1-py314h67d5eaa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simde-0.8.2-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.1.0-h272cf33_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xxhash-0.8.3-h39ac402_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + new-version: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py314hfe1a184_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-parser-0.9.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-scripts-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ruamel.yaml-0.19.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.15.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-parser-0.9.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-scripts-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ruamel.yaml-0.19.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.15.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_103.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.15-py314h17af80e_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-parser-0.9.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-scripts-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ruamel.yaml-0.19.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.15.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_103.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.15-py314hd98292b_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-parser-0.9.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-scripts-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ruamel.yaml-0.19.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.15.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.8-h4f90d01_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.8-h53f6dd8_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py314hc5dbbe4_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + python-oldest: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/catch2-3.16.0-h4dbf13b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ccache-4.14.1-h420ae53_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.4.4-hff7ac6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.3.0-h8846f6e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-2.0.0-hdab9b82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-5.0.1-h19c2612_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.3.0-h6ad849d_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.3.0-hc6a0c74_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.3.0-h90d9265_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-11_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-11_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.22.0-ha042cf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhiredis-1.3.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-11_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.30-he0a2e19_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.34-pthreads_hf13c14d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.23.1-hd9e3e90_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.3.0-h54950a5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.38-h280c20c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.22-h267e890_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.15.2-py310h1d65ade_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h84d6215_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hec8ed23_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.3.0-h2b852eb_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.3.0-hb2c5482_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-9_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-64-21.1.8-h8d5f570_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-9_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-1.0.0-h87af9f7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-1.0.2-had63097_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-1.0.0-h71a5ee5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-1.0.0-h3af93c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-1.0.0-he02826c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-1.0.0-h704dcf7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-1.0.0-h704dcf7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/catch2-3.16.0-h66869c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ccache-4.14.1-hfd753c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm21_1_he201b2c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm21_1_hd9d6719_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-21.1.8-default_cfg_he3ef750_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-21.1.8-default_ha1a018a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-4.4.4-haddf760_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-21.1.8-h694c41f_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt21-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-2.0.0-h94bea0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-5.0.1-h8a113fb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-2.2.0-nompi_ha76ad8a_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h69064fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm21_1_h2eed689_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm21_1_hb373d2a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libaec-1.1.5-he7c3a48_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-11_he492b99_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-11_h9b27e0a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp21.1-21.1.8-default_h0a1f3f9_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-21.1.8-h8c1e6b9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.22.0-h5318221_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-21.1.8-h7c275be_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20260512-pl5321hba2e2ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-16.2.0-h13771c8_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-16.2.0-h7e5c614_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-16.2.0-h2539e6c_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libhiredis-1.3.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-11_h859234e_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm21-21.1.8-hd11396f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.3-hd11396f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.30-ha0ad728_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.34-openmp_h5c7ac21_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libpsl-0.23.1-h7ff43d8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hd53bb72_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h8376fb4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-hb56241c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21-21.1.8-h36529c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21.1.8-h8c1e6b9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.13.2-hebe015c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.2.6-py310h07c5b4d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.22-hea035f4_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.6-ha1e9b39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/s2n-1.7.7-h6035f5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.15.2-py310hef62574_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simde-0.8.2-h37c8870_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xxhash-0.8.3-hd5b56d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-arm64-21.1.8-hb8825d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-9_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-8_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-1.0.0-h7ad4001_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-1.0.2-h74c22ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-1.0.0-h7b2e6b5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-1.0.0-h49e100f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-1.0.0-hffd187b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-1.0.0-h50d513f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-1.0.0-h50d513f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/catch2-3.16.0-hfbe1efa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ccache-4.14.1-h0e49cae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm21_1_h8e84c17_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm21_1_h2e2604f_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-21.1.8-default_cfg_h7f0254a_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.4.4-hf91ab31_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-21.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt21-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-2.0.0-he3883d0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-5.0.1-hdb59ae0_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-2.2.0-nompi_h9376f17_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm21_1_h5d6df6c_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm21_1_h1a10cc4_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-11_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-11_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp21.1-21.1.8-default_h4399b93_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-21.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.22.0-h6651222_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-21.1.8-h6dc3340_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20260512-pl5321h26f1114_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhiredis-1.3.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-11_hd9741b5_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm21-21.1.8-h759d1ac_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.3-h759d1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmatio-1.5.30-h41674cd_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.34-openmp_h5e6e99c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpsl-0.23.1-hdb0c161_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_102.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-hbf2880b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21-21.1.8-h79441dc_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21.1.8-hdb3d66b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h3feff0a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.2.6-py310h4d83441_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.22-hac0b6dc_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/s2n-1.7.7-h430f396_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.15.2-py310h32ab4ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simde-0.8.2-h7b3277c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xxhash-0.8.3-h579eaed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-ha8204d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-9_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/catch2-3.16.0-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ccache-4.14.1-h7fd822b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.4.4-hde52c71_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-2.0.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/eigen-5.0.1-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_hae35d4c_110.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libaec-1.1.5-haf901d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-11_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-11_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.22.0-hdb0ef4a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhiredis-1.3.0-he0c23c2_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.15.0-default_hae90fe0_1001.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-11_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmatio-1.5.30-hbeb426f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpsl-0.23.1-h9b16d47_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h734d217_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.52.1-h6a83c73_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_235.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.2.6-py310h4987827_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.10.22-hc20f281_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.15.2-py310h15c175c_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simde-0.8.2-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.1.0-h272cf33_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xxhash-0.8.3-h39ac402_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 28948 + timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-atk-2.38.0-h0630a04_3.tar.bz2 + sha256: 26ab9386e80bf196e51ebe005da77d57decf6d989b4f34d96130560bc133479c + md5: 6b889f174df1e0f816276ae69281af4d + depends: + - at-spi2-core >=2.40.0,<2.41.0a0 + - atk-1.0 >=2.36.0 + - dbus >=1.13.6,<2.0a0 + - libgcc-ng >=9.3.0 + - libglib >=2.68.1,<3.0a0 + license: LGPL-2.1-or-later + license_family: LGPL + run_exports: + weak: + - at-spi2-atk >=2.38.0,<3.0a0 + size: 339899 + timestamp: 1619122953439 +- conda: https://conda.anaconda.org/conda-forge/linux-64/at-spi2-core-2.40.3-h0630a04_0.tar.bz2 + sha256: c4f9b66bd94c40d8f1ce1fad2d8b46534bdefda0c86e3337b28f6c25779f258d + md5: 8cb2fc4cd6cc63f1369cfa318f581cc3 + depends: + - dbus >=1.13.6,<2.0a0 + - libgcc-ng >=9.3.0 + - libglib >=2.68.3,<3.0a0 + - xorg-libx11 + - xorg-libxi + - xorg-libxtst + license: LGPL-2.1-or-later + license_family: LGPL + run_exports: + weak: + - at-spi2-core >=2.40.3,<2.41.0a0 + size: 658390 + timestamp: 1625848454791 +- conda: https://conda.anaconda.org/conda-forge/linux-64/atk-1.0-2.38.0-h04ea711_2.conda + sha256: df682395d05050cd1222740a42a551281210726a67447e5258968dd55854302e + md5: f730d54ba9cd543666d7220c9f7ed563 + depends: + - libgcc-ng >=12 + - libglib >=2.80.0,<3.0a0 + - libstdcxx-ng >=12 + constrains: + - atk-1.0 2.38.0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - atk-1.0 >=2.38.0 + size: 355900 + timestamp: 1713896169874 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.46.1-default_h4852527_102.conda + sha256: 659c367ef49df7741749a2ad240b007d7df51b4f210505a78543deafb001e44c + md5: e8452fe381cac5fff20563a07722dfa5 + depends: + - binutils_impl_linux-64 >=2.46.1,<2.46.2.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 35399 + timestamp: 1784214547142 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + sha256: fb7bf36984a37ce7e4714d1d1da0bd0e3bfc679520f5cdc184afc676fd4b5da2 + md5: a0c5e0b7f58c8ceeb08e5bc41251d5a2 + depends: + - ld_impl_linux-64 2.46.1 default_hbd61a6d_102 + - sysroot_linux-64 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 3713752 + timestamp: 1784214522814 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + sha256: 1a0d382c515ebf55f8ee1f38c8b81bc95af5c2acc42ad53b66bc5df932032f96 + md5: e675fabcf81499adc7edf58124fb1e01 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 257808 + timestamp: 1785906269155 +- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.8-hebe6cf0_2.conda + sha256: 9c37cc233238adf366ea75b0e845662a5be07ceadf62e458183516369340274b + md5: 3ad2b403be8fc5612b9159e2ce621f69 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: + weak: + - c-ares >=1.34.8,<2.0a0 + size: 228700 + timestamp: 1787169971173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.6-h3c89d7e_0.conda + sha256: 5d0efc6f9981468aca72897460d9b2d17b74dff72787f20a9d2330e214064515 + md5: 7920701f9abcb488411495742cf365a7 + depends: + - __glibc >=2.17,<3.0.a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.3,<79.0a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=15 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libstdcxx >=15 + - libxcb >=1.17.0,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - pixman >=0.46.4,<1.0a0 + - xorg-libice >=1.1.2,<2.0a0 + - xorg-libsm >=1.2.6,<2.0a0 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxrender >=0.9.12,<0.10.0a0 + license: LGPL-2.1-only or MPL-1.1 + run_exports: + weak: + - cairo >=1.18.6,<2.0a0 + size: 1007110 + timestamp: 1790045358757 +- conda: https://conda.anaconda.org/conda-forge/linux-64/catch2-3.16.0-h4dbf13b_0.conda + sha256: 2912874e38b635b89db9bbecb284f13ae449a6c3925a28a87f78b23e4730d767 + md5: ff146041192f4d830974030bdec19f86 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + license: BSL-1.0 + run_exports: + weak: + - catch2 >=3.16.0,<4.0a0 + size: 659129 + timestamp: 1787658434406 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ccache-4.14.1-h420ae53_0.conda + sha256: 8909d6a9b913c1ea2525185d373a4a9d9c529fd9c81b19fc9347021554b89ad9 + md5: 4b6ec9356481745d37486201e071b7ac + depends: + - libstdcxx >=15 + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + - libhiredis >=1.3.0,<1.4.0a0 + - xxhash >=0.8.3,<0.8.4.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 880094 + timestamp: 1790515418700 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.1.1-py314h8d76f0c_3.conda + sha256: 15e38176fa2173e063a19dad3d55746ac4c757b028813380d7f22c42781af4c4 + md5: ee66d46f7693fdcbaa1761fb8a4f6c3d + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 307262 + timestamp: 1788485305536 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clang-23-23.1.2-default_hfab3205_0.conda + sha256: 86a6c2e8d77a1c07905623c4decaa2304a27a55ea7fa39a2ce338f911104f799 + md5: b67150987226220dcb9b2f66a146d2b2 + depends: + - compiler-rt23 ==23.1.2 + - libclang-cpp23.1 ==23.1.2 default_h0acdd01_0 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libclang-cpp23.1 >=23.1.2,<23.2.0a0 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 973937 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clang-23.1.2-default_cfg_hc1abcf6_0.conda + sha256: ebf8acd24c828fffb3cd66580e534abdd62894a596c60c9f4cbcfb8f899f8627 + md5: d45fce9ef3bba711703c9961151223ba + depends: + - clang-23 ==23.1.2 default_hfab3205_0 + - llvm-openmp >=23.1.2 + - clang_impl_linux-64 ==23.1.2 default_he0f7a93_0 + - binutils + - libgcc-devel_linux-64 + - sysroot_linux-64 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 34053 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clang-scan-deps-23.1.2-default_h0acdd01_0.conda + sha256: 7c8a8382a7ab32f731302d1af010e73329cdac9ad29fa2d77c3a5048307c9308 + md5: 84b2c7a5d5e0fe4ec4f857f54f9016ea + depends: + - libclang13 >=23.1.2 + - libclang-cpp23.1 >=23.1.2,<23.2.0a0 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 112152 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clang_impl_linux-64-23.1.2-default_he0f7a93_0.conda + sha256: c88b4669209d93a93738ba7a1c59518a2cbefd9498dbfc873e9f5ce2fbc7991a + md5: 4d58d731440b3751115d47dae87f4632 + depends: + - clang-23 ==23.1.2 default_hfab3205_0 + - compiler-rt_linux-64 ==23.1.2 + - compiler-rt ==23.1.2 + - binutils_impl_linux-64 + - libgcc-devel_linux-64 + - sysroot_linux-64 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 33704 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clangxx-23.1.2-default_cfg_hbe11dda_0.conda + sha256: ed8eb86f603e9d7283f0afd680239f492ca5677a46e9f05d4d3506351e505707 + md5: 8a0ef84a8f0511977ee657bf664b5aa1 + depends: + - clang ==23.1.2 default_cfg_hc1abcf6_0 + - clangxx_impl_linux-64 ==23.1.2 default_* + - libstdcxx-devel_linux-64 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 34193 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clangxx_impl_linux-64-23.1.2-default_h165e814_0.conda + sha256: 878904b19bfa0ae7ffeccac551336609af19adf1ce8f74feb7f0e965fec9bde3 + md5: 069b2761c372bc9428032e92a9407ae8 + depends: + - clang-23 ==23.1.2 default_hfab3205_0 + - clang_impl_linux-64 ==23.1.2 default_he0f7a93_0 + - clang-scan-deps ==23.1.2 default_h0acdd01_0 + - libstdcxx-devel_linux-64 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 33787 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.4.4-hff7ac6b_0.conda + sha256: 1c04749bc4a45d5712ba81d7bf38204f6f3a53803b8c223571e7a0a1e1dbbebf + md5: f58ffc242c3ecbf9753d1f7dc6b91276 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + - ncurses >=6.6,<7.0a0 + - libexpat >=2.8.5,<3.0a0 + - libcurl >=8.22.0,<9.0a0 + - rhash >=1.4.6,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libuv >=1.52.1,<2.0a0 + - bzip2 >=1.0.8,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 26080138 + timestamp: 1791001096509 +- conda: https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-23.1.2-ha770c72_0.conda + sha256: 11b5fcbfdc088c370c5120ac758593905aca71ac2b511912fc60d9e6595bb709 + md5: d3c40459de39dab509062d8be7e31fc0 + depends: + - compiler-rt23 23.1.2 h7148c6a_0 + - libcompiler-rt 23.1.2 h7148c6a_0 + constrains: + - clang 23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16621 + timestamp: 1790196197180 +- conda: https://conda.anaconda.org/conda-forge/linux-64/compiler-rt23-23.1.2-h7148c6a_0.conda + sha256: 3b59755649409e7d61a92233ba1be11880c1d7071796ef8713f4f8be2f3aa645 + md5: 4bf9de220f59de2e26733a8e7677d86d + depends: + - __glibc >=2.17,<3.0.a0 + - compiler-rt23_linux-64 23.1.2.* + - libgcc >=15 + - libstdcxx >=15 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 116754 + timestamp: 1790196196369 +- conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.3.0-h8846f6e_7.conda + sha256: 395a5928fc78e8545afdb4e9bf074cf90e37ff8287a1f34cd98c9350da6c3095 + md5: da715e003b8f6e6737923cda77f67dbf + depends: + - gcc_impl_linux-64 >=15.3.0,<15.3.1.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 32760 + timestamp: 1790302817774 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-2.0.0-hdab9b82_0.conda + sha256: 384ab445d260e0d69e701c32eb0ed870d348ec7e3efc78d944823855d4512ca1 + md5: 923dacbfd97122c65c97a35f6e959ab8 + depends: + - gxx 15.* + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 6972 + timestamp: 1786642183694 +- conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-he8c428d_2.conda + sha256: 87a0a42d4ccc527597eff3234509dfb03e0d9bf67d5e2b6fc758e2ef389d8abe + md5: a6eb37b51be1a9a654dc3a8aca039b1a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + - libexpat >=2.8.1,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - libglib >=2.88.3,<3.0a0 + license: AFL-2.1 OR GPL-2.0-or-later + run_exports: + weak: + - dbus >=1.16.2,<2.0a0 + size: 449564 + timestamp: 1788197922783 +- conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.18.0-py310hb664d3d_0.conda + sha256: aa8efe84767d1f628f439749df5bd1d369cad6ef1a6cc2922ffc75238e62f07a + md5: 13974bf5357b9bb5ecab0a09fd06d144 + depends: + - libiconv + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libiconv >=1.18,<2.0a0 + license: GPL-2.0-only + license_family: GPL + run_exports: {} + size: 14579949 + timestamp: 1788247237167 +- conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-5.0.1-h19c2612_3.conda + sha256: e134dba3ad3523573d5902ff1222a4033372089ea31efa99e6adaf0aa18f904a + md5: cf1f7131e9055f06f07a834091f44ca4 + license: MPL-2.0 + license_family: MOZILLA + run_exports: {} + size: 1311719 + timestamp: 1788951264833 +- conda: https://conda.anaconda.org/conda-forge/linux-64/epoxy-1.5.10-hb03c661_2.conda + sha256: a5b51e491fec22bcc1765f5b2c8fff8a97428e9a5a7ee6730095fb9d091b0747 + md5: 057083b06ccf1c2778344b6dabace38b + depends: + - __glibc >=2.17,<3.0.a0 + - libdrm >=2.4.125,<2.5.0a0 + - libegl >=1.7.0,<2.0a0 + - libegl-devel + - libgcc >=14 + - libgl >=1.7.0,<2.0a0 + - libgl-devel + - libglx >=1.7.0,<2.0a0 + - libglx-devel + - xorg-libx11 >=1.8.12,<2.0a0 + - xorg-libxdamage >=1.1.6,<2.0a0 + - xorg-libxext >=1.3.6,<2.0a0 + - xorg-libxfixes >=6.0.1,<7.0a0 + - xorg-libxxf86vm >=1.1.6,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - epoxy >=1.5.10,<1.6.0a0 + size: 411735 + timestamp: 1758743520805 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.3-h4db4eae_1.conda + sha256: 5a3eb10b18a97223ab06b3a7f0d7f56658db2f2800e2f2af95836fe3bf55ba63 + md5: 922776b528a470ab5afa81fd42abfa1d + depends: + - __glibc >=2.17,<3.0.a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=15 + - libuuid >=2.42.2,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + size: 296288 + timestamp: 1786667377340 +- conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_2.conda + sha256: 612a8e0c1a6ecae23da54d81ef395f6ebb5c8e4468ec2611593ebce75876a4e0 + md5: 2d0ea23b23603e07ca47f23f949f67b6 + depends: + - libfreetype 2.14.3 ha770c72_2 + - libfreetype6 2.14.3 h5e6c136_2 + license: GPL-2.0-only OR FTL + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + size: 175239 + timestamp: 1786641011029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.17-h7cc23a3_0.conda + sha256: 3ba79ebfbd14ca5db4affaf10ee8001064e907de5baabc2dbe5bcd9aec856c9f + md5: f9d5302bca196ee87e62f393f2626562 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: LGPL-2.1-or-later + run_exports: + weak: + - fribidi >=1.0.17,<2.0a0 + size: 64102 + timestamp: 1790011855888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.3.0-hc6a0c74_7.conda + sha256: f362d14caab740de46f60d5ca8a4340066704ff573bc0a618030ceca3a2b7f87 + md5: f86312df66bf0d79961e8e185e4f9957 + depends: + - conda-gcc-specs + - gcc_impl_linux-64 15.3.0 h6ad849d_7 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 29624 + timestamp: 1790302921468 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.3.0-h6ad849d_7.conda + sha256: 3c6deaf411a00aef601fb37f3a5e00aa4b85bace1fd2ebad347033aadc543c55 + md5: 61f2e6900de1f2aff25717b332ed6dac + depends: + - binutils_impl_linux-64 >=2.46.1 + - libgcc >=15.3.0 + - libgcc-devel_linux-64 15.3.0 h2b852eb_107 + - libgomp >=15.3.0 + - libsanitizer 15.3.0 h54950a5_7 + - libstdcxx >=15.3.0 + - libstdcxx-devel_linux-64 15.3.0 hb2c5482_107 + - sysroot_linux-64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 83849972 + timestamp: 1790302722312 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.44.8-h68053f1_2.conda + sha256: 32f3ebd1871cb6ac7eac36c78c410860f38e8d252d5857a80f6abfcb79c7e0ff + md5: d7bd6ccfc58eb6796bd6bba85878fc0e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libglib >=2.88.3,<3.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libtiff >=4.7.2,<4.8.0a0 + license: LGPL-2.1-or-later + license_family: LGPL + run_exports: + weak: + - gdk-pixbuf >=2.44.8,<3.0a0 + size: 581961 + timestamp: 1788490424411 +- conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.90.0-h3d503d9_0.conda + sha256: a31c2244c6743a85941ac1d19a77ce2cc871afa171b0ad9aaac309af532d0677 + md5: d4adaebf8a2c9040ada6549c52a6b8d8 + depends: + - libglib ==2.90.0 h569388d_0 + - libffi + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + license: LGPL-2.1-or-later + run_exports: {} + size: 237225 + timestamp: 1789478025196 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.15-h54a6638_1.conda + sha256: 7fa3b6a9c081fa3e545573152a788d061a0a0ba57df7251cc0f4f75225fc93e7 + md5: f9fe2984587fa8235a6af6004760cd18 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 + size: 102835 + timestamp: 1786118485753 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphviz-14.1.2-h8b86629_0.conda + sha256: 48d4aae8d2f7dd038b8c2b6a1b68b7bca13fa6b374b78c09fcc0757fa21234a1 + md5: 341fc61cfe8efa5c72d24db56c776f44 + depends: + - __glibc >=2.17,<3.0.a0 + - adwaita-icon-theme + - cairo >=1.18.4,<2.0a0 + - fonts-conda-ecosystem + - gdk-pixbuf >=2.44.4,<3.0a0 + - gtk3 >=3.24.43,<4.0a0 + - gts >=0.7.6,<0.8.0a0 + - libexpat >=2.7.3,<3.0a0 + - libgcc >=14 + - libgd >=2.3.3,<2.4.0a0 + - libglib >=2.86.3,<3.0a0 + - librsvg >=2.60.0,<3.0a0 + - libstdcxx >=14 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - pango >=1.56.4,<2.0a0 + license: EPL-1.0 + license_family: Other + run_exports: + weak: + - graphviz >=14.1.2,<15.0a0 + size: 2426455 + timestamp: 1769427102743 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gtk3-3.24.52-ha5ea40c_0.conda + sha256: c6bb4f06331bcb0a566d84e0f0fad7af4b9035a03b13e2d5ecfaf13be57e6e10 + md5: bcaea22d85999a4f17918acfab877e61 + depends: + - __glibc >=2.17,<3.0.a0 + - at-spi2-atk >=2.38.0,<3.0a0 + - atk-1.0 >=2.38.0 + - cairo >=1.18.4,<2.0a0 + - epoxy >=1.5.10,<1.6.0a0 + - fontconfig >=2.17.1,<3.0a0 + - fonts-conda-ecosystem + - fribidi >=1.0.16,<2.0a0 + - gdk-pixbuf >=2.44.5,<3.0a0 + - glib-tools + - harfbuzz >=13.2.1 + - hicolor-icon-theme + - libcups >=2.3.3,<2.4.0a0 + - libcups >=2.3.3,<3.0a0 + - libexpat >=2.7.4,<3.0a0 + - libfreetype >=2.14.2 + - libfreetype6 >=2.14.2 + - libgcc >=14 + - libglib >=2.86.4,<3.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxkbcommon >=1.13.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - pango >=1.56.4,<2.0a0 + - wayland >=1.25.0,<2.0a0 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxcomposite >=0.4.7,<1.0a0 + - xorg-libxcursor >=1.2.3,<2.0a0 + - xorg-libxdamage >=1.1.6,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxfixes >=6.0.2,<7.0a0 + - xorg-libxi >=1.8.2,<2.0a0 + - xorg-libxinerama >=1.1.6,<1.2.0a0 + - xorg-libxrandr >=1.5.5,<2.0a0 + - xorg-libxrender >=0.9.12,<0.10.0a0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - gtk3 >=3.24.52,<4.0a0 + - adwaita-icon-theme + size: 5939083 + timestamp: 1774288645605 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gts-0.7.6-h977cf35_4.conda + sha256: b5cd16262fefb836f69dc26d879b6508d29f8a5c5948a966c47fe99e2e19c99b + md5: 4d8df0b0db060d33c9a702ada998a8fe + depends: + - libgcc-ng >=12 + - libglib >=2.76.3,<3.0a0 + - libstdcxx-ng >=12 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - gts >=0.7.6,<0.8.0a0 + size: 318312 + timestamp: 1686545244763 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.3.0-hc6a0c74_7.conda + sha256: b4d8243c72c114f3bc5189659f0ad7745d35b3c08fbd529d7dd32b7fbb631a5e + md5: 6ab627ce20ea2270ea95cf54577aacf4 + depends: + - conda-gcc-specs + - gcc 15.3.0 hc6a0c74_7 + - gxx_impl_linux-64 15.3.0 h90d9265_7 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 28905 + timestamp: 1790302956904 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.3.0-h90d9265_7.conda + sha256: 23e396ca14d05c645f431175379ec010676827d0b7791131ef4f1422f522a755 + md5: f36649dd9798b6982afd26447244984e + depends: + - gcc_impl_linux-64 15.3.0 h6ad849d_7 + - libstdcxx-devel_linux-64 15.3.0 hb2c5482_107 + - sysroot_linux-64 + - tzdata + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 17023748 + timestamp: 1790302893582 +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-14.6.0-ha770c72_1.conda + sha256: 91b07a1ea0d353ffb0b98fda1806e96ba47bdb89f823920169e97a3af2a30301 + md5: c4ba2eba9b3746ef646cb1f11e2eff33 + depends: + - libharfbuzz-devel 14.6.0 h23af247_1 + license: MIT + run_exports: + weak: + - libharfbuzz >=14.6.0 + size: 11103 + timestamp: 1791336162823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h19486de_110.conda + sha256: ac57ce3abbda2a82d6192bc36fbd7fe96e867d84c999ef81a3da034dfd01a995 + md5: 9c6e11a83468e1d5decae516077a73fb + depends: + - __glibc >=2.17,<3.0.a0 + - libaec >=1.1.5,<2.0a0 + - libcurl >=8.20.0,<9.0a0 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + - libstdcxx >=14 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - hdf5 >=1.14.6,<1.14.7.0a0 + size: 3721555 + timestamp: 1780581675871 +- conda: https://conda.anaconda.org/conda-forge/linux-64/hicolor-icon-theme-0.17-ha770c72_3.conda + sha256: 6d7e6e1286cb521059fe69696705100a03b006efb914ffe82a2ae97ecbae66b7 + md5: 129e404c5b001f3ef5581316971e3ea0 + license: GPL-2.0-or-later + license_family: GPL + run_exports: {} + size: 17625 + timestamp: 1771539597968 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + sha256: 9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae432 + md5: 72a381cbad04f24b1c2a43ef707f45b4 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14459115 + timestamp: 1786545741408 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + sha256: dd053c96dcb0dcfd59422aefea9d2fe937a190167f34fba7893ec1e10a7e8963 + md5: ba55d1b89fd7775e67de8291029b4059 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: LGPL-2.1-or-later + run_exports: + weak: + - keyutils >=1.6.3,<2.0a0 + size: 135295 + timestamp: 1786739238128 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + sha256: 2a5c38c85e63df84c4e69ee71439841ce570d259ae3060627bb9a49a938d66f4 + md5: 53318d715316929a574f83591308b1f8 + depends: + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=15 + - libstdcxx >=15 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 1394333 + timestamp: 1786762112514 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + sha256: 27d83f1188cd19bcb7754a078b3fa7f4cfb8527f8eb2fde54dd01fc529d1adec + md5: 449500f2c089da11c40f5c21312e3e07 + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.46.1 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 745303 + timestamp: 1784214507189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.2.0-hdb68285_0.conda + sha256: bf9fdebf55d8bc99d83531cdffda00703f4dc5f93a1a956768c147362c72feda + md5: fb9d356b1a57d6d54768be7ebd5fce09 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - lerc >=4.2.0,<5.0a0 + size: 271158 + timestamp: 1785036167977 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda + sha256: 822e4ae421a7e9c04e841323526321185f6659222325e1a9aedec811c686e688 + md5: 86f7414544ae606282352fa1e116b41f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libaec >=1.1.5,<2.0a0 + size: 36544 + timestamp: 1769221884824 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-11_h4a7cf45_openblas.conda + build_number: 11 + sha256: d942e0c820d60a613a6f786d074f0820fb6343e3f1ccfb110b1d98b44fb75968 + md5: b8cce1486f3c62f33291d6318c193d0d + depends: + - libopenblas >=0.3.34,<0.3.35.0a0 + - libopenblas >=0.3.34,<1.0a0 + constrains: + - blas 2.311 openblas + - libcblas 3.11.0 11*_openblas + - liblapack 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + - mkl <2027 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 + size: 18246 + timestamp: 1789061062982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-11_h0358290_openblas.conda + build_number: 11 + sha256: f7d1bbdea61cf94ba219d17b2cb571a29830f8025385af799bff5a7ad1ef45e6 + md5: 73a248c30811075059b5aeda766c2624 + depends: + - libblas 3.11.0 11_h4a7cf45_openblas + constrains: + - blas 2.311 openblas + - liblapack 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 + size: 18196 + timestamp: 1789061068819 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp23.1-23.1.2-default_h0acdd01_0.conda + sha256: 49156155d4f0ab4f479bc96d24db2c48c0b6bdb5659135c194f03c289ae2c523 + md5: b4820da1ea9315a05a8d9e6a09cd919f + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libclang-cpp23.1 >=23.1.2,<23.2.0a0 + size: 25352541 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-23.1.2-default_hfab3205_0.conda + sha256: 6009280c06f52fcce68f4c95c19e23a13aaf3edc99c4ae1e574c4c5f09eccac3 + md5: 6a0a310fae06a7f1ee8e70f1d3953157 + depends: + - libclang-cpp23.1 ==23.1.2 default_h0acdd01_0 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libclang13 >=23.1.2 + size: 15440981 + timestamp: 1790242185189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcompiler-rt-23.1.2-h7148c6a_0.conda + sha256: 2b0e6b377b1a429db6a86cad50a07e856a2c6ef748d740a3d59722677376eefd + md5: 6a6b0f4e8f08c3f7b717db7c23ab4a8d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libcompiler-rt >=23.1.2 + size: 10695608 + timestamp: 1790196181311 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c + md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 + depends: + - __glibc >=2.17,<3.0.a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - libcups >=2.3.3,<2.4.0a0 + size: 4518030 + timestamp: 1770902209173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.22.0-ha042cf0_0.conda + sha256: 483b7eb97f56fbb3a9cb7190d33012dfa0a5aaed99ede61465563cd97dd82504 + md5: e617deee7af8eb0c04f6296d12b54157 + depends: + - __glibc >=2.17,<3.0.a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=15 + - libnghttp2 >=1.68.1,<2.0a0 + - libpsl >=0.23.1,<0.24.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.8,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + run_exports: + weak: + - libcurl >=8.22.0,<9.0a0 + size: 499651 + timestamp: 1788340719230 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-hd45a770_1.conda + sha256: 82e134c8a08b1eed9a2ed8ab578b89aa1730dcde3dea8dd87645ed0637878e54 + md5: 40f9b31aa9cf007789867df0decd0492 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 + size: 73710 + timestamp: 1785908694612 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.129-h7cc23a3_0.conda + sha256: ea46b0ca0fa16af1f8b329b740e6cd8b4577c5378fa8717b28a885f70668633d + md5: 64cc91512b6278c315349dc13c53f680 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libpciaccess >=0.19,<0.20.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libdrm >=2.4.129,<2.5.0a0 + size: 313461 + timestamp: 1786684701973 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + sha256: 45301f14f4eb66da57cfaf2d265f3eeee73f8b07e99614ee3afc5b26eea91126 + md5: 27dbd7e2984b8fe48e069379636ccfdd + depends: + - ncurses + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.6,<7.0a0 + license: BSD-2-Clause + run_exports: + weak: + - libedit >=3.1.20260512,<3.2.0a0 + size: 135877 + timestamp: 1791327370514 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_5.conda + sha256: 13d3fde9c1dcf254968cc70652222a43f25d04e69555ccf855553110e753288e + md5: 3a1b41c4591a0a1734382af3e2b8bc08 + depends: + - __glibc >=2.17,<3.0.a0 + - libglvnd 1.7.0 ha4b6fd6_5 + license: LicenseRef-libglvnd + run_exports: {} + size: 46694 + timestamp: 1787310030923 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_5.conda + sha256: fd2794bbcff7e692fb476c17886702702893d074071d429217bad7cfb072abfd + md5: 577800fc8c9d8b7d9727246bbfde704e + depends: + - __glibc >=2.17,<3.0.a0 + - libegl 1.7.0 ha4b6fd6_5 + - libgl-devel 1.7.0 ha4b6fd6_5 + - xorg-libx11 + license: LicenseRef-libglvnd + run_exports: + weak: + - libegl >=1.7.0,<2.0a0 + size: 31242 + timestamp: 1787310065866 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h280c20c_3.conda + sha256: e4418f68d01a6307c4431b585c71b584f40189877364e542ee87deb777f5e85b + md5: 7bc31538d6e3fb349e897353969237ec + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: BSD-2-Clause OR GPL-2.0-or-later + license_family: GPL + run_exports: + weak: + - libev >=4.33,<4.34.0a0 + size: 43220 + timestamp: 1785917328200 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + sha256: 6de73033a7c5f712c9c5a54124e4581e025691029835e5bceaf10a333a7e7bc0 + md5: 72cfd2b95b0540247220b42f58a148d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 77893 + timestamp: 1790346247149 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + sha256: c8c7583ef063bc3c430f1d48298e5ad24f796a35c22ed5b14183325825a61106 + md5: 6525a0b06aa4fd390795f0740636a9dd + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 68004 + timestamp: 1787753412298 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_2.conda + sha256: fb12ecb46c30d18d928c0e8fc346ab13b5f6fc8a9cacae4f2f4bb188782586f5 + md5: f8054e759d0ddddaf34a5c8fedc900a1 + depends: + - libfreetype6 >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 8407 + timestamp: 1786641007099 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h5e6c136_2.conda + sha256: ec607dd5445dd17ff6bf8b7fe6832e5504c226dd91d3aaea7ba83569808b0ce4 + md5: b72a266a9317036fd0464cb98b027cd0 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - freetype >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 387671 + timestamp: 1786641006460 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + sha256: e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea + md5: 735629b400b70eeab21a2ba8f5b1c2ce + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==16.2.0=*_7 + - libgomp 16.2.0 he0feb66_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 1058444 + timestamp: 1790303109576 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.2.0-h69a702a_7.conda + sha256: 03b54d7008de080a17cc2174b0e4acd6d06e1c981b2eb19846f46d8f59966034 + md5: 2005515ac9340f816fb2ac7e83afe553 + depends: + - libgcc 16.2.0 ha9f2e26_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: + strong: + - libgcc + size: 28616 + timestamp: 1790303114248 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgd-2.3.3-h5fbf134_12.conda + sha256: 245be793e831170504f36213134f4c24eedaf39e634679809fd5391ad214480b + md5: 88c1c66987cd52a712eea89c27104be6 + depends: + - __glibc >=2.17,<3.0.a0 + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.1,<79.0a0 + - libexpat >=2.7.3,<3.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + - libgcc >=14 + - libjpeg-turbo >=3.1.2,<4.0a0 + - libpng >=1.6.53,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + license: GD + license_family: BSD + run_exports: + weak: + - libgd >=2.3.3,<2.4.0a0 + size: 177306 + timestamp: 1766331805898 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_7.conda + sha256: 9682ae4dd11487e10b904b3cb3ab6379cad25233d45fdfdf90d54349df244494 + md5: 3a8d285f5f22138ef826ad54cf267e73 + depends: + - libgfortran5 16.2.0 h6b99dfc_7 + constrains: + - libgfortran-ng ==16.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 28571 + timestamp: 1790303139904 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_7.conda + sha256: 04dbab12c925b92977bb835dd2f5eda413607afa79f95a554e5a04b07a380322 + md5: 7719ed7be38ad8c492c4bd5cc2bce0c4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=16.2.0 + constrains: + - libgfortran 16.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 2528180 + timestamp: 1790303122004 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_5.conda + sha256: 7b2e7e31e8a4f5a01c45ecadcd8aa68c8f733b035240bc7ba9881835ef4bf7b4 + md5: 81141db127a106eb5a91df69a29c9918 + depends: + - __glibc >=2.17,<3.0.a0 + - libglvnd 1.7.0 ha4b6fd6_5 + - libglx 1.7.0 ha4b6fd6_5 + license: LicenseRef-libglvnd + run_exports: {} + size: 131988 + timestamp: 1787310049847 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_5.conda + sha256: 3bebdbeb3ce451287794dddd5cc4d7f4970aac200b2fb797f0d17ac727a71cb7 + md5: f5f7fc038c611a25b22758c0a40d25c9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgl 1.7.0 ha4b6fd6_5 + - libglx-devel 1.7.0 ha4b6fd6_5 + license: LicenseRef-libglvnd + run_exports: + weak: + - libgl >=1.7.0,<2.0a0 + size: 116212 + timestamp: 1787310061570 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.90.0-h569388d_0.conda + sha256: 9e688e046550415c030c3d08ed9a3fd13a51d7bc56295283b858b6c3070bb9f8 + md5: c85e9539551f1fd21104e518d940c244 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libiconv >=1.18,<2.0a0 + - pcre2 >=10.47,<10.48.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - glib >2.66 + license: LGPL-2.1-or-later + run_exports: + weak: + - libglib >=2.90.0,<3.0a0 + size: 4819130 + timestamp: 1789478025196 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_5.conda + sha256: 6eb77601a44b78c4631d886d54ef54f321c2bdc69fdefc4065a1e0491f030c76 + md5: cfcf11edcfd4acf0094771a9c3b8587f + depends: + - __glibc >=2.17,<3.0.a0 + license: LicenseRef-libglvnd + run_exports: {} + size: 133827 + timestamp: 1787310026653 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_5.conda + sha256: d1f0d51aea6bcc5d915969cbed32e72a8ed6a95931b87357ef8d0866573688c4 + md5: 614e10aae180f87b84f0d1ca8ceb7d9e + depends: + - __glibc >=2.17,<3.0.a0 + - libglvnd 1.7.0 ha4b6fd6_5 + - xorg-libx11 >=1.8.13,<2.0a0 + license: LicenseRef-libglvnd + run_exports: {} + size: 79834 + timestamp: 1787310042550 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_5.conda + sha256: aff3841e3404d78e1887fef988ca4842930c577399d566fa0980808756b1df51 + md5: fb00b4fb800f2d431303a5c1625ef9d0 + depends: + - __glibc >=2.17,<3.0.a0 + - libglx 1.7.0 ha4b6fd6_5 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-xorgproto + license: LicenseRef-libglvnd + run_exports: + weak: + - libglx >=1.7.0,<2.0a0 + size: 27698 + timestamp: 1787310053582 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + sha256: 92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758 + md5: d904c7ddd95e026254b4b80808ee9e12 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 640566 + timestamp: 1790303046034 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-14.6.0-h23af247_1.conda + sha256: a5af64065d8fb70b77ce4551c9ae022b4f170f11b789249ee6efab3e83fedbe0 + md5: bd7ae146a629d6c17e4be9365d4ec811 + depends: + - __glibc >=2.17,<3.0.a0 + - cairo >=1.18.6,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=15 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.59,<1.7.0a0 + - libstdcxx >=15 + - libzlib >=1.3.2,<2.0a0 + license: MIT + run_exports: {} + size: 1465053 + timestamp: 1791336135892 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-devel-14.6.0-h23af247_1.conda + sha256: 7c5c3f8a10ac96c8ce6f46a7bd65531317469624524a473eea73789745cf73ad + md5: e43e418e02d8f52cc7784696d3c62b6f + depends: + - __glibc >=2.17,<3.0.a0 + - cairo >=1.18.6,<2.0a0 + - freetype + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=15 + - libglib >=2.90.0,<3.0a0 + - libharfbuzz 14.6.0 h23af247_1 + - libpng >=1.6.59,<1.7.0a0 + - libstdcxx >=15 + - libzlib >=1.3.2,<2.0a0 + license: MIT + run_exports: + weak: + - libharfbuzz >=14.6.0 + size: 2316467 + timestamp: 1791336155010 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libhiredis-1.3.0-h5888daf_1.conda + sha256: 5638e321719590b00826d218431d5028d1a22a76f281532ce621d9a40d5e0f42 + md5: aa342fcf3bc583660dbfdb2eae6be48e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libhiredis >=1.3.0,<1.4.0a0 + size: 140759 + timestamp: 1748219397797 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda + sha256: f943117edb9cd4d9c61cc972eee5a34291dc55ea7a6e9e38da104995841cbcb6 + md5: f92233bf33e24a25668bb2119e2c51f9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: LGPL-2.1-only + run_exports: + weak: + - libiconv >=1.18,<2.0a0 + size: 789471 + timestamp: 1787033836207 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.2.0-hb03c661_1.conda + sha256: bba8538e6538ed58a8479b332337b96986561f975d06cfa2039a016c2d246ee4 + md5: 898d1c9793eaa52efc4727bd84d2e39a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + run_exports: + weak: + - libjpeg-turbo >=3.2.0,<4.0a0 + size: 650434 + timestamp: 1785896381946 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-11_h47877c9_openblas.conda + build_number: 11 + sha256: 1ad3f43c9319ef398a8ef45989f4903a06e3965b51e77fc669a4c894168a8411 + md5: 5622a13917855ce4b953b9e655cf9262 + depends: + - libblas 3.11.0 11_h4a7cf45_openblas + constrains: + - blas 2.311 openblas + - libcblas 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 + size: 18227 + timestamp: 1789061073957 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm23-23.1.3-h474f4eb_0.conda + sha256: 7ce347e2da1502442d4df406101cfaf429927b7a9410badadd3f147d3cbf2d00 + md5: cd6352703382608abc83ad5120abddd5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libllvm23 >=23.1.3,<23.2.0a0 + size: 45082185 + timestamp: 1791345280243 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + sha256: 9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab + md5: 1390b7c5ac0b1d8e447bc5efa6d3c8c2 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 112995 + timestamp: 1786348617826 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmatio-1.5.30-he0a2e19_0.conda + sha256: c9ac2d45e7504a4844f3b56dbac2c78330d67a64432b1ae47de9d7059548edf9 + md5: c253b59cce00f8d6a7588500ff3597b7 + depends: + - __glibc >=2.17,<3.0.a0 + - hdf5 >=1.14.6,<1.14.7.0a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + - zlib + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libmatio >=1.5.30,<1.5.31.0a0 + size: 202346 + timestamp: 1767753592345 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + sha256: 46820b4a835e175940ae20bec00fdddaff804cda27a1408ab1b95e77a2196437 + md5: fcfed1dc5053eb1901b66e7b1fc32588 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 92759 + timestamp: 1786650399772 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h74cf4be_1.conda + sha256: 11a2f54a6f391e25738bce0023e6ef499600147bbcf21c1fa69d2e251b03cc6a + md5: 75d211f04ac87506f1f43420712a69fe + depends: + - __glibc >=2.17,<3.0.a0 + - c-ares >=1.34.8,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=15 + - libstdcxx >=15 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 + size: 649974 + timestamp: 1787177490105 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + run_exports: + weak: + - libnsl >=2.0.1,<2.1.0a0 + size: 33731 + timestamp: 1750274110928 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.34-pthreads_hf13c14d_2.conda + sha256: 69a722751e14eab2eb3bfdcb9acb1187afbd962b0c49b48d829341e0f6787f60 + md5: 7e19fcd73d7f0997d3cb3326d2586a86 + depends: + - libgfortran5 >=15.3.0 + - libgfortran + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + constrains: + - openblas >=0.3.34,<0.3.35.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libopenblas >=0.3.34,<1.0a0 + size: 6845411 + timestamp: 1789141490688 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_1.conda + sha256: addc80c69d362a9e6c40305c493139a8e9ee504b2f45a6687dbdaa9da3c6183c + md5: 35fa2b34bbced424e6976d30f5fde576 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + run_exports: + weak: + - libpciaccess >=0.19,<0.20.0a0 + size: 30070 + timestamp: 1785971678815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.59-h922cc85_0.conda + sha256: c7381be8ef713501f6cd2f5ad473e401f2edeaec3c46788296b8dbf0de165e15 + md5: 8c9caf742a485ac688ffa88bbadbf0be + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: zlib-acknowledgement + run_exports: + weak: + - libpng >=1.6.59,<1.7.0a0 + size: 316872 + timestamp: 1790805159503 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpsl-0.23.1-hd9e3e90_1.conda + sha256: 09e8effdc89bc5d021349318d32b85594f5b8d8e3ab8f90a85b81f8fe695a566 + md5: 77be60417aa572afcb48cbe0f967401d + depends: + - libstdcxx >=15 + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libpsl >=0.23.1,<0.24.0a0 + size: 72519 + timestamp: 1786970753847 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.14.8-hdc7f604_101_cp314.conda + build_number: 101 + sha256: 3dc27daa3470f9b6f863942d99db623d79204ea478955ea73e97d3519cae2ab5 + md5: 5782a594549b816514ca434a42bbf11a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + license: Python-2.0 + run_exports: + weak: + - libpython >=3.14,<4.0a0 + size: 10544845 + timestamp: 1791333423324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/librsvg-2.62.4-ha427ee3_0.conda + sha256: b8036adad17ceddcef416790131492fd236d34c64a0b2754934903087fa84279 + md5: f9bda2728debbde4c641bd1af103c623 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libglib >=2.90.0,<3.0a0 + - pango >=1.58.2,<2.0a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - libxml2-16 >=2.15.4 + - cairo >=1.18.6,<2.0a0 + - libharfbuzz >=14.5.0 + - gdk-pixbuf >=2.44.8,<3.0a0 + constrains: + - __glibc >=2.17 + license: LGPL-2.1-or-later + run_exports: + weak: + - librsvg >=2.62.4,<3.0a0 + size: 4692221 + timestamp: 1790276295756 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.3.0-h54950a5_7.conda + sha256: 9e5518e38502568f4591be965d48c1a3f79e2da4d74567f1a62e00244cf40222 + md5: 04361d154f650289702f20c0ff86d7be + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15.3.0 + - libstdcxx >=15.3.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: + weak: + - libsanitizer 15.3.0 + size: 8073659 + timestamp: 1790302682129 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_102.conda + sha256: 0f6e60634de2b55da15772fe65485965fd9b61afcce0d749c1446f625babba30 + md5: 59ec6dc9fa87a6687c00969d4dcfcd97 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 969522 + timestamp: 1791167270446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h0737f62_103.conda + sha256: 66f4831f4ee3055f0ffe94e01901198cf3601e2c1b4f6b51d05c3f2d8557ce1d + md5: cc1ad2520049c35344239454a17560ac + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + constrains: + - icu <0.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 967489 + timestamp: 1791288185694 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda + sha256: 7e463000fa1cba3f3a6597b776f6ab301d425a96e3bc20d0d9d76a3b9f237aa3 + md5: 5c526561e1d2a2e071941174eae84557 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libssh2 >=1.11.1,<2.0a0 + size: 306045 + timestamp: 1786713107897 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + sha256: fa7018298629fc429971fffd6ecba3d27a7b02e4e890d6a93ea01ffebe8cb745 + md5: 9b6707e0caca917fa6ea9ee473f37a5d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 16.2.0 ha9f2e26_7 + constrains: + - libstdcxx-ng ==16.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 6615436 + timestamp: 1790303132935 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.2.0-hdf11a46_7.conda + sha256: 337f481db36cc357884f05f404ccd1b3a7e0fc1ee48ec5c884e4281d213bc863 + md5: 25a23bde5e26d548374f3e02b4669670 + depends: + - libstdcxx 16.2.0 h934c35e_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: + strong: + - libstdcxx + size: 28665 + timestamp: 1790303164510 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.2-hcc2c06a_1.conda + sha256: 10e125da82ca93e09191e66e5a94d566b2cf8d4024e2a0db3a9114297447e0d9 + md5: 0907d876f460ebc941ae590338b6102f + depends: + - __glibc >=2.17,<3.0.a0 + - lerc >=4.2.0,<5.0a0 + - libdeflate >=1.25,<1.26.0a0 + - libgcc >=15 + - libjpeg-turbo >=3.2.0,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libstdcxx >=15 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + run_exports: + weak: + - libtiff >=4.7.2,<4.8.0a0 + size: 459753 + timestamp: 1787755584172 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + sha256: f34b8d1de9a2bf62476d8608057d9b8a918d97444236dc53a47128f2fae79041 + md5: 54a948337e66706380ff24d6b5fde63f + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libuuid >=2.42.4,<3.0a0 + size: 34442 + timestamp: 1790121449161 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda + sha256: 67761d0206f84140047a367eaf9befe03a7e157a29ee25aee0047b40801cc6b6 + md5: 01c4ed87826af55996768af6dbc936b4 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 420040 + timestamp: 1785914567661 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_1.conda + sha256: 8415001414f488c85b72b9d8cc2071dfb3981a47bc3c8eb56ef91a57d12eae7f + md5: 9332b53d0ea93c5d39e33be03a0c611a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 + size: 428430 + timestamp: 1785954557217 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-hb83e432_2.conda + sha256: 7b49e6fd2a584b7f072943e6adf4149677af5121246975278804782d37752837 + md5: 61f0ffba9161cbb3a77722869b21e4bb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - pthread-stubs + - xorg-libxau >=1.0.12,<2.0a0 + - xorg-libxdmcp >=1.1.5,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libxcb >=1.17.0,<2.0a0 + size: 395120 + timestamp: 1787885788278 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.38-h280c20c_0.conda + sha256: f7e9292dd219a6435bbb1223da9586c3e70d66d169c5a92f08db3f2127df04e9 + md5: f7a7ff5a6ab331e037abd34f379a631d + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: LGPL-2.1-or-later + run_exports: + weak: + - libxcrypt >=4.4.38 + size: 101957 + timestamp: 1785887123445 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.13.2-h51789e4_1.conda + sha256: d44878d396713ccf3b355df617f61c40a1442fffcf134392bc6ce0e6c2219369 + md5: f888787e0eab7a8076a67d197e155ffc + depends: + - xkeyboard-config + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libxcb >=1.17.0,<2.0a0 + - xorg-libxau >=1.0.12,<2.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + license: MIT AND MIT-open-group AND HPND AND HPND-sell-variant AND ISC + run_exports: + weak: + - libxkbcommon >=1.13.2,<2.0a0 + size: 942571 + timestamp: 1787178780572 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hf3af7cc_0.conda + sha256: 9a1685c8d8b8488cd7882a9cd6e673e687211ca763ebbcd1e91b6f594eeadc45 + md5: b7545c57a73a51d72aa6eee5695cf051 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=15 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - libxml2 2.15.4 + license: MIT + license_family: MIT + run_exports: {} + size: 569196 + timestamp: 1788635197456 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-h7df9aa5_0.conda + sha256: 053d85821ce5e36b7ce03faea5930382f6af695df9e2cd68e5d8d273072d1551 + md5: ea192d1ef556bf1d55de4acb8c0f5b65 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=15 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.4 hf3af7cc_0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.4 + size: 47077 + timestamp: 1788635202698 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + sha256: eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc736 + md5: 0de0122d9570a8ab637c6b73db268389 + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 63713 + timestamp: 1785362952714 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lld-23.1.2-h5985d43_0.conda + sha256: fedcd88c7d728213d36eb489da574bd36cd844b25736ad06df12424592bde4ec + md5: 6803d265ec68590bb73d31570fd9cf4d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libllvm23 >=23.1.2,<23.2.0a0 + - libstdcxx >=15 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - llvm ==23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 12253424 + timestamp: 1790193220438 +- conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-23.1.2-h7148c6a_0.conda + sha256: 292606e3a17fcf98db940d3ee6e723f84f4c6fb0104a6a69cd95043a7794eef0 + md5: ea93fc2d6563d7401bba4a6fffd9d641 + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - intel-openmp <0.0a0 + - openmp 23.1.2|23.1.2.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + strong: + - llvm-openmp >=23.1.2 + - _openmp_mutex >=4.5 + - _openmp_mutex * *_llvm + size: 6129472 + timestamp: 1790195558482 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + sha256: 5d46557214ed184381dafe835b7c94a474a1c3b307a08a250b1ea4779b44ffb3 + md5: ee6c0cd80a60961a1f48aa3e0b91f986 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: X11 AND BSD-3-Clause + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 911196 + timestamp: 1786355078102 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_1.conda + sha256: 2b5f2e865122f9fc0637f520a7cb22e16b9727b2db6761ee16cb5e6404412c81 + md5: 2db7a395d7dc2b6ed5effaf68fb99443 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 186767 + timestamp: 1786713048064 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda + sha256: 0ba94a61f91d67413e60fa8daa85627a8f299b5054b0eff8f93d26da83ec755e + md5: b0cea2c364bf65cd19e023040eeab05d + depends: + - __glibc >=2.17,<3.0.a0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc >=13 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx >=13 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.21,<3 + size: 7893263 + timestamp: 1747545075833 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.3-py314hd3a7d6b_0.conda + sha256: 2aeb4c5a0869a84e69b4e57bfd04911cd148070d667bc598f3bb85366ee40607 + md5: d1ae35d69e57534c8713ff0368b9fdb9 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - liblapack >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + - libblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.25,<3 + size: 9395024 + timestamp: 1788731986404 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + sha256: 9c1533f1cf784f0e250919c0c9762d0b0e6bc727a79290ffb7cea1ceca1d038c + md5: 5a51a2ea653f120240b1a9bf76e0aae9 + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=15 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 3195299 + timestamp: 1791098052301 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pango-1.58.2-h7bb47b9_1.conda + sha256: 47c3d25a0bdb0ae50627f9ef2a10345fabfabe0e6620cbcff04e589a644542d3 + md5: 0b889b1c6b472d215d6332c6b195589c + depends: + - __glibc >=2.17,<3.0.a0 + - cairo >=1.18.4,<2.0a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - fribidi >=1.0.16,<2.0a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=15 + - libglib >=2.88.3,<3.0a0 + - libharfbuzz >=14.4.0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: LGPL-2.1-or-later + run_exports: + weak: + - pango >=1.58.2,<2.0a0 + size: 471814 + timestamp: 1788490377724 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-h8b3dc9c_1.conda + sha256: 9ebb10a4eb3be51ae67d85c679f5a7a50cb040ed25c783e6331a225ea09991d4 + md5: 06f6113cf1ff4a54b65f87ead132a5f1 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 + size: 1218833 + timestamp: 1787294571916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_3.conda + sha256: 829d8288764282de5a9f7b9169acb75cc7dc0b6c3fe2535cfe87dea3436bbc5d + md5: 0ee5bb30034b081a1386c1e2c98ab0a7 + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 + size: 376704 + timestamp: 1786106621354 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-h7cc23a3_1004.conda + sha256: 4a44fd00ea73b79ca2c89b0727b9ccf61c506ead71e67a9abfa4c590042b5a4a + md5: bb66b610707b811e3c65181a6431e7a8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: {} + size: 9630 + timestamp: 1788381877753 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.22-h267e890_0_cpython.conda + sha256: 819fa140a71ab005c448bf164eb182f91610b50f0bffca5b0b94cb6773c5e2f4 + md5: 4dd10eb73930c39aa7bc48b979fa24e0 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc >=14 + - liblzma >=5.8.3,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libuuid >=2.42.4,<3.0a0 + - libxcrypt >=4.4.38 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.10.* *_cp310 + noarch: + - python + size: 25334749 + timestamp: 1791328449078 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.8-hcd007b5_101_cp314.conda + build_number: 101 + sha256: e22f6a79d290935b2c854d325e260f70f364c7cc7ec0bc8308ded4f2f1eef7e6 + md5: 5cb98b237dfc2c64a65e660d7b99cfa5 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 hdc7f604_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libuuid >=2.42.4,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 26633451 + timestamp: 1791333464567 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d + md5: 2035f68f96be30dc60a5dfd7452c7941 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 202391 + timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + sha256: 01b3fe073a66e321970d09e04b388708f8cbdca5cdfbfcb7c9eeb470ad10383d + md5: 69c01c781e7c8190bbdaf79e3848c5ca + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 348899 + timestamp: 1787033801506 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda + sha256: 186a5b225077ad5f4656966da947d43307101950751ef4a239b455588756b4e1 + md5: 007602d697e07c11ff9864964eba5ee3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + run_exports: + weak: + - rhash >=1.4.6,<2.0a0 + size: 194994 + timestamp: 1786731436520 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py314hfe1a184_5.conda + sha256: a1e3159f6d131fb7c6a17a1812ec9b53e03e485a78901781ccaef82c8196774c + md5: 2c8de2bca562cd68bdcfd0920a6395b9 + depends: + - python + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 160103 + timestamp: 1788881212732 +- conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.15.2-py310h1d65ade_0.conda + sha256: 4cb98641f870666d365594013701d5691205a0fe81ac3ba7778a23b1cc2caa8e + md5: 8c29cd33b64b2eb78597fa28b5595c8d + depends: + - __glibc >=2.17,<3.0.a0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc >=13 + - libgfortran + - libgfortran5 >=13.3.0 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx >=13 + - numpy <2.5 + - numpy >=1.19,<3 + - numpy >=1.23.5 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 16417101 + timestamp: 1739791865060 +- conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.1-py314h36f0660_1.conda + sha256: d51ca962cc65f892c6e3bbcddb9c4093c83368647985cdf2b29e71ade750103b + md5: 2c5a3b238546edf4e3ea3bd9c1b9fa03 + depends: + - __glibc >=2.17,<3.0.a0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc >=15 + - libgfortran + - libgfortran5 >=15.3.0 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx >=15 + - numpy <2.8 + - numpy >=1.25,<3 + - numpy >=2.0.0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 17462716 + timestamp: 1790022695245 +- conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h84d6215_0.conda + sha256: c055f966ebd72a768e25994ea7bdea0f0eecf481128c01e26f68c4ab11ae21b7 + md5: aa4dd437f90aa209a0309313af213964 + depends: + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: {} + size: 480387 + timestamp: 1724439702451 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + build_number: 104 + sha256: a1a241d172c1ccab067ba245206dd048bc3c2d1b84504b53c9468e99adfc16a1 + md5: 676a2f9b1c4fcf57b70aa5c65f6c60d0 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - xorg-libx11 >=1.8.13,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3566806 + timestamp: 1787272857910 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py314h9891dd4_0.conda + sha256: c84034056dc938c853e4f61e72e5bd37e2ec91927a661fb9762f678cbea52d43 + md5: 5d3c008e54c7f49592fca9c32896a76f + depends: + - __glibc >=2.17,<3.0.a0 + - cffi + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 15004 + timestamp: 1769438727085 +- conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.26.0-hc1c935e_2.conda + sha256: df65b987979e6d7f88e756494da5a230d4f2d08d17437d04eecd35559c3a04e4 + md5: 88a47e22b53e50865b1cabe2eb648352 + depends: + - __glibc >=2.17,<3.0.a0 + - libexpat >=2.8.1,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - wayland >=1.26.0,<2.0a0 + size: 340058 + timestamp: 1787793849093 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.48-h280c20c_0.conda + sha256: 3b04afd5d1a65d2d27ac2d49a63b01ab8bcd875776779ec63e337370ed38afdc + md5: b233b41be0bf210989d57160ed39b394 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 441670 + timestamp: 1782027360439 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-h280c20c_0.conda + sha256: 49b532d1df875c6749d9078b56a76f3f5db49a5abe0ca620b593ed474ef0ebf1 + md5: 85c9442aec283b4e464fa9ecc484a2f3 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libice >=1.1.2,<2.0a0 + size: 62517 + timestamp: 1786474410404 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-h0d788c3_1.conda + sha256: ef907caee0665cf3b0f775602cc50e388e3bade8ce22ecade0873ff26604b2fd + md5: aa7459ed9ad086ba11dda843d764b33d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libice >=1.1.2,<2.0a0 + - libuuid >=2.42.2,<3.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libsm >=1.2.6,<2.0a0 + size: 30739 + timestamp: 1786545374265 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_1.conda + sha256: 68053eebfa9f0d91666786c8fb5839d989aa9b869add92cb8815228bb2d7302c + md5: 8c282bbe4808a3cc80a5c98e9aec1cfc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libxcb >=1.17.0,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libx11 >=1.8.13,<2.0a0 + size: 839578 + timestamp: 1787087012372 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-h7cc23a3_2.conda + sha256: 3ec065b94554dc48a4ca582a960a5484bc166b26e83ce0954653e08d17e8bd53 + md5: da33efee1a93603d92e06d4a2b68def6 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxau >=1.0.12,<2.0a0 + size: 18793 + timestamp: 1788960512381 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.7-hb03c661_0.conda + sha256: 048c103000af9541c919deef03ae7c5e9c570ffb4024b42ecb58dbde402e373a + md5: f2ba4192d38b6cef2bb2c25029071d90 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libx11 >=1.8.12,<2.0a0 + - xorg-libxfixes >=6.0.2,<7.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxcomposite >=0.4.7,<1.0a0 + size: 14415 + timestamp: 1770044404696 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda + sha256: 832f538ade441b1eee863c8c91af9e69b356cd3e9e1350fff4fe36cc573fc91a + md5: 2ccd714aa2242315acaf0a67faea780b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - xorg-libx11 >=1.8.10,<2.0a0 + - xorg-libxfixes >=6.0.1,<7.0a0 + - xorg-libxrender >=0.9.11,<0.10.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxcursor >=1.2.3,<2.0a0 + size: 32533 + timestamp: 1730908305254 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda + sha256: 43b9772fd6582bf401846642c4635c47a9b0e36ca08116b3ec3df36ab96e0ec0 + md5: b5fcc7172d22516e1f965490e65e33a4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - xorg-libx11 >=1.8.10,<2.0a0 + - xorg-libxext >=1.3.6,<2.0a0 + - xorg-libxfixes >=6.0.1,<7.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxdamage >=1.1.6,<2.0a0 + size: 13217 + timestamp: 1727891438799 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-h7cc23a3_2.conda + sha256: 8a095df9bc1d2e50f2504ce8858a047ae29ea634aad6cc0b43298c63361da6d9 + md5: eabfc45786244de252090cf8d55128a8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxdmcp >=1.1.5,<2.0a0 + size: 22606 + timestamp: 1789676943335 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-h7cc23a3_1.conda + sha256: aa9bbe8b278aacc194e280ff5037f9f9a1f2c5b33ed97de8e7f01cfbe90dda43 + md5: e5b6b28536b81b3f4cb20db4668a4642 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxext >=1.3.7,<2.0a0 + size: 53124 + timestamp: 1787100841900 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-h7cc23a3_1.conda + sha256: aec84f554fc897bf4085c7bc8b8f0740e4c224e13bca3cc51c93e7699d56f83a + md5: 09132e874fe0e1f5e4492b0b6b904b6e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxfixes >=6.0.2,<7.0a0 + size: 21440 + timestamp: 1787248059682 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.3-h7cc23a3_1.conda + sha256: a523d71344a2f640efe6fc42b88fc261d9cd389d4f9838a5d42dcdb120c2b0c8 + md5: a1412b2b1184dacda45f8476fef2cc25 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxfixes >=6.0.2,<7.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxi >=1.8.3,<2.0a0 + size: 49165 + timestamp: 1787257060460 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxinerama-1.1.6-hecca717_0.conda + sha256: 3a9da41aac6dca9d3ff1b53ee18b9d314de88add76bafad9ca2287a494abcd86 + md5: 93f5d4b5c17c8540479ad65f206fea51 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - xorg-libx11 >=1.8.12,<2.0a0 + - xorg-libxext >=1.3.6,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxinerama >=1.1.6,<1.2.0a0 + size: 14818 + timestamp: 1769432261050 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-h7cc23a3_1.conda + sha256: 05a7f25d7f7f5cd32b27a019233ece97167fd8ade255bc13a0e49e53387f4c30 + md5: 798a8c9d171859a022e1cb89e7d0eb10 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxrender >=0.9.12,<0.10.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxrandr >=1.5.5,<2.0a0 + size: 31106 + timestamp: 1787246614086 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb03c661_1.conda + sha256: 6901f91d398811e4ec89d7e20a69abac02a7bfebfaf073338b7ea3d1a99685b7 + md5: e470d224a7a5be1b1d021bded7abb536 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxrender >=0.9.12,<0.10.0a0 + size: 34645 + timestamp: 1787100191192 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-h7cc23a3_4.conda + sha256: d66525e7b1c492aa179c6c55610fc8dfb0a9a62ea7d4fb9f904fa6af62127f61 + md5: 752a5ac9322e0fbbc24146c1ce3ae44e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxi >=1.8.3,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxtst >=1.2.5,<2.0a0 + size: 35052 + timestamp: 1787360025506 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.7-hb03c661_0.conda + sha256: 64db17baaf36fa03ed8fae105e2e671a7383e22df4077486646f7dbf12842c9f + md5: 665d152b9c6e78da404086088077c844 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libx11 >=1.8.12,<2.0a0 + - xorg-libxext >=1.3.6,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxxf86vm >=1.1.7,<2.0a0 + size: 18701 + timestamp: 1769434732453 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xorgproto-2025.1-hebe6cf0_3.conda + sha256: 8e9c7ca4fcfe9f0c300e4aa853b79c25411fc4e470decfe8f909b74f60dfb6dd + md5: c3d0a6f03ba3aa312777b41b20a71ec0 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + run_exports: {} + size: 596340 + timestamp: 1788874111132 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xxhash-0.8.3-hec8ed23_1.conda + sha256: 540cf88e742b381244cbfdd2918cd5ed7523c1b0cc2945f3bb63620095c10e50 + md5: 72ab4ea51529ec63ff010ae9fb62b02f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - xxhash >=0.8.3,<0.8.4.0a0 + size: 109364 + timestamp: 1785949296126 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-hebe6cf0_3.conda + sha256: d164dfa75ecd538f6fd68765defcc06aa875bc697b9b215362d79a2a73125dd0 + md5: e741576fb8f89821ac7c1c537322a33d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 + size: 84936 + timestamp: 1787228426393 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_3.conda + sha256: 16080a1c7724f7d25727cdc23c7658e0cec2db52448c1dc0c33467ee2c6e1c62 + md5: 6acb86426229f96f93e5468d1df3a5e8 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib 1.3.2 h25fd6f3_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 96132 + timestamp: 1785362957588 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + sha256: 47d682b9f6d6ec9eb1a6e6c3e75ea6273e899e78fb7fc59f81d39745009fbc60 + md5: aa459086047c0e5e27023ab19f8cb86a + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 601301 + timestamp: 1786599621503 +- conda: https://conda.anaconda.org/conda-forge/noarch/adwaita-icon-theme-51.0-unix_0.conda + sha256: def01b148aa54d4de29b7d4bf58d941c8699582201db14cf78c6c89fa1666434 + md5: 6f62266fb2bfc35a5071cfa1d6ffdcc9 + depends: + - __unix + - hicolor-icon-theme + - librsvg + license: LGPL-3.0-or-later OR CC-BY-SA-3.0 + run_exports: {} + size: 687517 + timestamp: 1790100765464 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab + md5: c6b0543676ecb1fb2d7643941fe375f2 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 64927 + timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + sha256: 95e8e74062a5fe5f870ac8c90302b6e89945165fdaed7810606e84ddee6aac12 + md5: e27d2ac27b096dc51fedfcf775a53f9b + depends: + - __win + license: ISC + run_exports: {} + size: 132136 + timestamp: 1784754918886 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + sha256: 0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6 + md5: 0f51e2391ade309db462a55611263e9c + depends: + - __unix + license: ISC + run_exports: {} + size: 131780 + timestamp: 1784754889428 +- conda: https://conda.anaconda.org/conda-forge/noarch/cereal-1.3.2-hd8ed1ab_1.conda + sha256: c32c97e0238aa0a9c480ca2cdffbbe1d898298f4e50ec19b21df87ebf3ad12f2 + md5: 78be8886fc8b989bd9f2a805a3ceca8f + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 203811 + timestamp: 1770054823665 +- conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + sha256: aa589352e61bb221351a79e5946d56916e3c595783994884accdb3b97fe9d449 + md5: 381bd45fb7aa032691f3063aff47e3a1 + depends: + - python >=3.10 + license: MIT + license_family: MIT + run_exports: {} + size: 13589 + timestamp: 1763607964133 +- conda: https://conda.anaconda.org/conda-forge/noarch/cmake-parser-0.9.2-pyhcf101f3_0.conda + sha256: 4ccbf74b2c70c391c4ae97ad00023343f0261fae7179b851412eb463590d4f1b + md5: fc15671b7ef4ee3381229358b97fee54 + depends: + - python >=3.10 + - attrs >=21.3.0 + - python + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 26496 + timestamp: 1781880728174 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-64-21.1.8-h8d5f570_2.conda + sha256: 259c849b2f86f6d7d5c26d01905fd1f0f83fdfdfc9efa4599947a8574f56b189 + md5: 2ca2bde7f33a5f7140832515674bf682 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 10251130 + timestamp: 1787376380967 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt21_osx-arm64-21.1.8-hb8825d9_2.conda + sha256: e7fef79b60a612236b2f4ab84e6d0556fa7f670e32ede52f1217a59213e389d6 + md5: 93f5de189aa3dca7d88ae1d16a0c9754 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 10226963 + timestamp: 1787374944374 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_win-64-22.1.8-h49e36cd_2.conda + sha256: 83503e95b871dd9af6a5e78ed28add18eb2ee40302a2b58584d20f6836750cb6 + md5: c0e5034e1fa0b269ab426ee8cc20c312 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 3527671 + timestamp: 1787293957032 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_linux-64-23.1.2-h0e38de2_0.conda + sha256: 8ab3d19a6d833a9d98a559d40a2e9f07eea353d5501c2610417f53102391bf8c + md5: e25fb7def68a898e3ba171f9e7492ac0 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 45685477 + timestamp: 1790196130803 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_osx-64-23.1.2-h8d5f570_0.conda + sha256: a3ca596feee730ef98015a6c9d6f55749e8634c01c17e7eb2acef8b13b7af483 + md5: 71e18b913d34725cc248d6971517a042 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 10556483 + timestamp: 1790197428579 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-23.1.2-ha770c72_0.conda + sha256: 1365a5fff5c9463b09586ed4cd0b03864083fde070bbbe5320d4ddf70d648ebe + md5: b48086b8f050ef99950bf204d67147a2 + depends: + - compiler-rt23_linux-64 23.1.2 h0e38de2_0 + constrains: + - clang 23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16624 + timestamp: 1790196196963 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-21.1.8-h694c41f_2.conda + sha256: 7a217b3a2f83a059bd9d0297ad27fbf7e2ee61348b41d1b98341103ab29dcade + md5: 21851e90f66ab111ca2b15cc7adcaab4 + depends: + - compiler-rt21_osx-64 21.1.8 h8d5f570_2 + constrains: + - clang 21.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16360 + timestamp: 1787376495927 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-23.1.2-h694c41f_0.conda + sha256: 101d620216e883738286ffd860764cf688161bfce223495d5e9387838a279b70 + md5: e1bf4ad987b73957d917b07532f4cfd0 + depends: + - compiler-rt23_osx-64 23.1.2 h8d5f570_0 + constrains: + - clang 23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16828 + timestamp: 1790197497235 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-21.1.8-hce30654_2.conda + sha256: 05fded2aca8465080c1f2c6fcbeb0039eff1a1cc84e5ff1b61bab360d317117f + md5: 1756ab5909480865183f5eee080e66dd + depends: + - compiler-rt21_osx-arm64 21.1.8 hb8825d9_2 + constrains: + - clang 21.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16400 + timestamp: 1787374964124 +- conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.3-pyhcf101f3_0.conda + sha256: e2753997b8bd34205f42be01b8bab8037423dc30c02a1ec12de23e5b4c0b0a2e + md5: 58638f77697c4f6726753eb8be34818b + depends: + - python >=3.10 + - python + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 303705 + timestamp: 1781320269259 +- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-4.0.12-pyhd8ed1ab_0.conda + sha256: 3ac3221099466ca3bd57bf8cc59c2d92c3b04634a798fbc6c8d1872ac7c55697 + md5: d6556b2fef359c26b25ff003af9ae2c1 + depends: + - python >=3.11 + license: MIT + license_family: MIT + run_exports: {} + size: 85969 + timestamp: 1791210321663 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b + md5: 0c96522c6bdaed4b1566d11387caaf45 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 397370 + timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c + md5: 34893075a5c9e55cdafac56607368fc6 + license: OFL-1.1 + license_family: Other + run_exports: {} + size: 96530 + timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 + md5: 4d59c254e01d9cde7957100457e2d5fb + license: OFL-1.1 + license_family: Other + run_exports: {} + size: 700814 + timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 + md5: 49023d73832ef61042f6a237cb2687e7 + license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 + license_family: Other + run_exports: {} + size: 1620504 + timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 + md5: fee5683a3f04bd15cbd8318b096a27ab + depends: + - fonts-conda-forge + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 3667 + timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda + sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 + md5: a7970cd949a077b7cb9696379d338681 + depends: + - font-ttf-ubuntu + - font-ttf-inconsolata + - font-ttf-dejavu-sans-mono + - font-ttf-source-code-pro + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 4059 + timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.20-pyhd8ed1ab_0.conda + sha256: 6375ae2e28de130843ab7ca98132bf83d988f7fd7034e3dbe646308dbeaca2fd + md5: be9ea4f030b4b2bc121b2a548b066c0b + depends: + - python >=3.11 + - ukkonen + license: MIT + license_family: MIT + run_exports: {} + size: 79783 + timestamp: 1790540591548 +- conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-h9437b0d_0.conda + sha256: a13f35c3eab9527a18baf2f868abe1237f7d43318cdd56bfa5625da662c992c4 + md5: 3173f387121cfdc8099fff71683bfc52 + depends: + - __unix + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 91716 + timestamp: 1787562521736 +- conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-2.3.0-ha8204d5_0.conda + sha256: b5c109276bd8c0bd0399d025126184da4326206f8f69815cde0c171d220e3ffd + md5: c3e760c0fe0d7865cb19e8819788e4b7 + depends: + - __win + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 90943 + timestamp: 1787562530130 +- conda: https://conda.anaconda.org/conda-forge/noarch/jrl-cmakemodules-scripts-2.3.0-pyhcf101f3_0.conda + sha256: fdd68b67fc679fdc5fcf9a7e9feba51f9b52132dca4e0cb78bd4b08527c9a3a2 + md5: 706b2a31ccc96e1af241b9ddfb2d1ad9 + depends: + - python >=3.10 + - tomlkit >=0.11.0 + - ruamel.yaml >=0.17.0 + - rich >=12.0.0 + - packaging >=21.0 + - cmake-parser >=0.1.0 + - python + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 26607 + timestamp: 1787562521736 +- conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + sha256: 41557eeadf641de6aeae49486cef30d02a6912d8da98585d687894afd65b356a + md5: 86d9cba083cd041bfbf242a01a7a1999 + constrains: + - sysroot_linux-64 ==2.28 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + run_exports: {} + size: 1278712 + timestamp: 1765578681495 +- conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-21.1.8-h707e725_4.conda + sha256: cea3b422a9afafa44109ecc10680d9b0b18d1c6dd07a22245862c7ca63b5dd7b + md5: 76fbc135d624924c09afc9bc7b831795 + depends: + - __unix + constrains: + - libcxx-devel 21.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 1131998 + timestamp: 1791301505546 +- conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-23.1.3-h707e725_0.conda + sha256: 988c4834d71fd39bf463a88e464c9653c663f3dcbb75f523b035d8401142b967 + md5: b4ee1da103215d51ffcccc49e48a032c + depends: + - __unix + constrains: + - gxx_osx-arm64 >=14 + - clangxx >=19 + - gxx_osx-64 >=14 + - gxx_linux-64 >=14 + - libcxx-devel 23.1.3 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 1197465 + timestamp: 1791337241645 +- conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.3.0-h2b852eb_107.conda + sha256: 5200a1402eb3c3e9b0e4ba38b3cf163be136d020a15477fb86ce6e754d3ae515 + md5: 057ab488a4da13485caa3b672df9824a + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 3085843 + timestamp: 1790302578256 +- conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.3.0-hb2c5482_107.conda + sha256: 4b2d94a9abf2feedea354e4256756c5dc255b84080e7faed9a324a101cf20e74 + md5: edce245dade1c29f691983796b4b8414 + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 20673146 + timestamp: 1790302599776 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f + md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 + depends: + - mdurl >=0.1,<1 + - python >=3.10 + license: MIT + license_family: MIT + run_exports: {} + size: 69017 + timestamp: 1778169663339 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 + md5: 592132998493b3ff25fd7479396e8351 + depends: + - python >=3.9 + license: MIT + license_family: MIT + run_exports: {} + size: 14465 + timestamp: 1733255681319 +- conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.0.1-pyhd8ed1ab_0.conda + sha256: 70e38b5cfdf4aebf4869dfbe11ae5916a87ce8ff79e9a188a0e0b9bded7d70c9 + md5: 67ac83e3530c217431c5ca85955744dd + depends: + - python >=3.10 + constrains: + - nanobind-abi ==22 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 233710 + timestamp: 1788293984920 +- conda: https://conda.anaconda.org/conda-forge/noarch/nanobind-3.1.0-pyh5ded981_0.conda + sha256: e241962d0dbee1d3f12461830d754344b51bfc4b7ee3715d392d7e262856ae5b + md5: 0a5b25e7072092edf6bd6f10c6a0cd7e + depends: + - python >=3.11 + - python + constrains: + - nanobind-abi ==22 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 248130 + timestamp: 1790169021068 +- conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + sha256: 4fa40e3e13fc6ea0a93f67dfc76c96190afd7ea4ffc1bac2612d954b42cdc3ee + md5: eb52d14a901e23c39e9e7b4a1a5c015f + depends: + - python >=3.10 + - setuptools + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 40866 + timestamp: 1766261270149 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + sha256: c432626b16768b8dab228bfb706f7060c2d462a21c516d240f68f2f902b5a044 + md5: 936687ed80f295a1f5dbcf8bd34c252c + depends: + - python >=3.9 + - python + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 116363 + timestamp: 1785888127370 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.12.3-pyh5ded981_0.conda + sha256: b93a46b1c1fb34a380b0afa309040d603ebefdb8184a87a4bfaeef989a07cbc4 + md5: 96bd08b41fbb94da012c8f5c56132519 + depends: + - python >=3.11 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 33916 + timestamp: 1791121724699 +- conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.6.2-pyha770c72_0.conda + sha256: fc0a0620a8f829c46787a9a13ddbae8b6049f2e77da353a8a2adaa01af0da7e2 + md5: c36b88db560b4e74f294380613f1a239 + depends: + - cfgv >=2.0.0 + - identify >=1.0.0 + - nodeenv >=0.11.1 + - python >=3.10 + - pyyaml >=5.1 + - virtualenv >=20.10.0 + license: MIT + license_family: MIT + run_exports: {} + size: 201879 + timestamp: 1786408353117 +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + sha256: e27e0473fc6723311a0bd48b89b616fa1b996a2f7a2b555338cbbcfb9c640568 + md5: 9c5491066224083c41b6d5635ed7107b + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 55886 + timestamp: 1779293633166 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + sha256: f5f015ff1bc3e1b7fc08eee096b1865234189ae0b82bebdb86a5369116e42fa0 + md5: 2882dee445dfa45b0c5afce3ffb7730a + depends: + - python >=3.10 + - python + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 959376 + timestamp: 1786995678795 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.6.1-pyh5ded981_0.conda + sha256: 396bf7b5a62eb3a12d20e16962acf36f9018332b2842d29548399df03b9deaa4 + md5: ae0feb6a3f297952bd4f4270fe77f530 + depends: + - python >=3.11 + - filelock >=3.15.4 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 39252 + timestamp: 1789811798811 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-9_cp310.conda + build_number: 9 + sha256: 24e01bf97a2f5e608ef2d35547bba12281b5f1c8efecfcfd3447c43abc01342b + md5: 3bb52811c66f1f07377537cc82ccb093 + constrains: + - python 3.10.* *_cpython + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 6774 + timestamp: 1788302826572 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + build_number: 9 + sha256: e7f8e965bbfb98e08feb2365cacdad8bb218fa5b5a0a2752f747287f425f213c + md5: 350d89b50d7de805abf2e63e29dee451 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 6791 + timestamp: 1788302824440 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda + sha256: 3d6ba2c0fcdac3196ba2f0615b4104e532525ffa1335b50a2878be5ff488814a + md5: 0242025a3c804966bf71aa04eee82f66 + depends: + - markdown-it-py >=2.2.0 + - pygments >=2.13.0,<3.0.0 + - python >=3.10 + - typing_extensions >=4.0.0,<5.0.0 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 208577 + timestamp: 1775991661559 +- conda: https://conda.anaconda.org/conda-forge/noarch/ruamel.yaml-0.19.1-pyhcf101f3_0.conda + sha256: b48bebe297a63ae60f52e50be328262e880702db4d9b4e86731473ada459c2a1 + md5: 06ad944772941d5dae1e0d09848d8e49 + depends: + - python >=3.10 + - ruamel.yaml.clib >=0.2.15 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 98448 + timestamp: 1767538149184 +- conda: https://conda.anaconda.org/conda-forge/noarch/sdkroot_env_osx-64-26.0-h62b880e_7.conda + sha256: 7e7e2556978bc9bd9628c6e39138c684082320014d708fbca0c9050df98c0968 + md5: 68a978f77c0ba6ca10ce55e188a21857 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 4948 + timestamp: 1771434185960 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + sha256: 9e200ee5f9ff19a4d94e4b51c4856d53dec849f91032f345cf0c6bc3d51a7183 + md5: 62ac906f1cd582c6c264c95625cb9d6f + depends: + - python >=3.10 + license: MIT + license_family: MIT + run_exports: {} + size: 524488 + timestamp: 1786282924579 +- conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + sha256: c47299fe37aebb0fcf674b3be588e67e4afb86225be4b0d452c7eb75c086b851 + md5: 13dc3adbc692664cd3beabd216434749 + depends: + - __glibc >=2.28 + - kernel-headers_linux-64 4.18.0 he073ed8_9 + - tzdata + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + run_exports: + strong: + - __glibc >=2.28,<3.0.a0 + size: 24008591 + timestamp: 1765578833462 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.15.1-pyhcf101f3_0.conda + sha256: 5cf833b4d199688b7652fb322ecc134de9555e9444d9249750de9a153421ad0a + md5: e4942e2de7436ff28be7f5645cf3c8d6 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 49054 + timestamp: 1784287707171 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + sha256: 2d888f90af0686044882c74193ec80a90ec1943145d94a7b1b048958acda1848 + md5: c70ad746c22219b9700931707482992c + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + run_exports: {} + size: 52631 + timestamp: 1783002732887 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + sha256: b928c30ddcb0e3f544c6eade8352737e6e610e263276b90232db6a578ef899d8 + md5: fcb489df604d100968b737f2cb6076c6 + license: LicenseRef-Public-Domain + run_exports: {} + size: 118849 + timestamp: 1784250406640 +- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.14.5-pyh5ded981_0.conda + sha256: 9b3c5763839d28361c2fa595a0f3fb20537c468e8a30412601b81c5e72b44f8f + md5: 4a2e00093b6a7bdc858e2c377378f32c + depends: + - python >=3.11 + - distlib >=0.3.7,<1 + - filelock >=3.24.2,<5 + - packaging >=23.1 + - platformdirs >=3.9.1,<5 + - python-discovery >=1.6 + - python + license: MIT + license_family: MIT + run_exports: {} + size: 3994945 + timestamp: 1790972539501 +- conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + sha256: b72270395326dc56de9bd6ca82f63791b3c8c9e2b98e25242a9869a4ca821895 + md5: f622897afff347b715d046178ad745a5 + depends: + - __win + license: MIT + license_family: MIT + run_exports: {} + size: 238764 + timestamp: 1745560912727 +- conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-8_kmp_llvm.conda + build_number: 8 + sha256: 09ba32614a1512b729e3cb608b0714c24654f37b5d0f8239bdb77d7be0ede4f7 + md5: b9e2e7fcf1926cedbdb216a6974d67e3 + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - _openmp_mutex >=4.5 + size: 8002 + timestamp: 1788046683209 +- conda: https://conda.anaconda.org/conda-forge/osx-64/atk-1.0-2.38.0-h4bec284_2.conda + sha256: a5972a943764e46478c966b26be61de70dcd7d0cfda4bd0b0c46916ae32e0492 + md5: d9684247c943d492d9aac8687bc5db77 + depends: + - __osx >=10.9 + - libcxx >=16 + - libglib >=2.80.0,<3.0a0 + - libintl >=0.22.5,<1.0a0 + constrains: + - atk-1.0 2.38.0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - atk-1.0 >=2.38.0 + size: 349989 + timestamp: 1713896423623 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-1.0.0-h87af9f7_2.conda + sha256: 782907587566ebc07bed1dc89174eace0fc5705319a98d48357bf44d68ba29d6 + md5: fd99bf11a4f9b0321fe6f2d8c9d61944 + depends: + - __osx >=11.0 + - aws-c-sdkutils >=1.0.0,<1.1.0a0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + - aws-c-http >=1.0.0,<1.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-auth >=1.0.0,<1.0.1.0a0 + size: 121069 + timestamp: 1790928678748 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-1.0.0-h704dcf7_1.conda + sha256: fb089d27dfb099ef1c2b672331b5fc4c3324f808d105e1cd662b63f2ca579b94 + md5: 2e74dbc05fcce10aa8c388a6edc16d7a + depends: + - __osx >=11.0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-cal >=1.0.0,<1.1.0a0 + size: 48908 + timestamp: 1790950045859 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-1.0.2-had63097_0.conda + sha256: 4f6975d2f1c74da8eec3aff7b306894cf7b744ea95b21ded93f9f4cd4e428602 + md5: 067503f4d20059eb0c405f2052e2a101 + depends: + - __osx >=11.0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-common >=1.0.2,<1.1.0a0 + size: 259489 + timestamp: 1790800630396 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-1.0.0-h704dcf7_1.conda + sha256: 9c52b5b95b094f5e54af2bce5aa0d592d39492032fec10877266b0bf5cac28f7 + md5: d7c6ac24b4425085469245f9db43dd9d + depends: + - __osx >=11.0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-compression >=1.0.0,<1.1.0a0 + size: 21960 + timestamp: 1790877787258 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-1.0.0-h71a5ee5_1.conda + sha256: c6785a15e58697614f961274b6b7da1fe12a56a66131bda7658ff98576cdf642 + md5: 1ac429744b1147f397e53e177ec0216e + depends: + - __osx >=11.0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + - aws-c-compression >=1.0.0,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-http >=1.0.0,<1.1.0a0 + size: 198125 + timestamp: 1790884188629 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-1.0.0-h3af93c9_0.conda + sha256: 20b47bf825a855643e5c04005919ad88ede025aae85d1b30277d54014ce8cf51 + md5: 1603c478138591d981ad45e6cb28d6db + depends: + - __osx >=11.0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + - s2n >=1.7.7,<1.7.8.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-io >=1.0.0,<1.1.0a0 + size: 197859 + timestamp: 1790877125834 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-1.0.0-he02826c_1.conda + sha256: 994bda8a9fea7147174a3b863714c81e6d8f9e62e1e985c6e14a8aeeff60951a + md5: 17d724e4a8610965a6fe48f35315ef4d + depends: + - __osx >=11.0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-auth >=1.0.0,<1.0.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + - aws-checksums >=1.0.0,<1.0.1.0a0 + - aws-c-http >=1.0.0,<1.1.0a0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-s3 >=1.0.0,<1.1.0a0 + size: 143905 + timestamp: 1790935733646 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-1.0.0-h704dcf7_1.conda + sha256: 8639c6040ba33a98c49eecf1838f5f5b7cbb2fcfdaa421c199d09c0fd9d55b04 + md5: abfddae0619eeb0f248ba7adcc664380 + depends: + - __osx >=11.0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-sdkutils >=1.0.0,<1.1.0a0 + size: 63064 + timestamp: 1790878604682 +- conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-1.0.0-h704dcf7_0.conda + sha256: c5de0296aa4e8811ec5831fe823d360b28dd697c039ccadc814d38ae5ab60c32 + md5: 3c9bc13abb2df0b2a3c23aa7a3a0e766 + depends: + - __osx >=11.0 + - aws-c-common >=1.0.1,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-checksums >=1.0.0,<1.0.1.0a0 + size: 96278 + timestamp: 1790400260721 +- conda: https://conda.anaconda.org/conda-forge/osx-64/binutils-1.0.1-0.tar.bz2 + sha256: bb198bc7df6dcdd2f1344642000669a56585f3a32ea4ce30d330f20c9e7bd364 + md5: 81de342aeec55f3ba88cec426f084c12 + depends: + - cctools + - ld64 + license: BSD + run_exports: {} + size: 6151 + timestamp: 1549965667543 +- conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda + sha256: 4ed83961876dc8844a6f0df49c07b408efbaea275ffb0b37133e24c006990b3a + md5: 9d9a39212a876e4bb751c1cc3927b678 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 133271 + timestamp: 1785906721507 +- conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.8-had63097_2.conda + sha256: a00162ac4b2f68a6ddf23905e9d2fdb3ecd5abad51659f512539952a780d53ed + md5: 925ff9ab74f4b9262a28842766e9e7b1 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - c-ares >=1.34.8,<2.0a0 + size: 205559 + timestamp: 1787170041830 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cairo-1.18.6-h5791faa_0.conda + sha256: 5f7bf2bfd42cb6d955b196d5ab9ba74c1bb075977703aafd244c0af6f9c6cee2 + md5: 0f4816120b8af052d460ad3262b450c6 + depends: + - __osx >=11.0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.3,<79.0a0 + - libcxx >=21 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - pixman >=0.46.4,<1.0a0 + license: LGPL-2.1-only or MPL-1.1 + run_exports: + weak: + - cairo >=1.18.6,<2.0a0 + size: 866318 + timestamp: 1790045989668 +- conda: https://conda.anaconda.org/conda-forge/osx-64/catch2-3.16.0-h66869c8_0.conda + sha256: b9fa3eec13d9fffbac6b5c7b0c9e4df4c590c41a270ee8f25c3f523a50beab2d + md5: c544458e510267dbab208f53808daefb + depends: + - __osx >=11.0 + - libcxx >=21 + license: BSL-1.0 + run_exports: + weak: + - catch2 >=3.16.0,<4.0a0 + size: 541689 + timestamp: 1787658516015 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ccache-4.14.1-hfd753c7_0.conda + sha256: 7d0cce876f249031d477e012e634cefbc83b56ed0f6d6de756b0a0c242305de5 + md5: dc876f43a251dbe113003448510ea72e + depends: + - libcxx >=21 + - __osx >=11.0 + - libhiredis >=1.3.0,<1.4.0a0 + - zstd >=1.5.7,<1.6.0a0 + - xxhash >=0.8.3,<0.8.4.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 674050 + timestamp: 1790515780567 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm21_1_he201b2c_6.conda + sha256: 4016b35a39d89471c4611eed9bc2750721fee3931c233563c6641d0f709aaf37 + md5: e1b6cb9193cf93945865b9d4cbd107fc + depends: + - cctools_impl_osx-64 1030.6.3 llvm21_1_hd9d6719_6 + - ld64 956.6 llvm21_1_h2eed689_6 + - libllvm21 >=21.1.8,<21.2.0a0 + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 24155 + timestamp: 1787727109865 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm23_1_h254e556_6.conda + sha256: 386336eab60ff2cbd2dbd510c015400b7d9f6263411c0297860e508261c68ed6 + md5: 33152a8d1e2e64ab0840799ee5ea06fd + depends: + - cctools_impl_osx-64 1030.6.3 llvm23_1_h3bd330e_6 + - ld64 956.6 llvm23_1_h0b736ef_6 + - libllvm23 >=23.1.0,<23.2.0a0 + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 24291 + timestamp: 1787725217090 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm21_1_hd9d6719_6.conda + sha256: 35db4a8d760bb58a15bdceb5713ae91ffbae2d02a80541b1589f63bf35b5d0a6 + md5: 96d18058f12b0335e1754a5242675029 + depends: + - __osx >=11.0 + - ld64_osx-64 >=956.6,<956.7.0a0 + - libcxx + - libllvm21 >=21.1.8,<21.2.0a0 + - libzlib >=1.3.2,<2.0a0 + - llvm-tools 21.1.* + - sigtool-codesign + constrains: + - cctools 1030.6.3.* + - clang 21.1.* + - ld64 956.6.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 751705 + timestamp: 1787727078539 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6.conda + sha256: 318a4ce9253a4808283b35dd09e1db36e07751a1a4ce1dc00312b00ae932e3c8 + md5: 5f7730ce84d5e1ce37e67376b099e8a5 + depends: + - __osx >=11.0 + - ld64_osx-64 >=956.6,<956.7.0a0 + - libcxx + - libllvm23 >=23.1.0,<23.2.0a0 + - libzlib >=1.3.2,<2.0a0 + - llvm-tools 23.1.* + - sigtool-codesign + constrains: + - cctools 1030.6.3.* + - clang 23.1.* + - ld64 956.6.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 752844 + timestamp: 1787725181784 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-1030.6.3-llvm23_1_h254e556_6.conda + sha256: e84d7bac69e270d023b60e37dfed73bd9617137d91be69cae39816f6e00604c3 + md5: d049b4612fa0f34f967aae0bf53b386c + depends: + - cctools_impl_osx-64 1030.6.3 llvm23_1_h3bd330e_6 + - ld64_osx-64 956.6 llvm23_1_h484b24f_6 + constrains: + - cctools 1030.6.3.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 23531 + timestamp: 1787725221261 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.1.1-py314h0656537_3.conda + sha256: 493eb10ddcd00cf42151f1a6303b5b08a3641172861583fe2e128e9bbc1db3e2 + md5: 5502c80a2761fbc926dc5847b69b7f53 + depends: + - __osx >=11.0 + - libffi >=3.7.0,<3.8.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 292318 + timestamp: 1788485600231 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21-21.1.8-default_h0a1f3f9_6.conda + sha256: 1e271e119bca842c0a02bdc4210a718c0ad152b0d320d6f2fc2e3fab13925c2f + md5: 4a5d91e8c3231198da749d5b8fbc82d0 + depends: + - __osx >=11.0 + - compiler-rt21 21.1.8.* + - libclang-cpp21.1 21.1.8 default_h0a1f3f9_6 + - libcxx >=21.1.8 + - libllvm21 >=21.1.8,<21.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 825172 + timestamp: 1787464823871 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-21.1.8-default_cfg_he3ef750_6.conda + sha256: 2cbc1c6a50c95a071c4b5570290dacec63a7181a2489f37a1c5abb8ea85bc7c5 + md5: 9c81ef549b07847bf5215341ed5769cf + depends: + - cctools + - clang-21 21.1.8.* default_* + - clang_impl_osx-64 21.1.8 default_ha1a018a_6 + - ld64 + - ld64_osx-64 * llvm21_1_* + - llvm-openmp >=21.1.8 + - llvm-tools 21.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28541 + timestamp: 1787464930535 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-23-23.1.2-default_h3065a3b_0.conda + sha256: b845ff3a9f3725face10ccf56582405fe5d4e97d4679f33bcc2892f4e4c55930 + md5: 731ba6bac2fe9f1abaca07f149bd13fe + depends: + - compiler-rt23 ==23.1.2 + - libclang-cpp23.1 ==23.1.2 default_h6e863b9_0 + - libcxx >=23.1.2 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - libclang-cpp23.1 >=23.1.2,<23.2.0a0 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 956761 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-23.1.2-default_cfg_hcbdff81_0.conda + sha256: 02e2cf73af313219166452f98befa873c6109555a21856af18e056955a4e5df9 + md5: 290d6e8bdfb156d8f9dcf2fed6bc008e + depends: + - clang-23 ==23.1.2 default_* + - llvm-openmp >=23.1.2 + - clang_impl_osx-64 ==23.1.2 default_h6e863b9_0 + - cctools + - ld64 + - ld64_osx-64 * llvm23_1_* + - llvm-tools ==23.1.2 + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 32309 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-21.1.8-default_h0a1f3f9_6.conda + sha256: 6a4100c9976fba7daa8d640f85760d9fa5eb7149963f5459307956954b93143d + md5: c731842720fa8b40764105c2e1f90e82 + depends: + - __osx >=11.0 + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 + - libclang13 >=21.1.8 + - libcxx >=21.1.8 + - libllvm21 >=21.1.8,<21.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 108492 + timestamp: 1787464912272 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-23.1.2-default_h6e863b9_0.conda + sha256: a587f276042f1ca56da7fd6f7e13db7d4da22d5b6c05d8bf7f38301c91971e4b + md5: b04eccf52db029f03b3ac60a3cdb99e0 + depends: + - libclang13 >=23.1.2 + - libclang-cpp23.1 >=23.1.2,<23.2.0a0 + - libcxx >=23.1.2 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 122844 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-21.1.8-default_ha1a018a_6.conda + sha256: 8ac4ab60fa711fe7efc709702e9a6d537391147747afc00e6080c2f6d18481f8 + md5: 3ab6196fe9cc75e1595e60371701b708 + depends: + - cctools_impl_osx-64 + - clang-21 21.1.8.* default_* + - compiler-rt 21.1.8.* + - compiler-rt_osx-64 21.1.8.* + - ld64_osx-64 * llvm21_1_* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28105 + timestamp: 1787464916479 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-23.1.2-default_h6e863b9_0.conda + sha256: c55b59c17a59de3bfd0eddacf2c6179940b882a47bafbdc9d42cdab473f10584 + md5: 0f35bbd59acef03831220708b32fa779 + depends: + - clang-23 ==23.1.2 default_* + - compiler-rt_osx-64 ==23.1.2 + - compiler-rt ==23.1.2 + - cctools_impl_osx-64 + - ld64_osx-64 * llvm23_1_* + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 31870 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang_osx-64-23.1.2-h11c87bf_34.conda + sha256: c0d3b2fb80e33ae53a03829572f83aaca8f9d850d02bb4bddb507e69b5ad17d0 + md5: b77a581bc2220224b832537d1858e283 + depends: + - cctools_osx-64 + - clang_impl_osx-64 23.1.2.* + - sdkroot_env_osx-64 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 20602 + timestamp: 1791335640046 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-21.1.8-default_cfg_he3ef750_6.conda + sha256: a9852e6e9ec539a8c75d6b7a031dfedbdc1f79f9ebbecb6d66adaf6578945e0c + md5: c0296fa5fb0e0c00a7bd7d44696d52be + depends: + - clang 21.1.8 default_cfg_he3ef750_6 + - clangxx_impl_osx-64 21.1.8.* default_* + - libcxx-devel 21.1.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28301 + timestamp: 1787465070892 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-23.1.2-default_cfg_h2b485f0_0.conda + sha256: f4c903ab46a89051c1d014b95a1c649e41c5bdb608155b172fcd23f1c9ee3cf9 + md5: 687a5105ff53a950c0a94e2e0f61a6f7 + depends: + - clang ==23.1.2 default_cfg_hcbdff81_0 + - clangxx_impl_osx-64 ==23.1.2 default_* + - libcxx-devel 23.1.* + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 32320 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-21.1.8-default_ha1a018a_6.conda + sha256: a8ab800a64e1bb1e73f0b59888551138b8184366ad6b8bec6eb5b30d9df3e70f + md5: 26765cf58312caac1f3a9bd16fd4631d + depends: + - clang-21 21.1.8.* default_* + - clang-scan-deps 21.1.8 default_h0a1f3f9_6 + - clang_impl_osx-64 21.1.8 default_ha1a018a_6 + - libcxx-devel 21.1.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28083 + timestamp: 1787465053689 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-23.1.2-default_hf9996f3_0.conda + sha256: a48098c2e05b661efbd3293f3c46962aa518cce4738d7e55f3fe22deecc510a6 + md5: f310d7a7a8a4c28bd213b8c47cbec088 + depends: + - clang-23 ==23.1.2 default_* + - clang_impl_osx-64 ==23.1.2 default_h6e863b9_0 + - clang-scan-deps ==23.1.2 default_h6e863b9_0 + - libcxx-devel 23.1.* + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 31950 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-23.1.2-h11c87bf_34.conda + sha256: 0e2a44cc5f4f098404e2d745b3ecf90b43cbddf2dd18dde1ad3bd987d2cd89fe + md5: 547f7cb9e1cab5bdf64d3575e2bad6e1 + depends: + - cctools_osx-64 + - clang_osx-64 23.1.2 h11c87bf_34 + - clangxx_impl_osx-64 23.1.2.* + - sdkroot_env_osx-64 + license: BSD-3-Clause + license_family: BSD + run_exports: + strong: + - libcxx >=23 + size: 19308 + timestamp: 1791335646916 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-4.4.4-haddf760_0.conda + sha256: 6973460a5a959ce96f4fe088f714bd658157049ec2a2296d4d89ed06891a9272 + md5: 3f03303ad0f0d251431ba8c2e533b555 + depends: + - __osx >=11.0 + - libcxx >=21 + - libexpat >=2.8.5,<3.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libcurl >=8.22.0,<9.0a0 + - libuv >=1.52.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - rhash >=1.4.6,<2.0a0 + - bzip2 >=1.0.8,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - ncurses >=6.6,<7.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 21895312 + timestamp: 1791001335825 +- conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-21.1.8-h694c41f_2.conda + sha256: 49c28d032422d448dfd7e8c6d8448eebf9cceb37fbb1b03f504208c59fc25588 + md5: baeaff063c802078b3d1120b1185fd82 + depends: + - compiler-rt21 21.1.8 h8c1e6b9_2 + - libcompiler-rt 21.1.8 h8c1e6b9_2 + constrains: + - clang 21.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16210 + timestamp: 1787376497825 +- conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-23.1.2-h694c41f_0.conda + sha256: be8fe7a2c142b10f4bb88b01f6e8b8691069c297a13ac34f14113ad7f94efaf7 + md5: b5a04b3f526b94b23baceda3097a7734 + depends: + - compiler-rt23 23.1.2 h8c1e6b9_0 + - libcompiler-rt 23.1.2 h8c1e6b9_0 + constrains: + - clang 23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16692 + timestamp: 1790197498709 +- conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt21-21.1.8-h8c1e6b9_2.conda + sha256: 7120ffa3f3a4e54b685235034573ba4045ec236c6c768db4cc3bee095578e06e + md5: f5c49fb09d03f6b142ad7b6927bbb20e + depends: + - __osx >=11.0 + - compiler-rt21_osx-64 21.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 99479 + timestamp: 1787376494153 +- conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt23-23.1.2-h8c1e6b9_0.conda + sha256: c05f82f29f66254a3f3f391d8d73beed669e22932358065939700b070fd07de7 + md5: 14ddc1f56f2b76fb2914273edf0b4e10 + depends: + - __osx >=11.0 + - compiler-rt23_osx-64 23.1.2.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 101031 + timestamp: 1790197495268 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.0.1-h04f5b5a_0.tar.bz2 + sha256: 3585e3ce4be4e0406bba6cad971acac8bc71d07e83c421f2fb0378fe0a25a0cd + md5: db2cff0cc2d413ac1a5e5759d5143d80 + depends: + - binutils 1.0.1 0 + - clangxx_osx-64 + - libcxx >=4.0.1 + license: BSD + run_exports: {} + size: 4472 + timestamp: 1549965747048 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-2.0.0-h94bea0c_0.conda + sha256: ed55ac3f0c67048c4621df042d611a42a1b8e4ff567b8dd1b2c1d3ed6ec8d515 + md5: b0ff17d7d1909900ffb7d00fb6db3510 + depends: + - clangxx 21.* + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 6997 + timestamp: 1786642665547 +- conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.18.0-py310h9e984d5_0.conda + sha256: dc4e3f25c4eeffdab0b3c4a8ade42e36161c0880d1f9645afb6f2d7af868e694 + md5: 204bea725cc0b8aa4fd9fb6b78088f7a + depends: + - libiconv + - libcxx >=21 + - __osx >=11.0 + - libiconv >=1.18,<2.0a0 + license: GPL-2.0-only + license_family: GPL + run_exports: {} + size: 15518140 + timestamp: 1788247350040 +- conda: https://conda.anaconda.org/conda-forge/osx-64/eigen-5.0.1-h8a113fb_3.conda + sha256: ba86a7f709b6cc5bc7bbc1bf0351e9575bf1f712440e616c17cf07c29f8351ac + md5: 22a2638b8ff371e1e96ad8236633f50b + license: MPL-2.0 + license_family: MOZILLA + run_exports: {} + size: 1313761 + timestamp: 1788951438110 +- conda: https://conda.anaconda.org/conda-forge/osx-64/epoxy-1.5.10-h8616949_2.conda + sha256: d5c466bddf423a788ce5c39af20af41ebaf3de9dc9e807098fc9bf45c3c7db45 + md5: efe7fa6c60b20cb0a3a22e8c3e7b721e + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + run_exports: + weak: + - epoxy >=1.5.10,<1.6.0a0 + size: 283016 + timestamp: 1758743470535 +- conda: https://conda.anaconda.org/conda-forge/osx-64/fontconfig-2.18.3-h7f3b9c9_1.conda + sha256: 4637141fa4f3a0f9b58afe4bda831adcb6964495600e97e7e2ed9763cd4f7eda + md5: beb62955ee805eff50e364f86ca2ee5c + depends: + - __osx >=11.0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libintl >=0.25.1,<1.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + size: 264035 + timestamp: 1786668314489 +- conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.14.3-h694c41f_2.conda + sha256: a9f6d77b27b67e681d4b3e214a0861a9d4aa87e0e824d8ef6c5bbfcf0cbb556e + md5: 570430c9aa9a903221d33e393dd21059 + depends: + - libfreetype 2.14.3 h694c41f_2 + - libfreetype6 2.14.3 h8afe040_2 + license: GPL-2.0-only OR FTL + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + size: 174876 + timestamp: 1786641723387 +- conda: https://conda.anaconda.org/conda-forge/osx-64/fribidi-1.0.17-hd115831_0.conda + sha256: 2d00bba4debd24538f030464507ed73369483ec69c02b9cef110945b9569ffa4 + md5: de3916de5b702b60b8e1a860869ecfdd + depends: + - __osx >=11.0 + license: LGPL-2.1-or-later + run_exports: + weak: + - fribidi >=1.0.17,<2.0a0 + size: 64612 + timestamp: 1790012239389 +- conda: https://conda.anaconda.org/conda-forge/osx-64/gdk-pixbuf-2.44.8-ha3e70bd_2.conda + sha256: a8ee577125a9213dc0c206d15497887d01b347fbf957e0951e48f146e187b0aa + md5: 6af16e46e2930c557108bbbed884eebf + depends: + - __osx >=11.0 + - libglib >=2.88.3,<3.0a0 + - libintl >=0.25.1,<1.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libtiff >=4.7.2,<4.8.0a0 + license: LGPL-2.1-or-later + license_family: LGPL + run_exports: + weak: + - gdk-pixbuf >=2.44.8,<3.0a0 + size: 554833 + timestamp: 1788491118420 +- conda: https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.90.0-he718cb3_0.conda + sha256: dc45ed9bb0f7b9014167177b94f9b82c58ff471345983e7a7c4462bd8347d679 + md5: 676efb4acf2e7279104c32d4154c2bd2 + depends: + - libglib ==2.90.0 h7e55108_0 + - libffi + - __osx >=11.0 + - libintl >=0.25.1,<1.0a0 + license: LGPL-2.1-or-later + run_exports: {} + size: 213956 + timestamp: 1789478206873 +- conda: https://conda.anaconda.org/conda-forge/osx-64/graphite2-1.3.15-h2fb4741_1.conda + sha256: 8cc44569368289870f3cfe4a56f543ec15468398133545eae8d8c3ca4ef87774 + md5: 540c672170d018be5d460cfa784c5326 + depends: + - __osx >=11.0 + - libcxx >=19 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 + size: 91460 + timestamp: 1786118565040 +- conda: https://conda.anaconda.org/conda-forge/osx-64/graphviz-14.1.2-h44fc223_0.conda + sha256: dd6a5e3599a2e07c04f4d33e61ecd5c26738eee9e88b9faa1da0f8b062ac9ca3 + md5: 4c1c78d65d867d032c07303cf38117ba + depends: + - __osx >=10.13 + - adwaita-icon-theme + - cairo >=1.18.4,<2.0a0 + - fonts-conda-ecosystem + - gdk-pixbuf >=2.44.4,<3.0a0 + - gtk3 >=3.24.43,<4.0a0 + - gts >=0.7.6,<0.8.0a0 + - libcxx >=19 + - libexpat >=2.7.3,<3.0a0 + - libgd >=2.3.3,<2.4.0a0 + - libglib >=2.86.3,<3.0a0 + - librsvg >=2.60.0,<3.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - pango >=1.56.4,<2.0a0 + license: EPL-1.0 + license_family: Other + run_exports: + weak: + - graphviz >=14.1.2,<15.0a0 + size: 2297868 + timestamp: 1769427939677 +- conda: https://conda.anaconda.org/conda-forge/osx-64/gtk3-3.24.52-hf2d442a_0.conda + sha256: c69a03b1eec71c0a764658d67f81eaf9a316276ae900b107cd8d77766bc13cf8 + md5: 76be17e448c23c6d1c99a56c15b15925 + depends: + - __osx >=11.0 + - atk-1.0 >=2.38.0 + - cairo >=1.18.4,<2.0a0 + - epoxy >=1.5.10,<1.6.0a0 + - fribidi >=1.0.16,<2.0a0 + - gdk-pixbuf >=2.44.5,<3.0a0 + - glib-tools + - harfbuzz >=13.2.1 + - hicolor-icon-theme + - libexpat >=2.7.4,<3.0a0 + - libfreetype >=2.14.2 + - libfreetype6 >=2.14.2 + - libglib >=2.86.4,<3.0a0 + - libintl >=0.25.1,<1.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - pango >=1.56.4,<2.0a0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - gtk3 >=3.24.52,<4.0a0 + - adwaita-icon-theme + size: 5269457 + timestamp: 1774289309822 +- conda: https://conda.anaconda.org/conda-forge/osx-64/gts-0.7.6-h53e17e3_4.conda + sha256: d5b82a36f7e9d7636b854e56d1b4fe01c4d895128a7b73e2ec6945b691ff3314 + md5: 848cc963fcfbd063c7a023024aa3bec0 + depends: + - libcxx >=15.0.7 + - libglib >=2.76.3,<3.0a0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - gts >=0.7.6,<0.8.0a0 + size: 280972 + timestamp: 1686545425074 +- conda: https://conda.anaconda.org/conda-forge/osx-64/harfbuzz-14.6.0-h694c41f_1.conda + sha256: 4bb6ed8961477d04d86b20f4b162f2b30f7e4a6fbc152f97da1190a86d6aedf8 + md5: 51a2ceb7070e070c34822d73c38c2180 + depends: + - libharfbuzz-devel 14.6.0 h2974713_1 + license: MIT + run_exports: + weak: + - libharfbuzz >=14.6.0 + size: 11100 + timestamp: 1791336976507 +- conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-2.2.0-nompi_ha76ad8a_101.conda + sha256: 60c91413d4fb6ae4115befdf20c43877fda7a763fff2592746be9c81995c2640 + md5: 00afc427a521b8e8bb7cdfee4bf63902 + depends: + - __osx >=11.0 + - aws-c-auth >=1.0.0,<1.0.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + - aws-c-http >=1.0.0,<1.1.0a0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-s3 >=1.0.0,<1.1.0a0 + - aws-c-sdkutils >=1.0.0,<1.1.0a0 + - libaec >=1.1.5,<2.0a0 + - libcurl >=8.22.0,<9.0a0 + - libcxx >=21 + - libgcc >=15 + - libgfortran + - libgfortran5 >=15.3.0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.8,<4.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - hdf5 >=2.2.0,<3.0a0 + size: 4298381 + timestamp: 1790975107570 +- conda: https://conda.anaconda.org/conda-forge/osx-64/hicolor-icon-theme-0.17-h694c41f_3.conda + sha256: 3321e8d2c2198ac796b0ae800473173ade528b49f84b6c6e4e112a9704698b41 + md5: 690e5077aaccf8d280a4284d7c9ec6b4 + license: GPL-2.0-or-later + license_family: GPL + run_exports: {} + size: 17650 + timestamp: 1771539977217 +- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-py313hbf1d544_2.conda + sha256: 3abd86f3441f143b6b3203c92ae0d88dd8396a8857940af468f1fab854cdae57 + md5: f13f4740c18b562bf2662d494bad6099 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14223209 + timestamp: 1786545868538 +- conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h69064fd_2.conda + sha256: f41875ab241c4862b6bdb8316e5f4268ee8ff9e9115770d3d30a02028957c7c1 + md5: da54bd0f3b96eb0d7663b3db01862a19 + depends: + - __osx >=11.0 + - libcxx >=21 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 1199337 + timestamp: 1786762832264 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm21_1_h2eed689_6.conda + sha256: 89558916b01fbf1de7387de8af4cfbafb280f690f627ffd56527cef8f7704a7e + md5: 9444d5013b746c23136d9f83dada6b33 + depends: + - ld64_osx-64 956.6 llvm21_1_hb373d2a_6 + - libllvm21 >=21.1.8,<21.2.0a0 + constrains: + - cctools 1030.6.3.* + - cctools_osx-64 1030.6.3.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 21577 + timestamp: 1787727094899 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm23_1_h0b736ef_6.conda + sha256: 11a6c36fd6207683a57d5e91533d3ce1756c1fc7e2a30504de8686ac867a8f0b + md5: 1df57ff12656ea5b11345b05a902460f + depends: + - ld64_osx-64 956.6 llvm23_1_h484b24f_6 + - libllvm23 >=23.1.0,<23.2.0a0 + constrains: + - cctools 1030.6.3.* + - cctools_osx-64 1030.6.3.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 21611 + timestamp: 1787725200087 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm21_1_hb373d2a_6.conda + sha256: a74481c5033e374bb6ec6bebff4135fd3b34ab7b16284904e6ff2d1401e51eb1 + md5: 6f153cd18155d7c1d71a01b250b8c2d1 + depends: + - __osx >=11.0 + - libcxx + - libllvm21 >=21.1.8,<21.2.0a0 + - sigtool-codesign + - tapi >=1600.0.11.8,<1601.0a0 + constrains: + - cctools 1030.6.3.* + - cctools_impl_osx-64 1030.6.3.* + - clang 21.1.* + - ld64 956.6.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 1044920 + timestamp: 1787727005961 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm23_1_h484b24f_6.conda + sha256: 36c603caf2a7f65ae9f0ce4acbf7afde49357bdcea65b28ca7aefd9cf46c1f5a + md5: 27009650a65db7f0faca68367a06b9f7 + depends: + - __osx >=11.0 + - libcxx + - libllvm23 >=23.1.0,<23.2.0a0 + - sigtool-codesign + - tapi >=1600.0.11.8,<1601.0a0 + constrains: + - cctools 1030.6.3.* + - cctools_impl_osx-64 1030.6.3.* + - clang 23.1.* + - ld64 956.6.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 1048502 + timestamp: 1787725115201 +- conda: https://conda.anaconda.org/conda-forge/osx-64/lerc-4.2.0-h35c7297_0.conda + sha256: 5ae9e18ec7f8134a009765bd1454687d5057482fbe9a4c661a672746d4a29b0b + md5: 09e24eb1868a9ffc04130730e7a34a59 + depends: + - __osx >=11.0 + - libcxx >=19 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - lerc >=4.2.0,<5.0a0 + size: 217900 + timestamp: 1785036771895 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libaec-1.1.5-he7c3a48_0.conda + sha256: b42ac9c684c730cb97cb3931a0a97aaf791da38bace4f6944eca10de609e5946 + md5: 975f98248cde8d54884c6d1eb5184e13 + depends: + - __osx >=10.13 + - libcxx >=19 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libaec >=1.1.5,<2.0a0 + size: 30555 + timestamp: 1769222189944 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.11.0-11_he492b99_openblas.conda + build_number: 11 + sha256: d5e1a84f24990086f04dcb0155cc0df7a02ea0edae522c1a0dbd4d099c38e398 + md5: 37f29370fe4ad22f66a8fe4d8fb91b67 + depends: + - libopenblas >=0.3.34,<0.3.35.0a0 + - libopenblas >=0.3.34,<1.0a0 + constrains: + - blas 2.311 openblas + - libcblas 3.11.0 11*_openblas + - liblapack 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + - mkl <2027 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 + size: 18317 + timestamp: 1789061751704 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.11.0-11_h9b27e0a_openblas.conda + build_number: 11 + sha256: 0e76c359907461f9701b3cbac2c7911ad174a2ab5758247747ce1695a291e7c3 + md5: 88a6541bdc26d9e146f37520fad2e415 + depends: + - libblas 3.11.0 11_he492b99_openblas + constrains: + - blas 2.311 openblas + - liblapack 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 + size: 18289 + timestamp: 1789061763737 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp21.1-21.1.8-default_h0a1f3f9_6.conda + sha256: 6dbb78847b57b0c236b723b104a116aa9844b1abab79948e459d303c1d75f3df + md5: 84855bac76cb55bdc72e8fe4a9ce008d + depends: + - __osx >=11.0 + - libcxx >=21.1.8 + - libllvm21 >=21.1.8,<21.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 + size: 14492801 + timestamp: 1787464712817 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda + sha256: 491c85fac38f91060802761e59e3a1505ee738ed2849504e8d0f3ecf0c520537 + md5: 1eeb55e2946940f2406f5a5ec8d1fe1c + depends: + - libcxx >=23.1.2 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libclang-cpp23.1 >=23.1.2,<23.2.0a0 + size: 17900555 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda + sha256: 0dfe44aa4d56eae2ac5832a611ce1167d44ff17181c85596de01e149c04af01c + md5: e9fb94e71bc84291b105bec0df234ea1 + depends: + - libclang-cpp23.1 ==23.1.2 default_h6e863b9_0 + - libcxx >=23.1.2 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libclang13 >=23.1.2 + size: 11366158 + timestamp: 1790242163192 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-21.1.8-h8c1e6b9_2.conda + sha256: 7613a1a6085d287a3607529e64f3aeafc9af26c79d3e916baffc9e629830bb40 + md5: 5dbe869e022b709ec049a081a448eb90 + depends: + - __osx >=11.0 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libcompiler-rt >=21.1.8 + size: 1331129 + timestamp: 1787376477388 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-23.1.2-h8c1e6b9_0.conda + sha256: ff0e2bc0217a46aba323edb4b61dcd29ea333ab344735a93de5f9bf140a34fa8 + md5: 1f77d8bba65ad84d0d7b4563776fbb02 + depends: + - __osx >=11.0 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libcompiler-rt >=23.1.2 + size: 1378986 + timestamp: 1790197472223 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.22.0-h5318221_0.conda + sha256: 5625672a0a27c58c1c3c5849927c226eb65c88900e778262284e843dcce9c8f8 + md5: 0ba721f8549bac02c48fc646fffe0c4d + depends: + - __osx >=11.0 + - krb5 >=1.22.2,<1.23.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libpsl >=0.23.1,<0.24.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.8,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + run_exports: + weak: + - libcurl >=8.22.0,<9.0a0 + size: 439790 + timestamp: 1788341693572 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.3-h19cb2f5_0.conda + sha256: 19ec3adf903c04aac6f31b180d283f0beb6d0393c5c1603f1d57355eb3a8fd66 + md5: 55664c771bbae09ac41bd7c940c3a7e1 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 573303 + timestamp: 1791337833929 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-21.1.8-h7c275be_4.conda + sha256: 387556f7b09234f08dcd9a55b6b07c168f1b4060aabf0e5f1de58798632c57ed + md5: 3e895be4f48daba7afd5cab935cccd5d + depends: + - libcxx >=21.1.8 + - libcxx-headers >=21.1.8,<21.1.9.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 23848 + timestamp: 1791301821056 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-23.1.3-h7c275be_0.conda + sha256: ab128442eef431ff9bb49e18308bb3076514b4a33719d656ca1d00d31a0ff4d8 + md5: 0f45e0de241fe06680b227c9ff3158f6 + depends: + - libcxx >=23.1.3 + - libcxx-headers >=23.1.3,<23.1.4.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 21915 + timestamp: 1791337855688 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.25-h7ad9622_1.conda + sha256: 210ee1d6a5aa201cf6d02b10edd02738cc35a4e8fb0866e4fb425010d6dd2c49 + md5: 371a45a962d740d8191d46dd225e23df + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 + size: 71148 + timestamp: 1785909042684 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20260512-pl5321hba2e2ab_0.conda + sha256: 3b664a2fcc69b0e2ed6622bfacdf408a31003e92191ace3f4f1ab086c384449d + md5: f9fefe52ca6fa0cdb62806f626b70d98 + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: BSD-2-Clause + run_exports: + weak: + - libedit >=3.1.20260512,<3.2.0a0 + size: 116143 + timestamp: 1791327578296 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-ha3d0635_3.conda + sha256: 223314a7476bdeb00f698937b6960fc51cb98627af2ac5a629e5150bcddb8abf + md5: 6d2f0447151b390bdaed846e143272e3 + depends: + - __osx >=11.0 + license: BSD-2-Clause OR GPL-2.0-or-later + license_family: GPL + run_exports: + weak: + - libev >=4.33,<4.34.0a0 + size: 40479 + timestamp: 1785917395373 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.5-h6e061ac_0.conda + sha256: c58d84e9455db8161fa6a2413c1bf11de30682c02f9a3c1ddfaf24ea73dbe10f + md5: 082b0cec641dcb5bbf71d2aa4b37bfd4 + depends: + - __osx >=11.0 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 75347 + timestamp: 1790370393156 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h6b3a05b_1.conda + sha256: c4793041226c87f987b9903e6503b76f02f52855cc193be2729ac127e600529b + md5: e077b71ae65754eda067e4125364b905 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 60786 + timestamp: 1787754056669 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype-2.14.3-h694c41f_2.conda + sha256: cabaa404fde84dcf154c3394f7a86cbaa7cff1ce32e3951b0b6aad567c457e3f + md5: d2538644f6f7f8b9ce10bdffaa7d3d17 + depends: + - libfreetype6 >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 8384 + timestamp: 1786641705015 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libfreetype6-2.14.3-h8afe040_2.conda + sha256: 9c81d42ca311a1283fb8f79d05dae5659d86cf20f4e5d146a97836456537ccff + md5: cb777bcdd21bcfcfdaf76ebe1e1e0488 + depends: + - __osx >=11.0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - freetype >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 366001 + timestamp: 1786641701324 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-16.2.0-h13771c8_7.conda + sha256: 9b41fcce83df18224b3a3157d757bf0fc08c6f975e228d0049c0701d3e584faa + md5: 80bbe7ebcdfa9cd4507383087c1e5959 + depends: + - _openmp_mutex + constrains: + - libgcc-ng ==16.2.0=*_7 + - libgomp 16.2.0 7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 390794 + timestamp: 1790305700481 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgd-2.3.3-hb2c11ec_12.conda + sha256: bf7b0c25b6cca5808f4da46c5c363fa1192088b0b46efb730af43f28d52b8f04 + md5: e12673b408d1eb708adb3ecc2f621d78 + depends: + - __osx >=10.13 + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.1,<79.0a0 + - libexpat >=2.7.3,<3.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + - libiconv >=1.18,<2.0a0 + - libjpeg-turbo >=3.1.2,<4.0a0 + - libpng >=1.6.53,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + license: GD + license_family: BSD + run_exports: + weak: + - libgd >=2.3.3,<2.4.0a0 + size: 163145 + timestamp: 1766332198196 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-16.2.0-h7e5c614_7.conda + sha256: 73ca26e786bb3ea011ecc3fb763469cea5a371347bdff504075e457141a80754 + md5: efff7b31ffdf1b64c2c4a8b5f89e9fc0 + depends: + - libgfortran5 16.2.0 h2539e6c_7 + constrains: + - libgfortran-ng ==16.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 100012 + timestamp: 1790305892235 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-16.2.0-h2539e6c_7.conda + sha256: 5749bacc1a5bf6c9933623399742c4d4c148299a5fe0d7b3fa7a93e93606e8b7 + md5: 28e49e55dd8fd418e95b14ba1d2cd884 + depends: + - libgcc >=16.2.0 + constrains: + - libgfortran 16.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 1023547 + timestamp: 1790305708501 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libglib-2.90.0-h7e55108_0.conda + sha256: 68091b433dfa7105c294be490ab35803e287d9c50190e9f6654d2c209352549e + md5: 07a28c6afa037bccc9f8f4ee15de4b33 + depends: + - __osx >=11.0 + - libiconv >=1.18,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - libintl >=0.25.1,<1.0a0 + - pcre2 >=10.47,<10.48.0a0 + - libffi >=3.7.0,<3.8.0a0 + constrains: + - glib >2.66 + license: LGPL-2.1-or-later + run_exports: + weak: + - libglib >=2.90.0,<3.0a0 + size: 4569987 + timestamp: 1789478206873 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libharfbuzz-14.6.0-h2974713_1.conda + sha256: 428aea010269e031d1c74c1049172ff278954704ad3a102211f16d707e922565 + md5: 54423714677f30b3d7460100f8949b18 + depends: + - __osx >=11.0 + - cairo >=1.18.6,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libcxx >=21 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.59,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + run_exports: {} + size: 1186161 + timestamp: 1791336908081 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libharfbuzz-devel-14.6.0-h2974713_1.conda + sha256: 67eadc92ac9688f0e67eb3acaf10371f694cbbb1473d881e8c1e5deb18b62437 + md5: ccd3ccae8dce183a1154c02c57717a95 + depends: + - __osx >=11.0 + - cairo >=1.18.6,<2.0a0 + - freetype + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libcxx >=21 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libharfbuzz 14.6.0 h2974713_1 + - libpng >=1.6.59,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + run_exports: + weak: + - libharfbuzz >=14.6.0 + size: 1672488 + timestamp: 1791336961968 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libhiredis-1.3.0-h240833e_1.conda + sha256: ae54db888afde29109b518bdffd6a7af6b35add881242a1cdf90807d8cb33143 + md5: 5a088b358e37ccb4f4e5c573ff37a9f9 + depends: + - __osx >=10.13 + - libcxx >=18 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libhiredis >=1.3.0,<1.4.0a0 + size: 59830 + timestamp: 1748219625377 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda + sha256: 2389e03a58ed0f5e8f2469eb4d4ba80d0af378b38854ae5eee65e5b641244082 + md5: 9fd2f77288f43e462ccc6b0e5f018c89 + depends: + - __osx >=11.0 + license: LGPL-2.1-only + run_exports: + weak: + - libiconv >=1.18,<2.0a0 + size: 736150 + timestamp: 1787034707041 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h98e67c8_2.conda + sha256: 1fad645b88742ad51dbaf9a6709fa9663edd663a4fed6b27c9c4cbc42fa9c514 + md5: e2a18b5a25e8b2c3c24e6f185220299f + depends: + - __osx >=11.0 + - libiconv >=1.18,<2.0a0 + license: LGPL-2.1-or-later + run_exports: + weak: + - libintl >=0.25.1,<1.0a0 + size: 99337 + timestamp: 1790119517486 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-3.2.0-ha1e9b39_1.conda + sha256: 0792824360a9e59802c9464157c1098c3d84330dcab5dbde762abaca16f580a8 + md5: c864512172ac7b820637f6731287936c + depends: + - __osx >=11.0 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + run_exports: + weak: + - libjpeg-turbo >=3.2.0,<4.0a0 + size: 614315 + timestamp: 1785896908505 +- conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.11.0-11_h859234e_openblas.conda + build_number: 11 + sha256: 0583f8807db3a6d8c847479af71bda38161dd31169bc928626896c001929d53f + md5: d3319abaf7ea8afa19a0999d667ceb6e + depends: + - libblas 3.11.0 11_he492b99_openblas + constrains: + - blas 2.311 openblas + - libcblas 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 + size: 18295 + timestamp: 1789061779646 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm21-21.1.8-hd11396f_1.conda + sha256: af2694e2cfcc3ae79c84fe4ff8eefda999aa212098ef3fd0172cf01846494c25 + md5: b947d905af2472de8c587a5c99d8a17a + depends: + - __osx >=11.0 + - libcxx >=21 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libllvm21 >=21.1.8,<21.2.0a0 + size: 31593190 + timestamp: 1787371754765 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.2-hd11396f_0.conda + sha256: f6174a6f25f900bbcebaa6461ad7152937ff5769e6dbec500a385c321e5adbc2 + md5: 37a5c2da1ad1626d6dea6c3d94a60e5c + depends: + - __osx >=11.0 + - libcxx >=21 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libllvm23 >=23.1.2,<23.2.0a0 + size: 33411262 + timestamp: 1790170337003 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.3-hd11396f_0.conda + sha256: f490ade9e9ecce88a292c6c26d212e7ae758b92982b5cf4275af75acba87a40b + md5: c647e7cd7e7324c6dd0f151d0b73cab0 + depends: + - __osx >=11.0 + - libcxx >=21 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libllvm23 >=23.1.3,<23.2.0a0 + size: 33411306 + timestamp: 1791344373618 +- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda + sha256: 7915dac7c71c208e40e716e2f6d3eff41a8d5584e0e7c2d46f9bf9bd5f9aa739 + md5: daf49067580fbfeae3ac7f9535400494 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 104919 + timestamp: 1786349094608 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmatio-1.5.30-ha0ad728_1.conda + sha256: b6987255ba00f1fe738ce9abe54029efd19354aa4f88727b8889b91942a72ca5 + md5: affc02df23e889dc98e12d2677329900 + depends: + - __osx >=11.0 + - hdf5 >=2.2.0,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - zlib + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libmatio >=1.5.30,<1.5.31.0a0 + size: 204195 + timestamp: 1787410123727 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-ha1e9b39_2.conda + sha256: 6438d0ef76e81f2b75ad7599685a525407c1d9fb2d6a7c18f360614ae6807970 + md5: b10a43915a31193e06b2781b9d11aec3 + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 79639 + timestamp: 1786651070313 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h1e30255_1.conda + sha256: 2d5c131553e83089be74988529d758e2a6dbb9227056d8fa19c01f5ccef6e6fc + md5: b7c605bed8006cdeb822dd7de6ac87c7 + depends: + - __osx >=11.0 + - c-ares >=1.34.8,<2.0a0 + - libcxx >=21 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 + size: 598607 + timestamp: 1787178086085 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.34-openmp_h5c7ac21_1.conda + sha256: 0c12ff69cf8e62948ffdf92845cf61119a19f5d78dca44deb5d4e4c441383d55 + md5: 3e9f7a3115c55e96dc388c3ca6dbe889 + depends: + - __osx >=11.0 + - libgcc >=15 + - libgfortran + - libgfortran5 >=15.3.0 + - llvm-openmp >=21.1.8 + constrains: + - openblas >=0.3.34,<0.3.35.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libopenblas >=0.3.34,<1.0a0 + size: 6356971 + timestamp: 1789028341483 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.59-h4382c61_0.conda + sha256: 4576bdf533292672b4aa955a43029343e25dcffaf8048d255b88e66b0860e602 + md5: ee02f407bc1a367df25d0cee798198de + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: zlib-acknowledgement + run_exports: + weak: + - libpng >=1.6.59,<1.7.0a0 + size: 298908 + timestamp: 1790805250755 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libpsl-0.23.1-h7ff43d8_1.conda + sha256: 6ee1849c23ddd4de76bacdcf88d4d16dc28fc10aa7c3431f859ef392da6936b8 + md5: 4cd9cae1ac1aa63d8f760fe127b42685 + depends: + - libcxx >=21 + - __osx >=11.0 + - icu >=78.3,<79.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libpsl >=0.23.1,<0.24.0a0 + size: 72605 + timestamp: 1786970907332 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libpython-3.14.8-hfe304d0_101_cp314.conda + build_number: 101 + sha256: 00fa627d39047acaee98bac32821cc5dac92c60a49b3e62f1ad7cb8d03c2187e + md5: 466f99da218bc7b6713db0d5404ca8d5 + depends: + - __osx >=11.0 + - libcxx >=20 + license: Python-2.0 + run_exports: + weak: + - libpython >=3.14,<4.0a0 + size: 2120464 + timestamp: 1791334549048 +- conda: https://conda.anaconda.org/conda-forge/osx-64/librsvg-2.62.4-h43ae438_0.conda + sha256: dc6c5599a00eec5f536deecf7ec6cf1482d18ef3eace96bd30f341f68ae7e10f + md5: 01bd342d0b0d99195c5e66719341c548 + depends: + - __osx >=11.0 + - gdk-pixbuf >=2.44.8,<3.0a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - pango >=1.58.2,<2.0a0 + - libglib >=2.90.0,<3.0a0 + - libharfbuzz >=14.5.0 + - libxml2-16 >=2.15.4 + - cairo >=1.18.6,<2.0a0 + constrains: + - __osx >=11.0 + license: LGPL-2.1-or-later + run_exports: + weak: + - librsvg >=2.62.4,<3.0a0 + size: 4097299 + timestamp: 1790276484744 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda + sha256: c3d76ff04ebed64d00a7ff5106297a55af20082a3d3df0ea7dfb235f94ba31c3 + md5: acc366a7706c83b5364f5f81e1b4857b + depends: + - __osx >=11.0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 38559 + timestamp: 1786115361068 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_102.conda + sha256: 1902d4b50b964f9753145ec0121f51a0fefaf64ca9806aae860cecb81cc75b98 + md5: 3fd4d7c9bcb8d4911fc202a731b5bb38 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 1008845 + timestamp: 1791167528883 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_103.conda + sha256: 6ab024b8ec426ff3cb2856f77e3bcca3b0be619330d9bf422f90c934c5d836dc + md5: f8903c56faaf28af430e6aa3a9a33943 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - icu <0.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 1009387 + timestamp: 1791288417901 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hd53bb72_1.conda + sha256: ed0db46844a548f4ca57dad0b3abb92b37050d7f75ab1ef08fbed9d23f06b2de + md5: cb57b979974ef5b8a4526a8e5c8195b9 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libssh2 >=1.11.1,<2.0a0 + size: 286497 + timestamp: 1786713428677 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.7.2-h01c3a8c_1.conda + sha256: 661b0befbb6e2300e0d25d9aac8f66be7003297c757fbb3e016985bf43a72638 + md5: ee440bf7977466b7661370804a9a26dc + depends: + - __osx >=11.0 + - lerc >=4.2.0,<5.0a0 + - libcxx >=21 + - libdeflate >=1.25,<1.26.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + run_exports: + weak: + - libtiff >=4.7.2,<4.8.0a0 + size: 409602 + timestamp: 1787755925896 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.52.1-ha3d0635_1.conda + sha256: 4aacf651487bf2cd4dcfab49ea98a00a34305919ff3a09b66b7ddaa97d8b316f + md5: 17b0d6c818992264752f1a720be711fc + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 128560 + timestamp: 1785914631885 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.6.0-hb276fe9_1.conda + sha256: 96263e9134164b6ca015a8cfba3a4cac9ca2429ddfebd25c120817fa608d2fdc + md5: abc3595bd7aab5df201b76ecef123583 + depends: + - __osx >=11.0 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 + size: 364823 + timestamp: 1785954881871 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h8376fb4_0.conda + sha256: 99b8a8977c93f4ab42dbdd345ee32677363175077473ef0acf1b20a3c15c8ab1 + md5: c48784f5a83259699d2f8527acb1e243 + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - libxml2 2.15.4 + license: MIT + license_family: MIT + run_exports: {} + size: 499396 + timestamp: 1788635607801 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-hb56241c_0.conda + sha256: 2a3d6322639100d222f64caa146640f1e15e3623e1baf57da166c42afb657a19 + md5: ce466c8ae878f5514f2beca676520001 + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.4 h8376fb4_0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.4 + size: 41448 + timestamp: 1788635625152 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda + sha256: b2dba286dd6632292b12296e761193b5ef9fb0eaeecaa481f5ba9af72c0c18e1 + md5: 7d3fa28263bb7f8ea32db11f570a5bb6 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 58993 + timestamp: 1785276808631 +- conda: https://conda.anaconda.org/conda-forge/osx-64/lld-23.1.2-h9313d6c_0.conda + sha256: 8ca4f46721ba3a7bfe336a3be648ad1fb841d1d54b88ec785e962ec577181f20 + md5: c2fc4b1d6e9c2c84ba39993b890dd043 + depends: + - __osx >=11.0 + - libcxx >=21.1.8 + - libllvm23 >=23.1.2,<23.2.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - llvm ==23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 5796333 + timestamp: 1790194004963 +- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda + sha256: 3c17127e2a94d60a8babef57c66d643374c5b08c896ec5f0987a62ecfb81c8ee + md5: 90d406df3178ddd5180ad32ba3cc5df6 + depends: + - __osx >=11.0 + constrains: + - intel-openmp <0.0a0 + - openmp 23.1.2|23.1.2.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + strong: + - llvm-openmp >=23.1.2 + size: 311893 + timestamp: 1790195924928 +- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21-21.1.8-h36529c3_1.conda + sha256: 496d2f82ea522f5252e4f5b2fba8ecaf8a235376b88ba9beac1052d42d65aa33 + md5: 428d5d0dde69e631b8e6263fc292ecda + depends: + - __osx >=11.0 + - libcxx >=21 + - libllvm21 21.1.8 hd11396f_1 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 19346083 + timestamp: 1787372038275 +- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-21.1.8-h8c1e6b9_1.conda + sha256: 40800b28bab7babf270c4119394d7dd7ee36018a4f6e710449569fa1502f3462 + md5: 8da3c07afce64d53522bc61190f9cf9a + depends: + - __osx >=11.0 + - libllvm21 21.1.8 hd11396f_1 + - llvm-tools-21 21.1.8 h36529c3_1 + constrains: + - clang 21.1.8 + - clang-tools 21.1.8 + - llvm 21.1.8 + - llvmdev 21.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 87956 + timestamp: 1787372133111 +- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23-23.1.2-h36529c3_0.conda + sha256: 5c12ec6e2f59444aa38ed1ab778ae3533a9d09b5c9c7c5e97e482dca81e9e08d + md5: fe5f238742ca5739dc090040ef23f820 + depends: + - __osx >=11.0 + - libcxx >=21 + - libllvm23 23.1.2 hd11396f_0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 19647529 + timestamp: 1790170836617 +- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23.1.2-h8c1e6b9_0.conda + sha256: bbf730a23807a089f2c2e9f1d460d03d49919291f97895b3aeb9593f6f0d6309 + md5: 6adc2b0907be1b77522d359ba3f62d5e + depends: + - __osx >=11.0 + - libllvm23 23.1.2 hd11396f_0 + - llvm-tools-23 23.1.2 h36529c3_0 + constrains: + - clang 23.1.2 + - clang-tools 23.1.2 + - llvm 23.1.2 + - llvmdev 23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 51803 + timestamp: 1790171050183 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda + sha256: 12c1d676b9a0e8109b576672519312c5428308f3f3d7706f8717e2f536d5d9e7 + md5: 88a79390f87c8f3334b9999a892e78d4 + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 834865 + timestamp: 1786356957789 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.13.2-hebe015c_1.conda + sha256: c26058f38190a758906a0a0200a86a24a904e61ba5e04ee2e36325c84eac93f8 + md5: 27f01468ccd33fe598256baa0cd59e12 + depends: + - __osx >=11.0 + - libcxx >=19 + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 178973 + timestamp: 1786713175652 +- conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.2.6-py310h07c5b4d_0.conda + sha256: f1851c5726ff1a4de246e385ba442d749a68ef39316c834933ee9b980dbe62df + md5: d79253493dcc76b95221588b98e1eb3c + depends: + - __osx >=10.13 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=18 + - liblapack >=3.9.0,<4.0a0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.21,<3 + size: 6988856 + timestamp: 1747545137089 +- conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-2.5.3-py314he0ba898_0.conda + sha256: 2b465d07a047782c4dd5a5a3f463414f2aa0c167b2eb247e3a8d521ede250a26 + md5: bd4583b75773bccb7d2ee7b123f5769e + depends: + - python + - libcxx >=21 + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + - liblapack >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.25,<3 + size: 8418113 + timestamp: 1788732072528 +- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.5-h332eb6d_0.conda + sha256: d992d27aec2f1beac81f792c85b449546c030f06937b5b3ea7cf58431861dde4 + md5: 615ac6cff316565b442cd1af8b94837f + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 2786968 + timestamp: 1791099439455 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pango-1.58.2-hc5a6962_1.conda + sha256: f0d480da4a46cd5049d8cb88cead23d532debd098ac94a11791ce0a672d43acb + md5: 93a24b8f530f98324cf10ad9cd7213b2 + depends: + - __osx >=11.0 + - cairo >=1.18.4,<2.0a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - fribidi >=1.0.16,<2.0a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.88.3,<3.0a0 + - libharfbuzz >=14.4.0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: LGPL-2.1-or-later + run_exports: + weak: + - pango >=1.58.2,<2.0a0 + size: 450260 + timestamp: 1788490852434 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pcre2-10.47-h31793e3_1.conda + sha256: 9b3d0022e9f97939f7ea46661a4ef340c41ea137976bd38cfc4f7c5808a335d9 + md5: 81cf2094fa0fe0350f92921f6feab289 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 + size: 1113605 + timestamp: 1787295097187 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pixman-0.46.4-h2fb4741_3.conda + sha256: 261a3af8cb2d08d206b6661abcd44ea234afd72cea52fe78ad5262cf26e86065 + md5: 90abdf0a23ec21e68e965e9a1389d7e7 + depends: + - libcxx >=19 + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 + size: 321088 + timestamp: 1786106856384 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.22-hea035f4_0_cpython.conda + sha256: 437aa5d2b40484307293785892c738039092262a56573bde15159d0894352f6f + md5: 8598a289055f87b52267636305e6a009 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.4,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.10.* *_cp310 + noarch: + - python + size: 12116349 + timestamp: 1791329159840 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.8-hafa0b4b_101_cp314.conda + build_number: 101 + sha256: 91874ead4971c6d3b5a2b50b25c34ce8a312f2aa6a862469547c6e4d8b5af2f6 + md5: a66d7bb9eb54ce5939e5b0993d228bc5 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 hfe304d0_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 12690138 + timestamp: 1791334717743 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py314h10d0514_1.conda + sha256: aef010899d642b24de6ccda3bc49ef008f8fddf7bad15ebce9bdebeae19a4599 + md5: ebd224b733573c50d2bfbeacb5449417 + depends: + - __osx >=10.13 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 191947 + timestamp: 1770226344240 +- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda + sha256: feb9248a062b7a0738e56339d8c9e87bc9adf8e8c76549fb55b0b2456bec3a57 + md5: 434eb49340f57827ef7ca3bb21f77c32 + depends: + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 319279 + timestamp: 1787034454836 +- conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.6-ha1e9b39_2.conda + sha256: 4045a9fd2a79741bd149a5a93293bc335557bea0ad9660035a33e652a3843e3a + md5: 773d8a5db899e5db9591c49d93ff8300 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - rhash >=1.4.6,<2.0a0 + size: 186416 + timestamp: 1786732023380 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.15-py314h17af80e_5.conda + sha256: 7f052e49ff9f5e52ac6908af77016d3a396652771a2599bad8220680bc940d0a + md5: 63a5442ff95d8104cfa0eb8166982964 + depends: + - python + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 136249 + timestamp: 1788881295770 +- conda: https://conda.anaconda.org/conda-forge/osx-64/s2n-1.7.7-h6035f5b_0.conda + sha256: 5d19cc9a2b08fe6f9f5a171be074d72212b9f80223909511d82c87b4bb1f5e15 + md5: 95a53c7ff740c9bcc09f2167d1155c38 + depends: + - __osx >=11.0 + - openssl >=3.5.7,<4.0a0 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - s2n >=1.7.7,<1.7.8.0a0 + size: 297282 + timestamp: 1785890058208 +- conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.15.2-py310hef62574_0.conda + sha256: da86efbfa72e4eb3e4748e5471d04fdbe3f9887f367b6302c1dcdb155bbf712b + md5: e79860e43d87b020a0254f0b3f5017c5 + depends: + - __osx >=10.13 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=18 + - libgfortran >=5 + - libgfortran5 >=13.2.0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.5 + - numpy >=1.19,<3 + - numpy >=1.23.5 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 14682985 + timestamp: 1739792429025 +- conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.18.1-py314hefcf020_1.conda + sha256: 17dcfeba061acf230d092950563fd0c4bb19319d1faf26031184e0d13499153b + md5: b205e03df514d91e7c19e02f72bbd382 + depends: + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=21 + - libgcc >=15 + - libgfortran + - libgfortran5 >=15.3.0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.8 + - numpy >=1.25,<3 + - numpy >=2.0.0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 15708125 + timestamp: 1790023041262 +- conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda + sha256: 37aac42f05e21b48a3b61b28ae624ed5a3d2acfcbaabf2cd10ef7762c4fb4c45 + md5: e7eb95a1f841fbbb8312dcd65963334f + depends: + - __osx >=11.0 + - libsigtool 0.1.3 h8c25ef7_1 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 123458 + timestamp: 1786115396108 +- conda: https://conda.anaconda.org/conda-forge/osx-64/simde-0.8.2-h37c8870_0.conda + sha256: fc44261e4a4e8f4bdab010d7788fa2d90d8bef51d37e1b8ec61ece047443e037 + md5: e456c3a390b37a3192eb460bfe33587f + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + run_exports: {} + size: 483653 + timestamp: 1724439763303 +- conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda + sha256: 045e62838ec78ad75974552ebeeccbee5a4a843272da47c7a67e99fd9cc25d8d + md5: a70697fe1077cb11e33b11d6f6610314 + depends: + - libcxx >=19.0.0.a0 + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: NCSA + run_exports: {} + size: 216045 + timestamp: 1789668322695 +- conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-ha6c374e_4.conda + sha256: 74e5fabcaf6ca0db052c645646ea04ded98a5eb7540483217f8101a819eb3107 + md5: 71c9f1f0267f2639523e898c6b50a4dc + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3512384 + timestamp: 1787272935349 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.1.0-py314h473ef84_0.conda + sha256: a77214fabb930c5332dece5407973c0c1c711298bf687976a0b6a9207b758e12 + md5: 08a26dd1ba8fc9681d6b5256b2895f8e + depends: + - __osx >=10.13 + - cffi + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 14286 + timestamp: 1769439103231 +- conda: https://conda.anaconda.org/conda-forge/osx-64/xxhash-0.8.3-hd5b56d2_1.conda + sha256: 66272dc5c55fc2a0ff7f7644d4c03d543ae2384a56c771aed75f98c49e60fe56 + md5: 83dc421c7efc4e054271892ee12204b4 + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - xxhash >=0.8.3,<0.8.4.0a0 + size: 108753 + timestamp: 1785949570328 +- conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-had63097_3.conda + sha256: b63a29a5e4968b28c8403525549fd662de8ff5863e6287f89cfaac7d1d688ea0 + md5: 9b30f8e851965211d981aca9c9bd1196 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 + size: 75645 + timestamp: 1787228502493 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda + sha256: d46ba65a5ebcb4f682f9f0f21943c427eb56e7f9d15aeab8b823294c787dbb0b + md5: c67ad1f1d33a7de2dd34e55c01a21eca + depends: + - __osx >=11.0 + - libzlib 1.3.2 hbb4bfdb_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 93115 + timestamp: 1785276829908 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda + sha256: 5277886d9704a624dc9b79ac985861e1e431bdb39a57c082507ab577a138ec6c + md5: c1d11f04327e40537ffe6cad5b131019 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 528228 + timestamp: 1786599702092 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-8_kmp_llvm.conda + build_number: 8 + sha256: c7c98ce74f6a7ff25aaa4706d06fa41d63a333add4d697b73aa4d8d2d7ad7651 + md5: a2d706b4a7d603524133037c34f7fb76 + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - _openmp_mutex >=4.5 + size: 8016 + timestamp: 1788046437162 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/atk-1.0-2.38.0-hd03087b_2.conda + sha256: b0747f9b1bc03d1932b4d8c586f39a35ac97e7e72fe6e63f2b2a2472d466f3c1 + md5: 57301986d02d30d6805fdce6c99074ee + depends: + - __osx >=11.0 + - libcxx >=16 + - libglib >=2.80.0,<3.0a0 + - libintl >=0.22.5,<1.0a0 + constrains: + - atk-1.0 2.38.0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - atk-1.0 >=2.38.0 + size: 347530 + timestamp: 1713896411580 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-1.0.0-h7ad4001_2.conda + sha256: af68a6e3d81adbb073239fab8167afde1cb9a5758e88bd922be17def25ffe526 + md5: 33a5552622d7abdb3672ce0091a08cea + depends: + - __osx >=11.0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + - aws-c-sdkutils >=1.0.0,<1.1.0a0 + - aws-c-http >=1.0.0,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-auth >=1.0.0,<1.0.1.0a0 + size: 116434 + timestamp: 1790928562460 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-1.0.0-h50d513f_1.conda + sha256: 0bffdce8b029bf5f0455783279a377f1c8c99c294b0e7f2b55ccf5a9ca24f62e + md5: 9ee38ba0bbcb179dbb721da815d23059 + depends: + - __osx >=11.0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-cal >=1.0.0,<1.1.0a0 + size: 48028 + timestamp: 1790949943085 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-1.0.2-h74c22ad_0.conda + sha256: 21f98dcb2eef17e6db18f2b5b10da4b083fcc56d570437ca6d4644ffa308988a + md5: 294bb97c0dcfd0f486a9e3a960813fbd + depends: + - __osx >=11.0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-common >=1.0.2,<1.1.0a0 + size: 250603 + timestamp: 1790800542492 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-1.0.0-h50d513f_1.conda + sha256: e37b6a98ee0b83eb294a8f5e334e6b30d6690a3e21b4e0a08f8fcf9eb9af5d21 + md5: 020e142382ed238e2498f8451b8eaa06 + depends: + - __osx >=11.0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-compression >=1.0.0,<1.1.0a0 + size: 21598 + timestamp: 1790877722735 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-1.0.0-h7b2e6b5_1.conda + sha256: 53b3af80cb7dff673cca2c4c6faba8fccd9c092c12ebb59d5006fb103658e79c + md5: a299d766c37faddc4a0b02760069331a + depends: + - __osx >=11.0 + - aws-c-compression >=1.0.0,<1.1.0a0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-http >=1.0.0,<1.1.0a0 + size: 190041 + timestamp: 1790884087812 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-1.0.0-h49e100f_0.conda + sha256: 9bc9baa53892a70259bae5132deb032d4630dc13d27b6f56c524aa0efa100679 + md5: a8b6251a52e773cbdf11b1eabfa3a43c + depends: + - __osx >=11.0 + - aws-c-common >=1.0.2,<1.1.0a0 + - s2n >=1.7.7,<1.7.8.0a0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-io >=1.0.0,<1.1.0a0 + size: 190058 + timestamp: 1790876995483 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-1.0.0-hffd187b_1.conda + sha256: d020dae4eddce28fa56dee700fe5c2c12f3b3d470c8593f016fc27c53044ea90 + md5: 609163d6f6be38b3068295f4db7f9194 + depends: + - __osx >=11.0 + - aws-c-cal >=1.0.0,<1.0.1.0a0 + - aws-checksums >=1.0.0,<1.0.1.0a0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-http >=1.0.0,<1.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + - aws-c-auth >=1.0.0,<1.0.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-s3 >=1.0.0,<1.1.0a0 + size: 138226 + timestamp: 1790935678657 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-1.0.0-h50d513f_1.conda + sha256: 059dc4f87210182c7353220947aaa49ab3345ac64e41bee13fd6efe1ada1ecf5 + md5: 74a053965661a0824f56ca9903a6e80f + depends: + - __osx >=11.0 + - aws-c-common >=1.0.2,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-c-sdkutils >=1.0.0,<1.1.0a0 + size: 60422 + timestamp: 1790878540454 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-1.0.0-h50d513f_0.conda + sha256: 00b081ad4f26edae87c8b9fd884df9699787850c64419ba963c44f7f5bb1f10c + md5: d6e2c9135537aab25fc6df9426ad9285 + depends: + - __osx >=11.0 + - aws-c-common >=1.0.1,<1.1.0a0 + license: Apache-2.0 + license_family: APACHE + run_exports: + weak: + - aws-checksums >=1.0.0,<1.0.1.0a0 + size: 91669 + timestamp: 1790400193286 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + sha256: 8ec22f0ba25cbfc2e64d70cf29459eccd7ffdf6436f6a6ff15bbfef799f7d4f6 + md5: b50612e7d190b8061ab4e7dc119cf4d5 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 124965 + timestamp: 1785906749812 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.8-h74c22ad_2.conda + sha256: 82bdd5a3fcada6afef6255a9bf41172f07b362f36e04a354dc2abc0a29bfb756 + md5: 4cc01a374215de38387d45e19c8c5c9c + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - c-ares >=1.34.8,<2.0a0 + size: 197819 + timestamp: 1787169996553 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.6-h580cee5_0.conda + sha256: 32ad9b731d0b4c6dd82061201206164b07bd695bc695e5eb3addc0087ed54cca + md5: 0d25672f63cd1c9b08653a0becfbf31a + depends: + - __osx >=11.0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.3,<79.0a0 + - libcxx >=21 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - pixman >=0.46.4,<1.0a0 + license: LGPL-2.1-only or MPL-1.1 + run_exports: + weak: + - cairo >=1.18.6,<2.0a0 + size: 844614 + timestamp: 1790045326889 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/catch2-3.16.0-hfbe1efa_0.conda + sha256: 7fbbb02deb5e3b2896f7b71fd5f3fc091d2c4e05b6c499ccc137b72487494977 + md5: df1d7061f2d09aa5afa8b54915a47d66 + depends: + - libcxx >=21 + - __osx >=11.0 + license: BSL-1.0 + run_exports: + weak: + - catch2 >=3.16.0,<4.0a0 + size: 521799 + timestamp: 1787658440126 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ccache-4.14.1-h0e49cae_0.conda + sha256: 56c7fcceb4f036b88a6382a0e54340658b0525ee6e5beaf640d9769565f55a50 + md5: f1fbca856aaeb3e1145157c26b7462d8 + depends: + - __osx >=11.0 + - libcxx >=21 + - zstd >=1.5.7,<1.6.0a0 + - xxhash >=0.8.3,<0.8.4.0a0 + - libhiredis >=1.3.0,<1.4.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 618233 + timestamp: 1790515481923 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm21_1_h8e84c17_6.conda + sha256: 5325a4044f0292d83c3c91b3a84f5e2d9a90803e404da0d940102499c7101fe2 + md5: 8d4aa8689ae07aac4e26a3dabbd17288 + depends: + - cctools_impl_osx-arm64 1030.6.3 llvm21_1_h2e2604f_6 + - ld64 956.6 llvm21_1_h5d6df6c_6 + - libllvm21 >=21.1.8,<21.2.0a0 + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 24301 + timestamp: 1787724419088 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm21_1_h2e2604f_6.conda + sha256: 018a1c139e1a3f2e2721acfb34e562771797c11b69d12e3c5b862be1c727dbff + md5: ed827e1d36581308d0170ee137d74ced + depends: + - __osx >=11.0 + - ld64_osx-arm64 >=956.6,<956.7.0a0 + - libcxx + - libllvm21 >=21.1.8,<21.2.0a0 + - libzlib >=1.3.2,<2.0a0 + - llvm-tools 21.1.* + - sigtool-codesign + constrains: + - cctools 1030.6.3.* + - clang 21.1.* + - ld64 956.6.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 762271 + timestamp: 1787724408080 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.1.1-py314h618e29d_3.conda + sha256: 172fcb9649244b38083d3242550841e9b24fafeb5530ea125b44f364172f4e9d + md5: 1177738698334efc54d4e9a2f108c469 + depends: + - __osx >=11.0 + - libffi >=3.7.0,<3.8.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 292373 + timestamp: 1788485305495 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21-21.1.8-default_h4399b93_6.conda + sha256: 39e371e974b6a8a74cec9f4301bdca51c16573febbfa812f93e8e451c162bf9e + md5: c7b00dddcd694d2adf0d9b53ca3d1136 + depends: + - __osx >=11.0 + - compiler-rt21 21.1.8.* + - libclang-cpp21.1 21.1.8 default_h4399b93_6 + - libcxx >=21.1.8 + - libllvm21 >=21.1.8,<21.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 819338 + timestamp: 1787460800427 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-21.1.8-default_cfg_h7f0254a_6.conda + sha256: fa546d1b4bb7bdfe6ded986da678d140cd11f5682dd8e302c69fe7a0f74e24b4 + md5: 4c92f594715cc9a9e13bb52358c5609c + depends: + - cctools + - clang-21 21.1.8.* default_* + - clang_impl_osx-arm64 21.1.8 default_hc11f16d_6 + - ld64 + - ld64_osx-arm64 * llvm21_1_* + - llvm-openmp >=21.1.8 + - llvm-tools 21.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28809 + timestamp: 1787460825258 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-21.1.8-default_h4399b93_6.conda + sha256: 5bf62b02d1903a864a8002d2aa423d62298f5a1b5f5fe309a16749c00e75b177 + md5: 98a490d2b62988b22e1177f8bc80333b + depends: + - __osx >=11.0 + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 + - libclang13 >=21.1.8 + - libcxx >=21.1.8 + - libllvm21 >=21.1.8,<21.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 101271 + timestamp: 1787460822516 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + sha256: 612e5f7072e60ed3591f992d6a9039cce234d9f666a8ab6967a2c3c2a8637ea5 + md5: 2862f9e7af5eaa6462a3aca336806d43 + depends: + - cctools_impl_osx-arm64 + - clang-21 21.1.8.* default_* + - compiler-rt 21.1.8.* + - compiler-rt_osx-arm64 21.1.8.* + - ld64_osx-arm64 * llvm21_1_* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28353 + timestamp: 1787460823809 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-21.1.8-default_cfg_h7f0254a_6.conda + sha256: 3b4782b875e608368c1af6ceb1c820a3cfa9f999773ef3815b24a83e70be998b + md5: 9f2cb1aecf42ce02e0ce9310f074498a + depends: + - clang 21.1.8 default_cfg_h7f0254a_6 + - clangxx_impl_osx-arm64 21.1.8.* default_* + - libcxx-devel 21.1.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28476 + timestamp: 1787460868805 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-21.1.8-default_hc11f16d_6.conda + sha256: 6408bd1ec4bfba3a5898288dd04ab80e0b8a7303a56db644658a040cbbc67041 + md5: a908806b23961a3389ef3b5b47692039 + depends: + - clang-21 21.1.8.* default_* + - clang-scan-deps 21.1.8 default_h4399b93_6 + - clang_impl_osx-arm64 21.1.8 default_hc11f16d_6 + - libcxx-devel 21.1.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 28141 + timestamp: 1787460865775 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.4.4-hf91ab31_0.conda + sha256: 0dd66618a37205201d1b522e7a7188b8bba8f3e4121496a93d8e5743c8549eff + md5: 1dd388142b3f596207223993dd6564ca + depends: + - __osx >=11.0 + - libcxx >=21 + - libexpat >=2.8.5,<3.0a0 + - rhash >=1.4.6,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - libuv >=1.52.1,<2.0a0 + - ncurses >=6.6,<7.0a0 + - libcurl >=8.22.0,<9.0a0 + - liblzma >=5.8.3,<6.0a0 + - bzip2 >=1.0.8,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 20193229 + timestamp: 1791001164107 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-21.1.8-hce30654_2.conda + sha256: 624b8923052bf0cea5ae6ee422f18e73594f76cd4e9b7fc7565f51b256275c92 + md5: 129de7382248e851078a1c4bbde92756 + depends: + - compiler-rt21 21.1.8 hdb3d66b_2 + - libcompiler-rt 21.1.8 hdb3d66b_2 + constrains: + - clang 21.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 16236 + timestamp: 1787374964487 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt21-21.1.8-hdb3d66b_2.conda + sha256: 5557bddc870924ec1a1dd24900672229b5cef3e7b6b14d647d220b5f9810767f + md5: df63e236c76f7b443db681db51a73682 + depends: + - __osx >=11.0 + - compiler-rt21_osx-arm64 21.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 99569 + timestamp: 1787374963563 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-2.0.0-he3883d0_0.conda + sha256: ee789a31c86183e8e3c337cd5c1961c9f5ab27e410d11750fd3d7f686eb322b1 + md5: 726b88cb2cac68266015e3ec3aeb2c6f + depends: + - clangxx 21.* + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 7001 + timestamp: 1786642232883 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.18.0-py310h3226bdb_0.conda + sha256: b7c2aa55df787bea73a0736525d666334f46d3cb60f500cc96f721baed991b26 + md5: e38fde3d8b43b4607fa433ae57e955b4 + depends: + - libiconv + - __osx >=11.0 + - libcxx >=21 + - libiconv >=1.18,<2.0a0 + license: GPL-2.0-only + license_family: GPL + run_exports: {} + size: 14613657 + timestamp: 1788247276044 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/eigen-5.0.1-hdb59ae0_3.conda + sha256: da0696b71ab191ea0d15feed3d96a21ec85da0633ba0aabd99ca509806f8ea78 + md5: 9fa281383911482a235dade061aecaee + license: MPL-2.0 + license_family: MOZILLA + run_exports: {} + size: 1313767 + timestamp: 1788951329226 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/epoxy-1.5.10-hc919400_2.conda + sha256: ba685b87529c95a4bf9de140a33d703d57dc46b036e9586ed26890de65c1c0d5 + md5: 3b87dabebe54c6d66a07b97b53ac5874 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - epoxy >=1.5.10,<1.6.0a0 + size: 296347 + timestamp: 1758743805063 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.18.3-h81aa574_1.conda + sha256: 004570d35fb0eff73ce3ae49b209a47622d0c2e580dd0dc4c61d59626b386a09 + md5: 8ac8cc3fe744b484de4387703134d8b2 + depends: + - __osx >=11.0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libintl >=0.25.1,<1.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + size: 265659 + timestamp: 1786667932256 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.14.3-hce30654_2.conda + sha256: 90681f1d0658cb2fd49a074f644eb4774272499290487a4bebb1c4df01d6997b + md5: 2f4cc7dc2e6622591735c49dda1b92aa + depends: + - libfreetype 2.14.3 hce30654_2 + - libfreetype6 2.14.3 h2ed5691_2 + license: GPL-2.0-only OR FTL + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + size: 175388 + timestamp: 1786641016583 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.17-hb001647_0.conda + sha256: 803e78ec4a832a646dae842f09de0bc04acd2613deafa9b11d1970399d24d163 + md5: 29b021cee334af0050bdca46bada6e0e + depends: + - __osx >=11.0 + license: LGPL-2.1-or-later + run_exports: + weak: + - fribidi >=1.0.17,<2.0a0 + size: 63577 + timestamp: 1790011838821 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gdk-pixbuf-2.44.8-h5867e2c_2.conda + sha256: 96dcac22eaea2f24b9c92e8be078c3e39058829aa4db2a8103c1a4e85f8925ed + md5: 3a84786e0c929f4a05d08c07be5ec9b3 + depends: + - __osx >=11.0 + - libglib >=2.88.3,<3.0a0 + - libintl >=0.25.1,<1.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libtiff >=4.7.2,<4.8.0a0 + license: LGPL-2.1-or-later + license_family: LGPL + run_exports: + weak: + - gdk-pixbuf >=2.44.8,<3.0a0 + size: 552802 + timestamp: 1788490405006 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.90.0-h06d1d6c_0.conda + sha256: 4c0cd7642611222bc573e93ac761b811839b015e4d0d968ae2e880b944e8b1a9 + md5: 62aed33caa374a6807ba9b2780603b70 + depends: + - libglib ==2.90.0 hccd281b_0 + - libffi + - __osx >=11.0 + - libintl >=0.25.1,<1.0a0 + license: LGPL-2.1-or-later + run_exports: {} + size: 202352 + timestamp: 1789478088421 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.15-h784d473_1.conda + sha256: 471f34a187fdb4f2df33e26f2e471b16c239a5b277903f643d9c3a8c9a9f44ec + md5: 0c7b78d9ffff4f5a6ca28d346f734d8f + depends: + - libcxx >=19 + - __osx >=11.0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 + size: 86493 + timestamp: 1786118637573 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphviz-14.1.2-hec8c438_0.conda + sha256: 755c72d469330265f80a615912a3b522aef6f26cbc52763862b6a3c492fbf97c + md5: 1f3d859de3ca2bcaa845e92e87d73660 + depends: + - __osx >=11.0 + - adwaita-icon-theme + - cairo >=1.18.4,<2.0a0 + - fonts-conda-ecosystem + - gdk-pixbuf >=2.44.4,<3.0a0 + - gtk3 >=3.24.43,<4.0a0 + - gts >=0.7.6,<0.8.0a0 + - libcxx >=19 + - libexpat >=2.7.3,<3.0a0 + - libgd >=2.3.3,<2.4.0a0 + - libglib >=2.86.3,<3.0a0 + - librsvg >=2.60.0,<3.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - pango >=1.56.4,<2.0a0 + license: EPL-1.0 + license_family: Other + run_exports: + weak: + - graphviz >=14.1.2,<15.0a0 + size: 2218284 + timestamp: 1769427599940 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gtk3-3.24.52-hc0f3e19_0.conda + sha256: 26862a9898054b8552e55e609e5ce73c7ef1eb28bbe6fb87f0b9109d73cd09df + md5: 5557a2433b1339b8e536c264afea41ef + depends: + - __osx >=11.0 + - atk-1.0 >=2.38.0 + - cairo >=1.18.4,<2.0a0 + - epoxy >=1.5.10,<1.6.0a0 + - fribidi >=1.0.16,<2.0a0 + - gdk-pixbuf >=2.44.5,<3.0a0 + - glib-tools + - harfbuzz >=13.2.1 + - hicolor-icon-theme + - libexpat >=2.7.4,<3.0a0 + - libfreetype >=2.14.2 + - libfreetype6 >=2.14.2 + - libglib >=2.86.4,<3.0a0 + - libintl >=0.25.1,<1.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - pango >=1.56.4,<2.0a0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - gtk3 >=3.24.52,<4.0a0 + - adwaita-icon-theme + size: 9385734 + timestamp: 1774288504338 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gts-0.7.6-he42f4ea_4.conda + sha256: e0f8c7bc1b9ea62ded78ffa848e37771eeaaaf55b3146580513c7266862043ba + md5: 21b4dd3098f63a74cf2aa9159cbef57d + depends: + - libcxx >=15.0.7 + - libglib >=2.76.3,<3.0a0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - gts >=0.7.6,<0.8.0a0 + size: 304331 + timestamp: 1686545503242 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/harfbuzz-14.6.0-hce30654_1.conda + sha256: cb45eb8a728f0bfe3258f3efc51415d2b7b7d97354fc3bb6de8e6d1a4c922c27 + md5: 12d6c765d260e311a19ba54eadd8a46d + depends: + - libharfbuzz-devel 14.6.0 hcda0f7c_1 + license: MIT + run_exports: + weak: + - libharfbuzz >=14.6.0 + size: 11070 + timestamp: 1791336149886 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-2.2.0-nompi_h9376f17_101.conda + sha256: 358af8f9dc60fa2683fdbc7025b57c46214d17411b116e9aeeb617a8f792b6f6 + md5: 5ad5e35146fceba4af18fb0febd1ce34 + depends: + - __osx >=11.0 + - aws-c-auth >=1.0.0,<1.0.1.0a0 + - aws-c-common >=1.0.2,<1.1.0a0 + - aws-c-http >=1.0.0,<1.1.0a0 + - aws-c-io >=1.0.0,<1.1.0a0 + - aws-c-s3 >=1.0.0,<1.1.0a0 + - aws-c-sdkutils >=1.0.0,<1.1.0a0 + - libaec >=1.1.5,<2.0a0 + - libcurl >=8.22.0,<9.0a0 + - libcxx >=21 + - libgcc >=15 + - libgfortran + - libgfortran5 >=15.3.0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.8,<4.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - hdf5 >=2.2.0,<3.0a0 + size: 3576623 + timestamp: 1790973290607 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/hicolor-icon-theme-0.17-hce30654_3.conda + sha256: 46a4958f2f916c5938f2a6dc0709f78b175ece42f601d79a04e0276d55d25d07 + md5: cfb39109ac5fa8601eb595d66d5bf156 + license: GPL-2.0-or-later + license_family: GPL + run_exports: {} + size: 17616 + timestamp: 1771539622983 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + sha256: 6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416a43 + md5: a5efc0b42bb8b42e97d0a29ae3e3c187 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14070242 + timestamp: 1786545847761 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + sha256: aaea1d42b07769920db2af7471ece9399d2613448863da64ad8272998db5db34 + md5: 15235dd10450d67bc25ccafd5b46d2bc + depends: + - __osx >=11.0 + - libcxx >=21 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 1165740 + timestamp: 1786762145768 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm21_1_h5d6df6c_6.conda + sha256: 0d797d56fd1c37023923a363793cb426452453603f36986a7db671cb77dbda8f + md5: 4a7bce9254a49f75ed4b7a02fcd3891b + depends: + - ld64_osx-arm64 956.6 llvm21_1_h1a10cc4_6 + - libllvm21 >=21.1.8,<21.2.0a0 + constrains: + - cctools 1030.6.3.* + - cctools_osx-arm64 1030.6.3.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 21643 + timestamp: 1787724413801 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm21_1_h1a10cc4_6.conda + sha256: 6334685852bd2deb6c30770d5e355966228ae998fb9de513fa0d7bdb8d9d3034 + md5: 7d8a2267ffe4bf8713e289cac7d86e62 + depends: + - __osx >=11.0 + - libcxx + - libllvm21 >=21.1.8,<21.2.0a0 + - sigtool-codesign + - tapi >=1600.0.11.8,<1601.0a0 + constrains: + - cctools 1030.6.3.* + - cctools_impl_osx-arm64 1030.6.3.* + - clang 21.1.* + - ld64 956.6.* + license: APSL-2.0 + license_family: Other + run_exports: {} + size: 984335 + timestamp: 1787724392255 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.2.0-h1eee2c3_0.conda + sha256: c97aa17d16d2ac332ba9f184e82ce8f72dcb10e9a10c5f299030be2d44e191b9 + md5: e429aec4037d5cb8fd34ded9f5dadd39 + depends: + - __osx >=11.0 + - libcxx >=19 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - lerc >=4.2.0,<5.0a0 + size: 166477 + timestamp: 1785036480092 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + sha256: af9cd8db11eb719e38a3340c88bb4882cf19b5b4237d93845224489fc2a13b46 + md5: 13e6d9ae0efbc9d2e9a01a91f4372b41 + depends: + - __osx >=11.0 + - libcxx >=19 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libaec >=1.1.5,<2.0a0 + size: 30390 + timestamp: 1769222133373 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-11_h51639a9_openblas.conda + build_number: 11 + sha256: 718c3e1a16ad946caeeba041520dc18b7af461226bd8c28faef78b181920dbb4 + md5: 364639b771dbb4ede335d965f55a23ac + depends: + - libopenblas >=0.3.34,<0.3.35.0a0 + - libopenblas >=0.3.34,<1.0a0 + constrains: + - blas 2.311 openblas + - libcblas 3.11.0 11*_openblas + - liblapack 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + - mkl <2027 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 + size: 18300 + timestamp: 1789061064192 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-11_hb0561ab_openblas.conda + build_number: 11 + sha256: 3cebd672d8bd7c776a381422ea3fc48131343aeda2879974734715ac6a05c292 + md5: 73bde7d713e790b3168707e02102e87b + depends: + - libblas 3.11.0 11_h51639a9_openblas + constrains: + - blas 2.311 openblas + - liblapack 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 + size: 18324 + timestamp: 1789061068736 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp21.1-21.1.8-default_h4399b93_6.conda + sha256: 024ea5de27ed275003d2968579aae265059eb2dc8a27d741243d7037d1983f26 + md5: 76123dc601c7fa451a3cd0cffd3dc122 + depends: + - __osx >=11.0 + - libcxx >=21.1.8 + - libllvm21 >=21.1.8,<21.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 + size: 13700434 + timestamp: 1787460755337 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda + sha256: 7a176b6dda75f39184cc96b548fa436581451547bb185c610627a9b6dca05ca8 + md5: 0b7234ee57b22355d69beb3505c99c54 + depends: + - libcxx >=23.1.2 + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libclang-cpp23.1 >=23.1.2,<23.2.0a0 + size: 16610135 + timestamp: 1790242080815 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda + sha256: 8fd0a585f9f4701a991ddf311aeb315c402783aa5b21c24b14b4034eb8cc3f20 + md5: 00b5e540c5eba9af1b48a31372fac2aa + depends: + - libclang-cpp23.1 ==23.1.2 default_h79071a4_0 + - libcxx >=23.1.2 + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.4 + - libllvm23 >=23.1.2,<23.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libclang13 >=23.1.2 + size: 10617694 + timestamp: 1790242080815 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-21.1.8-hdb3d66b_2.conda + sha256: 20e87238247ff01824095f96de08980bdf5b80bc81e69e6d27b6786bc20a0262 + md5: 13bb416a04cefad0b5c5870adb461f05 + depends: + - __osx >=11.0 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + weak: + - libcompiler-rt >=21.1.8 + size: 1331133 + timestamp: 1787374959415 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.22.0-h6651222_0.conda + sha256: 46def32ec20d4dc6bce75d90fe5f2465a71cc22acef608c5ba37cc392e80e01d + md5: a7234b8d8e19a089dcb1eaaa18de1045 + depends: + - __osx >=11.0 + - krb5 >=1.22.2,<1.23.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libpsl >=0.23.1,<0.24.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.8,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + run_exports: + weak: + - libcurl >=8.22.0,<9.0a0 + size: 419925 + timestamp: 1788340708264 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.3-h55c6f16_0.conda + sha256: 2d9d31172d7919bd276a8d1be338de567dd5afdd181e8d3d3d8c2d8695e09de2 + md5: 424521e52e65ef7f6cf957c4966e6386 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 577501 + timestamp: 1791337239735 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-21.1.8-h6dc3340_4.conda + sha256: 3171a5e250032338210bf63eae862de2cf96287bef1c8e35e1fff3c3e1a91706 + md5: f6a6c5792714f24f81aceff0a2f8035f + depends: + - libcxx >=21.1.8 + - libcxx-headers >=21.1.8,<21.1.9.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 23967 + timestamp: 1791301793421 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-he7e0567_1.conda + sha256: d896f4aa4ce4c590c2838678cb1917356fdb461d2a189991c0280c818c362172 + md5: 78650d671cb56909bb3e5c13bce310f9 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 + size: 55727 + timestamp: 1785909153744 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20260512-pl5321h26f1114_0.conda + sha256: 5692a969e49b200c7874d1e869d281753361980b2ecfe9191b571d7e550f8b92 + md5: ef2ab2462744ec6ba3a54c34dcc6a06e + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: BSD-2-Clause + run_exports: + weak: + - libedit >=3.1.20260512,<3.2.0a0 + size: 108512 + timestamp: 1791327440683 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h1a92334_3.conda + sha256: c0100064506ae8abb432c5a506d474f10af2cf48c33d62bc221fb28b6d6ff6ac + md5: 19e86c8a6a47e92bb2e70ca12e758c5c + depends: + - __osx >=11.0 + license: BSD-2-Clause OR GPL-2.0-or-later + license_family: GPL + run_exports: + weak: + - libev >=4.33,<4.34.0a0 + size: 39991 + timestamp: 1785917376956 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.5-h6111c0a_0.conda + sha256: 50aa761b83fc7a116ca88fe0cb4cefce5abababb10a926bf8afbafd5c298d102 + md5: 5383c550b785bdaafcc4eaf638071a7c + depends: + - __osx >=11.0 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 69565 + timestamp: 1790370026495 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-h47dc5ef_1.conda + sha256: 2783389a7b9dda04c62cc54c6bbeb03dd3cef24b3fc642715d02a3fa19464a9a + md5: 216bbcc23c11e9695b3db4a8771d76eb + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 43637 + timestamp: 1787753403688 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_2.conda + sha256: 19ce8bd320414cb6b9889ecbf48a3ded848b0d1068b76ff6bea099bd7387d6f3 + md5: ee1fc5bba400ff0cae27fbf141a1ae0c + depends: + - libfreetype6 >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 8367 + timestamp: 1786641013393 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.3-h2ed5691_2.conda + sha256: d9b203d6484ad491b5b5f33d49a9d7a91189d776a9adae53d2b63af18ec11e6a + md5: 881cfb44ea02cc9849f612725a959660 + depends: + - __osx >=11.0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - freetype >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 340923 + timestamp: 1786641012794 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_7.conda + sha256: deacf62bd6cbbe05eb085dd69a2ca120053597c37066d53c8f7cf6815f26e9eb + md5: f100c8baeb0c816052b0d43948555bf6 + depends: + - _openmp_mutex + constrains: + - libgcc-ng ==16.2.0=*_7 + - libgomp 16.2.0 7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 365973 + timestamp: 1790301995634 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgd-2.3.3-h05bcc79_12.conda + sha256: 269edce527e204a80d3d05673301e0207efcd0dbeebc036a118ceb52690d6341 + md5: fa4a92cfaae9570d89700a292a9ca714 + depends: + - __osx >=11.0 + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.1,<79.0a0 + - libexpat >=2.7.3,<3.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + - libiconv >=1.18,<2.0a0 + - libjpeg-turbo >=3.1.2,<4.0a0 + - libpng >=1.6.53,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + license: GD + license_family: BSD + run_exports: + weak: + - libgd >=2.3.3,<2.4.0a0 + size: 159247 + timestamp: 1766331953491 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_7.conda + sha256: a5b4b63d0ef4c7c59c37225b9f0307b5cd2a3a8499b2a40b6ddd2b9f072712a8 + md5: 2efa9518e126c501a7c7d638b2fa3a21 + depends: + - libgfortran5 16.2.0 hdb7a957_7 + constrains: + - libgfortran-ng ==16.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 99745 + timestamp: 1790302083840 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_7.conda + sha256: 19297e5cf39de976cdd1a46499a4e15fdf54d249d3231f3b2a9d43af3be0bc66 + md5: c9d80dd8775b8fe76e825d63d8ccaf1b + depends: + - libgcc >=16.2.0 + constrains: + - libgfortran 16.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 554793 + timestamp: 1790302001166 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.90.0-hccd281b_0.conda + sha256: 4ec64c476881b31f211842952f192208a3af0925a596da227f4d97fb9a63e0ac + md5: 8f63a5f35547d0c6d819830ebe0d3245 + depends: + - __osx >=11.0 + - libintl >=0.25.1,<1.0a0 + - libzlib >=1.3.2,<2.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libiconv >=1.18,<2.0a0 + - pcre2 >=10.47,<10.48.0a0 + constrains: + - glib >2.66 + license: LGPL-2.1-or-later + run_exports: + weak: + - libglib >=2.90.0,<3.0a0 + size: 4489939 + timestamp: 1789478088421 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libharfbuzz-14.6.0-hcda0f7c_1.conda + sha256: 3ddd0668249555af41ef771442d4475a7ac92cce38348f4c1414c81528e3b17e + md5: d6098b2d99d69ec90a0877d709d229b3 + depends: + - __osx >=11.0 + - cairo >=1.18.6,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libcxx >=21 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.59,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + run_exports: {} + size: 1052738 + timestamp: 1791336128117 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libharfbuzz-devel-14.6.0-hcda0f7c_1.conda + sha256: 4eaab8af98511bda62503a567a9908ed378bef4dc5849a50910ed7679c958cff + md5: 859b12266a2f1c2aab875d95af4a0d1c + depends: + - __osx >=11.0 + - cairo >=1.18.6,<2.0a0 + - freetype + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libcxx >=21 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libharfbuzz 14.6.0 hcda0f7c_1 + - libpng >=1.6.59,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + run_exports: + weak: + - libharfbuzz >=14.6.0 + size: 1538287 + timestamp: 1791336145002 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhiredis-1.3.0-h286801f_1.conda + sha256: 8da7c0e83c1c9d1bda3569146bb5618ef78251c5f912afa5d4f1573aef6ef6c7 + md5: 58b2c5aee0ad58549bf92baead9baead + depends: + - __osx >=11.0 + - libcxx >=18 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libhiredis >=1.3.0,<1.4.0a0 + size: 56746 + timestamp: 1748219528586 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + sha256: 689a14968267f2f97c07112fca5636e7d756036b9aee969911267c20bd3eea1f + md5: 17f4744c0873e9f77ac9b5cd0a27c187 + depends: + - __osx >=11.0 + license: LGPL-2.1-only + run_exports: + weak: + - libiconv >=1.18,<2.0a0 + size: 750816 + timestamp: 1787033961086 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-hae62183_2.conda + sha256: b43c6645e668f86d04d5c06d6dc17efe921bbd9244be4b77946d56fb950a3fcc + md5: a3a4193101bc5427e6cf8be81d5eeddf + depends: + - __osx >=11.0 + - libiconv >=1.18,<2.0a0 + license: LGPL-2.1-or-later + run_exports: + weak: + - libintl >=0.25.1,<1.0a0 + size: 90024 + timestamp: 1790118675563 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.2.0-h84a0fba_1.conda + sha256: 05006418f9392c9b723e8428808db106de0350a497832f95f921b85ff1072310 + md5: b2f8c8e5a7651a1d7c05404c3a159517 + depends: + - __osx >=11.0 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + run_exports: + weak: + - libjpeg-turbo >=3.2.0,<4.0a0 + size: 558459 + timestamp: 1785896382474 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-11_hd9741b5_openblas.conda + build_number: 11 + sha256: e7697df761eeb243272801a8c883dc1de6018a7f738746b443ef1396f0a78075 + md5: d67ef1462e77d20cd3e0d27c876c3c9a + depends: + - libblas 3.11.0 11_h51639a9_openblas + constrains: + - blas 2.311 openblas + - libcblas 3.11.0 11*_openblas + - liblapacke 3.11.0 11*_openblas + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 + size: 18284 + timestamp: 1789061072707 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm21-21.1.8-h759d1ac_1.conda + sha256: 8db5628b9431043d5e07dcdff6f4e2e50b654b9b15f1fb5370523ec5482e0b97 + md5: ecef0bb48f6401ce6e99bedaa24c78be + depends: + - __osx >=11.0 + - libcxx >=21 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libllvm21 >=21.1.8,<21.2.0a0 + size: 29629677 + timestamp: 1787364227487 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.3-h759d1ac_0.conda + sha256: e1a0f238487d15d018b9e5a75b937164d25fd28b4408e96b1a4af321f4f73181 + md5: 25eeae19cac6af1b9d28cf229855551d + depends: + - __osx >=11.0 + - libcxx >=21 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: + weak: + - libllvm23 >=23.1.3,<23.2.0a0 + size: 31579504 + timestamp: 1791337321683 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + sha256: 23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4311 + md5: 8ab10323068b107661a4b9a4af84f3b5 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 91720 + timestamp: 1786348695846 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmatio-1.5.30-h41674cd_1.conda + sha256: 0065b3441dc386d301022666ab3a75a46f37256ff60f31ff5bcf895acf12adc6 + md5: 3a1686c4cf7d0a79f078cfa623ac5888 + depends: + - __osx >=11.0 + - hdf5 >=2.2.0,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - zlib + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libmatio >=1.5.30,<1.5.31.0a0 + size: 180131 + timestamp: 1787408833214 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + sha256: 04cc136c5a956a73aa14e0a160b5822b0b29714e67b299fa1b1fd16dbcba5366 + md5: ff33a4dbd93abc8a798cc4e0e7c8136d + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 73289 + timestamp: 1786651074391 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h435687b_1.conda + sha256: 445440d8cccccb6585f71d1eb7c949d64a2af2ced5481d924621424ff3b6a398 + md5: ac9902dcbe0417f50cf95ab2bde062fa + depends: + - __osx >=11.0 + - c-ares >=1.34.8,<2.0a0 + - libcxx >=21 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libnghttp2 >=1.68.1,<2.0a0 + size: 567024 + timestamp: 1787177422467 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.34-openmp_h5e6e99c_1.conda + sha256: 18f167fdaa26f67a123c59766f4730b41866d2c0920b5c29d74a93d3a2e92a96 + md5: 9c874eb9d4441a658ef3acf6ac56dc3e + depends: + - __osx >=11.0 + - libgcc >=15 + - libgfortran + - libgfortran5 >=15.3.0 + - llvm-openmp >=21.1.8 + constrains: + - openblas >=0.3.34,<0.3.35.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libopenblas >=0.3.34,<1.0a0 + size: 4249236 + timestamp: 1789023664380 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.59-hf5e6511_0.conda + sha256: 4de4dc4cb7432c328c1eaf4f7cc9c6b48c073eab1e9c6723d4533e6d57e7d595 + md5: 4f99571d5354c39f2621b8b6e3a9afa3 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: zlib-acknowledgement + run_exports: + weak: + - libpng >=1.6.59,<1.7.0a0 + size: 290299 + timestamp: 1790805167385 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpsl-0.23.1-hdb0c161_1.conda + sha256: c8c3153df39abedf3413483f672151ad70f1adb0c06c192bdf7ec432c3616b07 + md5: 5d270f716a2b4bc13df9af8612071b17 + depends: + - __osx >=11.0 + - libcxx >=21 + - icu >=78.3,<79.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libpsl >=0.23.1,<0.24.0a0 + size: 72673 + timestamp: 1786970928205 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpython-3.14.8-h4311e70_101_cp314.conda + build_number: 101 + sha256: 257d8491de0514a5da3b3fd0d81a64802df6a7e3a72c31d639bd92d0cb110a0f + md5: af47f048c7a22af82a66a912794fe4ee + depends: + - __osx >=11.0 + - libcxx >=20 + license: Python-2.0 + run_exports: + weak: + - libpython >=3.14,<4.0a0 + size: 1895946 + timestamp: 1791332518303 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/librsvg-2.62.4-hc8ac265_0.conda + sha256: 3bd54de0136907782249a0d5797744ecac5bbd77026f5f2712dd62390c5c9f77 + md5: 878c79beee628e3b683ddc9094aaad1e + depends: + - __osx >=11.0 + - pango >=1.58.2,<2.0a0 + - libglib >=2.90.0,<3.0a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - libxml2-16 >=2.15.4 + - gdk-pixbuf >=2.44.8,<3.0a0 + - libharfbuzz >=14.5.0 + - cairo >=1.18.6,<2.0a0 + constrains: + - __osx >=11.0 + license: LGPL-2.1-or-later + run_exports: + weak: + - librsvg >=2.62.4,<3.0a0 + size: 3888310 + timestamp: 1790276358897 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + sha256: fcfa03afe31f40dfabf011629d99836adbebbc3ed1b38c7e9eee9ffc7581975b + md5: c70eb797aa92a294b09ef8f41f6bd578 + depends: + - __osx >=11.0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 36651 + timestamp: 1786115069018 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_102.conda + sha256: 0343b4f1c1a9f2feb0496bf159d13c5dd894ca750b9016f1282df5a4b82bd80e + md5: 46a1017240580d5c504a40293b2d41c1 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 939016 + timestamp: 1791167241399 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h34a968b_103.conda + sha256: b7c1d5a15d21948eec177a00e90801ad0d1c35e552404da9fbf0d657421aa0dd + md5: 68c3a50b8a8abfcc926f2d7e12d1fef5 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - icu <0.0a0 + license: blessing + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 938370 + timestamp: 1791288154128 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-hbf2880b_1.conda + sha256: a056e518c3d2d09fbb1778cea80c0c95338fb24adf1a817bbf90fb484850a304 + md5: d957a8eda98c49b073e8dcfd677c127a + depends: + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libssh2 >=1.11.1,<2.0a0 + size: 280492 + timestamp: 1786714226814 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.2-hf67920b_1.conda + sha256: 847d22a86ae28f66d3888702698254d25bb4eac3a0f64c1fabfb1842ac00be4c + md5: b6b191267455bf202af79f973690ed5d + depends: + - __osx >=11.0 + - lerc >=4.2.0,<5.0a0 + - libcxx >=21 + - libdeflate >=1.25,<1.26.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + run_exports: + weak: + - libtiff >=4.7.2,<4.8.0a0 + size: 380645 + timestamp: 1787756067271 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.52.1-h1a92334_1.conda + sha256: 4f47de9de1990efd998edbbd6793f89c8f02ffde987ae8120b1c006acefd2a04 + md5: de09bd0f175611e94f21b28f8c708e80 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 122729 + timestamp: 1785914645797 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h202fb40_1.conda + sha256: 0ff54650d470c7e54cbeffdd53a8c063e055a7bcf784388c0385ce5c4741b0f4 + md5: 168a13e329259710b28277abc1395b8e + depends: + - __osx >=11.0 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 + size: 294522 + timestamp: 1785955350410 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda + sha256: 8a26f7c94ab849c1930da36c298f4b82e892382b70ae865cd7274188d9d783e2 + md5: b40633f711a5eb8617917e0e944b9965 + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - libxml2 2.15.4 + license: MIT + license_family: MIT + run_exports: {} + size: 469299 + timestamp: 1788635201153 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda + sha256: 81217fcd4d4abdc69ee63cdb9cdb22e05a20b9ba7a76f596579914a838fe5960 + md5: 4b97a34d06740b578c32deba195daf5a + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.4 heb56d2d_0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.4 + size: 41375 + timestamp: 1788635206084 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + sha256: a18fa5d5bac452401459f966cf0d872224e8080c4ff93c77e168d43ab42ef9d7 + md5: f39288f0ea63ae962e1a2e4f355a0d75 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 47822 + timestamp: 1785277049190 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lld-23.1.2-h98a3de6_0.conda + sha256: 764d20e8491e861bb0425227ae1a9d78d45ba9440121b01c800b061151f1bad5 + md5: 79b2892c3afabbb613e7e78e2e141c2b + depends: + - __osx >=11.0 + - libcxx >=21.1.8 + - libllvm23 >=23.1.2,<23.2.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - llvm ==23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 5258363 + timestamp: 1790193044977 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda + sha256: f9aea67117079c00b9663ee0bbca7e5409dbe94625c34e68881ce2c97c3d47c9 + md5: 97fa48b6e1d996689e6d3f822a41f1bf + depends: + - __osx >=11.0 + constrains: + - intel-openmp <0.0a0 + - openmp 23.1.2|23.1.2.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + strong: + - llvm-openmp >=23.1.2 + size: 287714 + timestamp: 1790195505384 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21-21.1.8-h79441dc_1.conda + sha256: 758cf9c842b4a3678f52c768b66bbfdb812a715601edb9b75c577249d448e33c + md5: 269fcdde9a200135f812c74785c08615 + depends: + - __osx >=11.0 + - libcxx >=21 + - libllvm21 21.1.8 h759d1ac_1 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 18536625 + timestamp: 1787364291969 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-21.1.8-hdb3d66b_1.conda + sha256: f3ae2d3cc10de67fcee0e72998d4f67cb7c01bdfc428c51f78a7a59dc6f9b0c2 + md5: 50fd053bd7140fd31e79bbc61ecef3f1 + depends: + - __osx >=11.0 + - libllvm21 21.1.8 h759d1ac_1 + - llvm-tools-21 21.1.8 h79441dc_1 + constrains: + - clang 21.1.8 + - clang-tools 21.1.8 + - llvm 21.1.8 + - llvmdev 21.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 89113 + timestamp: 1787364323163 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + sha256: 7024a48c8c0d0114ed4ab53c76bf9275d50e91ba7cea367a9aead638d3c29c68 + md5: 3dfa0d0316dc246cd44937a557de4501 + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 804298 + timestamp: 1786355189145 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h3feff0a_1.conda + sha256: 3309eaa32a97afb323edb380563206c660637046eed93886d4b6b1b0ca270076 + md5: db95a98a49313f75abcad60aefa720ed + depends: + - libcxx >=19 + - __osx >=11.0 + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 164371 + timestamp: 1786713083876 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.2.6-py310h4d83441_0.conda + sha256: 87704bcd5f4a4f88eaf2a97f07e9825803b58a8003a209b91e89669317523faf + md5: f4bd8ac423d04b3c444b96f2463d3519 + depends: + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=18 + - liblapack >=3.9.0,<4.0a0 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.21,<3 + size: 5841650 + timestamp: 1747545043441 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.3-py314he06036b_0.conda + sha256: 693fa3d8d4303c35250025409d1cbc6d0d6270fd3778303dfe9ea89e29003871 + md5: 37bb35c87a060e9ab1551c5bd987074f + depends: + - python + - __osx >=11.0 + - libcxx >=21 + - libblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.25,<3 + size: 7273776 + timestamp: 1788732001328 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.5-h55eecbc_0.conda + sha256: 44fbc526456571a9fb8fa18157f6f269d4d4bd40eef20183a93b9c9296f94497 + md5: 45d9179cdf6e53d88aec034246f0dad6 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 3111573 + timestamp: 1791097959641 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pango-1.58.2-hf9b25ef_1.conda + sha256: 9ba23103198cffa523488ff583b184ad37eb6d90985d330a683a1039dc917771 + md5: 4a71e68873ce37dc6da671a899d09a46 + depends: + - __osx >=11.0 + - cairo >=1.18.4,<2.0a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - fribidi >=1.0.16,<2.0a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.88.3,<3.0a0 + - libharfbuzz >=14.4.0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: LGPL-2.1-or-later + run_exports: + weak: + - pango >=1.58.2,<2.0a0 + size: 442274 + timestamp: 1788491046895 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.47-he63d830_1.conda + sha256: f8c415329b542e1fca1ff2917b80e687c18302dfa0353530668b90cb225b494f + md5: 5ab90033816cbe4097e8a297e5179f67 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 + size: 851704 + timestamp: 1787294559157 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.4-h784d473_3.conda + sha256: 4779cd57231ce2e96fac643fcbdd4a6f51a57986264545445574e9c4acf526d3 + md5: 9a99c0b60efe41c194d01c182d000733 + depends: + - __osx >=11.0 + - libcxx >=19 + license: MIT + license_family: MIT + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 + size: 198717 + timestamp: 1786106922508 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.22-hac0b6dc_0_cpython.conda + sha256: 66d5322d2a5b9e78bd65f301bd0a9da54452bedbbaead46a2b7da808cf485c80 + md5: b6dd4544c50c6fc3793cdec56467488a + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.4,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.10.* *_cp310 + noarch: + - python + size: 12877536 + timestamp: 1791327519372 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.8-h0ae1c2c_101_cp314.conda + build_number: 101 + sha256: 4aebb9d626b26a2f7257d3c671bac70a96fffd4706db4d61c35f7bda6bee74f3 + md5: db895757bd372efa32f96937fabb3ef0 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 h4311e70_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 12496923 + timestamp: 1791332554767 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + sha256: 95f385f9606e30137cf0b5295f63855fd22223a4cf024d306cf9098ea1c4a252 + md5: dcf51e564317816cb8d546891019b3ab + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 189475 + timestamp: 1770223788648 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + sha256: d6782b430e6dce4fe8c7ac118cd988d5a193eb4a7f60741edfaede58016b6110 + md5: 9347fd56a002e6b58946831d48fe62f6 + depends: + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 314395 + timestamp: 1787033878899 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h84a0fba_2.conda + sha256: b4da3ab88c407b4133d39512b3b615d6fb020c89d39f54491862e6731528ab95 + md5: 5cec61f5b18ca8c5bbb1ad2dc5923a8e + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - rhash >=1.4.6,<2.0a0 + size: 185483 + timestamp: 1786732022220 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.15-py314hd98292b_5.conda + sha256: ab2b09a80bd70c1fc7c589959abc8ee3394a1b3178197696a594d224bba5243f + md5: 5ce723bf0ba143a8caa534609a5be881 + depends: + - python + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 127818 + timestamp: 1788881217705 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/s2n-1.7.7-h430f396_0.conda + sha256: 643f677b74da742fb477a2ccb14745a0d992c9d40f1f04b45decb7a4e8f07a50 + md5: 1f66642f01f98d0ab115fc7bd110373f + depends: + - __osx >=11.0 + - openssl >=3.5.7,<4.0a0 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - s2n >=1.7.7,<1.7.8.0a0 + size: 278434 + timestamp: 1785890070065 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.15.2-py310h32ab4ed_0.conda + sha256: f6ff2c1ba4775300199e8bc0331d2e2ccb5906f58f3835c5426ddc591c9ad7bf + md5: a389f540c808b22b3c696d7aea791a41 + depends: + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=18 + - libgfortran >=5 + - libgfortran5 >=13.2.0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.5 + - numpy >=1.19,<3 + - numpy >=1.23.5 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 13507343 + timestamp: 1739792089317 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.18.1-py314hd9f3d4e_1.conda + sha256: f22ceb6bb79b37bfa19964920ed4ee1421369ee3a614f556865e27a54bf87ce7 + md5: 647611d868800dc50a82a5b20672c49f + depends: + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=21 + - libgcc >=15 + - libgfortran + - libgfortran5 >=15.3.0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.8 + - numpy >=1.25,<3 + - numpy >=2.0.0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 14272608 + timestamp: 1790022149285 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + sha256: 7efd6d7d18bf9cc5788bfe1c1e1620d9dbbe00a81c646814929a82ff31944cf3 + md5: a322c0a0d3b5be99ee11f9ccec99b60e + depends: + - __osx >=11.0 + - libsigtool 0.1.3 h98dc951_1 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 114653 + timestamp: 1786115093248 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/simde-0.8.2-h7b3277c_0.conda + sha256: 282929ab21b49577fd81c5a8d2d461c028086a4be6044762f6a5f546e423f299 + md5: fc5b5caefb2778064799b76751a69b69 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: {} + size: 482908 + timestamp: 1724439819598 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda + sha256: 6effea9587f049e702c838e8e57d98ac92b89ca1f3f1edd51c78dd252d24e83b + md5: fdb31cc6c306f60e194f29f17397a63c + depends: + - libcxx >=19.0.0.a0 + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: NCSA + run_exports: {} + size: 202107 + timestamp: 1789668272580 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + sha256: 857d89087ae7f2c328cf256728affcb7343031a148b4af847334d248a9cf564c + md5: 90a01bf394d1c594e0eb9258f967d828 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3342183 + timestamp: 1787272852357 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.1.0-py314h6cfcd04_0.conda + sha256: 033dbf9859fe58fb85350cf6395be6b1346792e1766d2d5acab538a6eb3659fb + md5: e229f444fbdb28d8c4f40e247154d993 + depends: + - __osx >=11.0 + - cffi + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 14884 + timestamp: 1769439056290 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xxhash-0.8.3-h579eaed_1.conda + sha256: 70c1161126ad9bc20ed870252ba3d3563f23cd5436b20ddad977a9afe3140813 + md5: 8e4fba8b818d2ea0b9690cc6bda06917 + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - xxhash >=0.8.3,<0.8.4.0a0 + size: 99064 + timestamp: 1785949561258 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h74c22ad_3.conda + sha256: 3e78c43207502418fc5fb2317bbbefe5df8b6fc1051d90bdcd1c881c76bb4193 + md5: 31cf6dcc138abe673c9440cd6fe6c6fe + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 + size: 77530 + timestamp: 1787228556857 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda + sha256: ab46d85e4fcffff1b1c5cac517afa40b7ae784cf76fc9da1f55f6a6934291eb6 + md5: 2c966485853aa27985fbec7e3fcc4e77 + depends: + - __osx >=11.0 + - libzlib 1.3.2 h8088a28_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 81744 + timestamp: 1785277062753 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + sha256: da867f5092eb0cb746d353694f0098031fd9817a4ce7d5743121209ae0f406ca + md5: 4ec2684c73812cc2c3d78379384a39cc + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 433687 + timestamp: 1786599629846 +- conda: https://conda.anaconda.org/conda-forge/win-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 8a1cee28bd0ee7451ada1cd50b64720e57e17ff994fc62dd8329bef570d382e4 + md5: 1626967b574d1784b578b52eaeb071e7 + depends: + - libgomp >=7.5.0 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + constrains: + - openmp_impl <0.0a0 + - msys2-conda-epoch <0.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 52252 + timestamp: 1770943776666 +- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + sha256: 04767466ee9227c9c57ab2c6503e0149177d34111c7418d2f420297acb1eb229 + md5: c3301c058362f340100d91cd8be0393f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: bzip2-1.0.6 + license_family: BSD + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 55919 + timestamp: 1785906343696 +- conda: https://conda.anaconda.org/conda-forge/win-64/cairo-1.18.6-h477c42c_0.conda + sha256: af62a4e441719050878d050d242619f8256a891983515950f8fb877137868a45 + md5: f87fcbccd5ad4cbbf0c4b1c030f9cfc2 + depends: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.3,<79.0a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - pixman >=0.46.4,<1.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-only or MPL-1.1 + run_exports: + weak: + - cairo >=1.18.6,<2.0a0 + size: 1533334 + timestamp: 1790045452587 +- conda: https://conda.anaconda.org/conda-forge/win-64/catch2-3.16.0-h477610d_0.conda + sha256: 52dfedad54f7c38ca4c6b3fe3c73e29b9907ed96328f3ffb0d1840735ed6bdae + md5: 638882984d6f0592adba235b692caec8 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: BSL-1.0 + run_exports: + weak: + - catch2 >=3.16.0,<4.0a0 + size: 1029775 + timestamp: 1787658433155 +- conda: https://conda.anaconda.org/conda-forge/win-64/ccache-4.14.1-h7fd822b_0.conda + sha256: 97ecae9759fc1bad80e13b866bcc92231b77db54d5f5417dbfee12d781660b08 + md5: 43f137b91bdf030d5ec5dba524a65186 + depends: + - ucrt + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - zstd >=1.5.7,<1.6.0a0 + - xxhash >=0.8.3,<0.8.4.0a0 + - libhiredis >=1.3.0,<1.4.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 701600 + timestamp: 1790515439194 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.1.1-py314h5a2d7ad_3.conda + sha256: 400e8869acc3e5a0633b9a8ccd6695ce8d36b63675708b8d3f5e1c018406ef6a + md5: 178930300441541491ece1cae80240b9 + depends: + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + run_exports: {} + size: 347452 + timestamp: 1788485352441 +- conda: https://conda.anaconda.org/conda-forge/win-64/clang-22-22.1.8-default_hac490eb_2.conda + sha256: 92defdaa5eb6ccce723a7a714a8eee6b1ec72c3f7962d2df2fd0053d0511c461 + md5: a5f13b4d9572ac8eb20ac43b97184ef7 + depends: + - compiler-rt22 22.1.8.* + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 77070410 + timestamp: 1781848680122 +- conda: https://conda.anaconda.org/conda-forge/win-64/clang-22.1.8-default_nocfg_hbb9487a_2.conda + sha256: a626a7e6781301a55d29bd2c1d2c78ed94d70a05675e36c109bf0039bad6e8ff + md5: fc81fbe066684d91ee9bd2c7db966498 + depends: + - clang-22 22.1.8 default_hac490eb_2 + - libzlib >=1.3.2,<2.0a0 + - llvm-openmp >=22.1.8 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 114419551 + timestamp: 1781848773142 +- conda: https://conda.anaconda.org/conda-forge/win-64/clangxx-22.1.8-default_nocfg_hbb9487a_2.conda + sha256: 0dbc269f05ed7e0980ec310aea118a0af4d069d109b7b04fadaac69f0794d5be + md5: bf0a33d41d6696c16a120f274fae0301 + depends: + - clang 22.1.8 default_nocfg_hbb9487a_2 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 38159662 + timestamp: 1781848886356 +- conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.4.4-hde52c71_0.conda + sha256: 159c0e80f733a4ebcd24a9bf7fa6ad848a8e1c6ac441d5f2f63bafcfdff176ce + md5: 8a2288d93af982987191a1e778de756e + depends: + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libuv >=1.52.1,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.22.0,<9.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 17932458 + timestamp: 1791001114890 +- conda: https://conda.anaconda.org/conda-forge/win-64/compiler-rt22-22.1.8-h49e36cd_2.conda + sha256: da6148eca9ad24b3f4ddb4e9062965ef6401d42aa950452a331dfc15a76ba8dc + md5: 74270fa76e330d33a452e904e8005a90 + depends: + - compiler-rt22_win-64 22.1.8.* + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 4077720 + timestamp: 1787293981528 +- conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-2.0.0-h1c1089f_0.conda + sha256: 6382c5c446544a7a82e5f6b1f3943982e2b4ab3a636e4a83c0cf36a37453e62d + md5: 0fc344714ed17f2eededa97737731a83 + depends: + - vs2022_win-64 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 7320 + timestamp: 1786642198521 +- conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.18.0-py312pl5321h3ecd741_0.conda + sha256: de32cca941f0561791996493c096a7c6f83e4dda455f49e82e26d5558a3c83ce + md5: 83e3876323688448ceb5761c2303e79b + depends: + - libiconv + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libiconv >=1.18,<2.0a0 + license: GPL-2.0-only + license_family: GPL + run_exports: {} + size: 12781490 + timestamp: 1788247251746 +- conda: https://conda.anaconda.org/conda-forge/win-64/eigen-5.0.1-h5112557_3.conda + sha256: bb68626fe848e2857c1e2620b0658264fd186241beb0806c1e6c1e79d6d7c79d + md5: 655faee6689159bd9f0dbecdec357e75 + license: MPL-2.0 + license_family: MOZILLA + run_exports: {} + size: 1308604 + timestamp: 1788951324422 +- conda: https://conda.anaconda.org/conda-forge/win-64/fontconfig-2.18.3-hd47e2ca_1.conda + sha256: f26139e3c774a6434c8a73381c08e3d2a4c2f9d9ef9587c66aab8836211ee2ec + md5: ed95670fed91b091fe34ba6cae6677d7 + depends: + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libiconv >=1.18,<2.0a0 + - libintl >=0.22.5,<1.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + run_exports: + weak: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + size: 217988 + timestamp: 1786667461139 +- conda: https://conda.anaconda.org/conda-forge/win-64/fribidi-1.0.17-hfd05255_0.conda + sha256: 30a93a5132923a5679e0729a02bf5b36052c84cc437decc14a35caee5e276f46 + md5: fbe8e77a49028820f94cf619890c2365 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-or-later + run_exports: + weak: + - fribidi >=1.0.17,<2.0a0 + size: 67033 + timestamp: 1790011847625 +- conda: https://conda.anaconda.org/conda-forge/win-64/getopt-win32-0.1-h6a83c73_3.conda + sha256: d04c4a6c11daa72c4a0242602e1d00c03291ef66ca2d7cd0e171088411d57710 + md5: 49c36fcad2e9af6b91e91f2ce5be8ebd + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: LGPL-3.0-only + license_family: LGPL + run_exports: + weak: + - getopt-win32 >=0.1,<0.1.1.0a0 + size: 26238 + timestamp: 1750744808182 +- conda: https://conda.anaconda.org/conda-forge/win-64/graphite2-1.3.15-h5112557_1.conda + sha256: 93a59bdf944fb6f947bd7ad2f293d5d80db3a90f8ff8dfabc591e3752141e46f + md5: 79538e7a7bc024084eda5989f73fde35 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 + size: 98064 + timestamp: 1786118492029 +- conda: https://conda.anaconda.org/conda-forge/win-64/graphviz-14.1.2-h4c50273_0.conda + sha256: 58f83755509a19501a9efe40c484727ffa61fcfaf6a237870678a79638fa6982 + md5: afabed4c46b197b89eb974aa038d12db + depends: + - cairo >=1.18.4,<2.0a0 + - getopt-win32 >=0.1,<0.1.1.0a0 + - gts >=0.7.6,<0.8.0a0 + - libexpat >=2.7.3,<3.0a0 + - libgd >=2.3.3,<2.4.0a0 + - libglib >=2.86.3,<3.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - pango >=1.56.4,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: EPL-1.0 + license_family: Other + run_exports: + weak: + - graphviz >=14.1.2,<15.0a0 + size: 1223547 + timestamp: 1769427507016 +- conda: https://conda.anaconda.org/conda-forge/win-64/gts-0.7.6-h6b5321d_4.conda + sha256: b79755d2f9fc2113b6949bfc170c067902bc776e2c20da26e746e780f4f5a2d4 + md5: a41f14768d5e377426ad60c613f2923b + depends: + - libglib >=2.76.3,<3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: LGPL-2.0-or-later + license_family: LGPL + run_exports: + weak: + - gts >=0.7.6,<0.8.0a0 + size: 188688 + timestamp: 1686545648050 +- conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_hae35d4c_110.conda + sha256: 54f5211e698a468fd74def162e277d834e956c5b24a9ba4f9cf6298209328475 + md5: 4c94504a694781771108b07bf4a9370f + depends: + - libaec >=1.1.5,<2.0a0 + - libcurl >=8.20.0,<9.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - hdf5 >=1.14.6,<1.14.7.0a0 + size: 2354049 + timestamp: 1780581446500 +- conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + sha256: 75c549b55b673e15de8785a8e5dd85bca7eb612eee0ff4dc8d7bdaa15eacbdbb + md5: e596942e8ee6ee17fdcf1e6a77757a66 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 16835644 + timestamp: 1784916416303 +- conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + sha256: 63ff03324e903eb01a715ccf357df56d66224e61952fd6615d86490ebefb3285 + md5: 93f5a01dec294a2228f757fe2f3432d4 + depends: + - openssl >=3.5.7,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 753425 + timestamp: 1786762169034 +- conda: https://conda.anaconda.org/conda-forge/win-64/lerc-4.2.0-hd936e49_0.conda + sha256: 93d666f63f284ef77b87b0b1f77b70f7d36d315a132f9afa64bc0012d937ba39 + md5: add59e2b60ac9d4299d17c938185c75a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - lerc >=4.2.0,<5.0a0 + size: 175297 + timestamp: 1785036247761 +- conda: https://conda.anaconda.org/conda-forge/win-64/libaec-1.1.5-haf901d7_0.conda + sha256: e54c08964262c73671d9e80e400333e59c617e0b454476ad68933c0c458156c8 + md5: 43b6385cfad52a7083f2c41984eb4e91 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libaec >=1.1.5,<2.0a0 + size: 34463 + timestamp: 1769221960556 +- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-11_h8455456_mkl.conda + build_number: 11 + sha256: 51a38b02bacb5a4b546d41aeb0f7921ee85c0ec1009fdcb58635bcad06f2eb1a + md5: a63c8b08343d276a552c395f495987fa + depends: + - mkl >=2026.1.0,<2027.0a0 + constrains: + - blas 2.311 mkl + - libcblas 3.11.0 11*_mkl + - liblapack 3.11.0 11*_mkl + - liblapacke 3.11.0 11*_mkl + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 + size: 67059 + timestamp: 1789061341346 +- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-11_h2a3cdd5_mkl.conda + build_number: 11 + sha256: 9a2d431ead1463a7a96a38bedc901705c325c5bbafd7a2bcc5a198fbfcdea29e + md5: c9f8a732af97d55997f9ac6d0c02e3f2 + depends: + - libblas 3.11.0 11_h8455456_mkl + constrains: + - blas 2.311 mkl + - liblapack 3.11.0 11*_mkl + - liblapacke 3.11.0 11*_mkl + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 + size: 67465 + timestamp: 1789061353350 +- conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.22.0-hdb0ef4a_0.conda + sha256: 5fe063cffa90ad3ef04e25c76b1a79cdbc4f6c43747164a7dcdd89c4faebb84e + md5: e8405e754eaac42d66f957222fcfd876 + depends: + - krb5 >=1.22.2,<1.23.0a0 + - libpsl >=0.23.1,<0.24.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: curl + license_family: MIT + run_exports: + weak: + - libcurl >=8.22.0,<9.0a0 + size: 413226 + timestamp: 1788340784214 +- conda: https://conda.anaconda.org/conda-forge/win-64/libdeflate-1.25-h1a1d4e4_1.conda + sha256: af1cda21d4653f594fbef20aa4e1ff158a546902b3307ef8af9a9b44b43862d2 + md5: e4e122e124676a49eebf241399ad8393 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 + size: 157828 + timestamp: 1785908793271 +- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + sha256: 70c73d9fd24ad996f2821d1501adae2ca70984b4e2d8faed76227f348ce86078 + md5: 4969128c45f9e71adbb6a1696679ce7f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - expat 2.8.5.* + license: MIT + license_family: MIT + run_exports: {} + size: 72107 + timestamp: 1790346254561 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + sha256: 613e8077c5cca5df7fe84ade7d5050301bee3c6c4c450ffe61d34a349ab4f11c + md5: ceb38b0ba900847d8da4289c3c8e5708 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 49992 + timestamp: 1787753517346 +- conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype-2.14.3-h57928b3_2.conda + sha256: d794d7fddb6eea50e18a62fa27ab3819f40d51bad00b90cf4ca591fb0d4006c2 + md5: 740f99c3c91079c03874b809fedace1b + depends: + - libfreetype6 >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 8742 + timestamp: 1786641045882 +- conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype6-2.14.3-hdbac1cb_2.conda + sha256: cbc650854003e434d4ff6c7b1a2667e38a4242ad8a391a1c5ff89721624065ce + md5: 8157483eb7ed3fcba71aad3b50a97131 + depends: + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - freetype >=2.14.3 + license: GPL-2.0-only OR FTL + run_exports: {} + size: 340385 + timestamp: 1786641044865 +- conda: https://conda.anaconda.org/conda-forge/win-64/libgcc-16.2.0-h110b43a_7.conda + sha256: 59feb6d16cba13a70f22dae70a44670eb2cc45e652e9a34a014814c2ca871132 + md5: bd1e0d06981ae43e35c1ebb50e268c59 + depends: + - _openmp_mutex >=4.5 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + constrains: + - libgcc-ng ==16.2.0=*_7 + - libgomp 16.2.0 h8ee18e1_7 + - msys2-conda-epoch <0.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: {} + size: 826913 + timestamp: 1790304405241 +- conda: https://conda.anaconda.org/conda-forge/win-64/libgd-2.3.3-h4974f7c_12.conda + sha256: 9ab562c718bd3fcef5f6189c8e2730c3d9321e05f13749a611630475d41207fc + md5: 3a5b40267fcd31f1ba3a24014fe92044 + depends: + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.1,<79.0a0 + - libexpat >=2.7.3,<3.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + - libjpeg-turbo >=3.1.2,<4.0a0 + - libpng >=1.6.53,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - xorg-libxpm >=3.5.17,<4.0a0 + license: GD + license_family: BSD + run_exports: + weak: + - libgd >=2.3.3,<2.4.0a0 + size: 166711 + timestamp: 1766331770351 +- conda: https://conda.anaconda.org/conda-forge/win-64/libglib-2.90.0-ha564072_0.conda + sha256: 55d9fad9d0884111826500629285dbd35c827e3f2b5fe04b50e3d7d67c71425e + md5: 29c689012c8a53a0e36a70dfd43227e4 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libffi >=3.7.0,<3.8.0a0 + - libintl >=0.22.5,<1.0a0 + - libiconv >=1.18,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - pcre2 >=10.47,<10.48.0a0 + constrains: + - glib >2.66 + license: LGPL-2.1-or-later + run_exports: + weak: + - libglib >=2.90.0,<3.0a0 + size: 4572716 + timestamp: 1789478046525 +- conda: https://conda.anaconda.org/conda-forge/win-64/libgomp-16.2.0-h8ee18e1_7.conda + sha256: 4b8a747f047d069ccd2a6cf2f4fdbc6b0c0e4dcd840998d1fe607b8c234e707b + md5: 1725e0c19dd2f01de09805536c4f3b51 + depends: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + constrains: + - msys2-conda-epoch <0.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + run_exports: + strong: + - _openmp_mutex >=4.5 + - libgomp >=16.2.0 + size: 688609 + timestamp: 1790304345963 +- conda: https://conda.anaconda.org/conda-forge/win-64/libharfbuzz-14.6.0-h03b5201_1.conda + sha256: 689199e460f15021019266a54abdf18901b96e3b8bfd17edac18b19f40397f96 + md5: 4572ed18126f19f703bbc6b8d7cd8b72 + depends: + - cairo >=1.18.6,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libexpat >=2.8.5,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.90.0,<3.0a0 + - libpng >=1.6.59,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + run_exports: {} + size: 1132989 + timestamp: 1791336347237 +- conda: https://conda.anaconda.org/conda-forge/win-64/libhiredis-1.3.0-he0c23c2_1.conda + sha256: 9234de8c29f1a3a51bd37c94752e31b19c2514103821e895f6fabaa65e74ea5a + md5: 821660830c0152d3260633b150f92b49 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libhiredis >=1.3.0,<1.4.0a0 + size: 64205 + timestamp: 1748219812303 +- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.15.0-default_hae90fe0_1001.conda + sha256: 240368b73a984a1812dab5f7964ed03304950ad97466cd7ee347df9cc707629d + md5: b679b0f76b152d40294fa4e43cabfd4a + depends: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - libxml2 + - libxml2-16 >=2.15.4 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libhwloc >=2.15.0,<2.15.1.0a0 + size: 2417452 + timestamp: 1790244291307 +- conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + sha256: 35e04e3ddac7720fc7c550a1c9f998604299d6a7bd1f3ec9b2825d825061daa2 + md5: a8a2abdf0f901bc4779d9b7be0845921 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-only + run_exports: + weak: + - libiconv >=1.18,<2.0a0 + size: 694899 + timestamp: 1787033851701 +- conda: https://conda.anaconda.org/conda-forge/win-64/libintl-0.22.5-h5728263_4.conda + sha256: 85b50be2209f3b8a873830ec9894477d260f4c7ba9540e65959f5812bf7219f8 + md5: 36d6e0045173974521fabd42bd5033d6 + depends: + - libiconv >=1.18,<2.0a0 + license: LGPL-2.1-or-later + run_exports: + weak: + - libintl >=0.22.5,<1.0a0 + size: 96669 + timestamp: 1787841116808 +- conda: https://conda.anaconda.org/conda-forge/win-64/libjpeg-turbo-3.2.0-hfd05255_1.conda + sha256: df78ab4c0eecb3dd9331898f96baeed8e5ca1c363346332517abeb0b614b9a53 + md5: fc2c23bacefd1e733f1e1d6cd3b2aaeb + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + run_exports: + weak: + - libjpeg-turbo >=3.2.0,<4.0a0 + size: 990125 + timestamp: 1785896494014 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-11_hf9ab0e9_mkl.conda + build_number: 11 + sha256: 460a2b9896bbee9a3cdfef26d1fdce056028291eef104564082de9e9f566bba6 + md5: 79bdf20fd2666b8a3485a6021c935b3a + depends: + - libblas 3.11.0 11_h8455456_mkl + constrains: + - blas 2.311 mkl + - libcblas 3.11.0 11*_mkl + - liblapacke 3.11.0 11*_mkl + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 + size: 79503 + timestamp: 1789061364082 +- conda: https://conda.anaconda.org/conda-forge/win-64/libllvm22-22.1.8-h830ff33_3.conda + sha256: 9f3d17c126cf7ea258e53c14b3e94e68c16adb3bed7a99d4fba74392de06026a + md5: ec52d2dba8d1e08c4e43ed3a401f59ae + depends: + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 20327 + timestamp: 1790102786831 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + sha256: d36c4a1e1f80fd08e18a407e03622ff2f34dfdd022da6488ad19603dea19e6d5 + md5: 880a0c8549479b198af21ba5dc49b109 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - xz 5.8.3.* + license: 0BSD + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 105809 + timestamp: 1786348717883 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmatio-1.5.30-hbeb426f_0.conda + sha256: 733183c1dc37501af50a6e32afaac287e5aa3383d0829faaaa45c3b4993bf325 + md5: 379cd16225411177a51f9bab3619f145 + depends: + - hdf5 >=1.14.6,<1.14.7.0a0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zlib + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - libmatio >=1.5.30,<1.5.31.0a0 + size: 186697 + timestamp: 1767753708811 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + sha256: f07e451de3db1836b87f7aedf95c8e65cdb06c0e6105329ba24bb5f7b5c75e2a + md5: 5ae92fd6614edd024576e14069d7ad4c + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + run_exports: {} + size: 89109 + timestamp: 1786650384519 +- conda: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.59-hdc8cecf_0.conda + sha256: 36050852deae6edc98d7b71489b8d07254e2753c69bd524bf5784927cd1f0b2c + md5: 05145e03eb7b7f4ad2e0575454061c87 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.2,<2.0a0 + license: zlib-acknowledgement + run_exports: + weak: + - libpng >=1.6.59,<1.7.0a0 + size: 385760 + timestamp: 1790805156982 +- conda: https://conda.anaconda.org/conda-forge/win-64/libpsl-0.23.1-h9b16d47_1.conda + sha256: e53fe3b09f82b59b644264133d6d148ac31bb5451b7583cff55690bf038f2f62 + md5: 39cdf8c4f59e4d253cfa8091c8b3d7de + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - icu >=78.3,<79.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libpsl >=0.23.1,<0.24.0a0 + size: 73511 + timestamp: 1786970749988 +- conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.8-h4f90d01_101_cp314.conda + build_number: 101 + sha256: 04f9f3a3b9d91e47009baa4a4379ddb11af3e5402928e40e1dd4e02ca83d60f1 + md5: 98114d6c6784f306f4929189f50520a9 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Python-2.0 + run_exports: {} + size: 51940 + timestamp: 1791333541956 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_103.conda + sha256: 94e12c9dd0323bd8f9e5abc85bba0994b9ad7f21420bb3310f9fbbbcc7c1b29e + md5: 97b2e506228f785f01a0e6c80b57103a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: blessing + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 1313318 + timestamp: 1791288170708 +- conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h734d217_1.conda + sha256: 1097b08429b4f53f5751a32c6d99a083d227ca7f7812c0b239eea124cec073a0 + md5: a21dd9ca39e74910bb96989feb916420 + depends: + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libssh2 >=1.11.1,<2.0a0 + size: 295149 + timestamp: 1786713186180 +- conda: https://conda.anaconda.org/conda-forge/win-64/libtiff-4.7.2-h8f73337_1.conda + sha256: 3575a092e3e52625a1767804a4ebd321becaadf61b63dcd6735ebb88c0b3c359 + md5: 970dbe48f843e7fbd179a9b6c22f865a + depends: + - lerc >=4.2.0,<5.0a0 + - libdeflate >=1.25,<1.26.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + run_exports: + weak: + - libtiff >=4.7.2,<4.8.0a0 + size: 1014211 + timestamp: 1787755773611 +- conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.52.1-h6a83c73_1.conda + sha256: 0d62467380061cd0fa4b27e579c805a95c7ef55a41ecb067de0c4d2d42490c66 + md5: 4ccef39545e98553cc900ea557dff085 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: + weak: + - libuv >=1.52.1,<2.0a0 + size: 331195 + timestamp: 1785914602690 +- conda: https://conda.anaconda.org/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_1.conda + sha256: 4470d98d3178b0d45492eed4808afe421d2e7808352b8d06c2dc29166b75d94d + md5: 35a9475e4cc999d52921f57c181979fc + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 + size: 278886 + timestamp: 1785954716703 +- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + sha256: 0fccf2d17026255b6e10ace1f191d0a2a18f2d65088fd02430be17c701f8ffe0 + md5: 8a86073cf3b343b87d03f41790d8b4e5 + depends: + - ucrt + constrains: + - pthreads-win32 <0.0a0 + - msys2-conda-epoch <0.0a0 + license: MIT AND BSD-3-Clause-Clear + run_exports: {} + size: 36621 + timestamp: 1759768399557 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxcb-1.17.0-h874e120_2.conda + sha256: f5932cbcadb67bef9374ee864fed72411af29e88690435c6c7fc5633c89dabee + md5: 3658b0201b32da9607ea5e3c1c463c1f + depends: + - libgcc >=13 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - pthread-stubs + - ucrt >=10.0.20348.0 + - xorg-libxau >=1.0.12,<2.0a0 + - xorg-libxdmcp >=1.1.5,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - libxcb >=1.17.0,<2.0a0 + size: 1215534 + timestamp: 1787886015478 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda + sha256: 9fa71cec30425c9cc8eda6af3574af1faf4fefa5e239c9e037b1f778ef3ce8ac + md5: bab5489f4bd38494ffaa83d6ab924c1f + depends: + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libxml2 2.15.4 + license: MIT + license_family: MIT + run_exports: {} + size: 515800 + timestamp: 1788635268845 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda + sha256: a19bb3821830f6b1281e782844d5dd265f796dfed2e4812b16c9995a8c778c88 + md5: 3ce54d0f8f24dfab99d82414411640aa + depends: + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.4 h3cfd58e_0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.4 + size: 43845 + timestamp: 1788635276599 +- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + sha256: 0629c2cc0404d3bb29d6baa7b4ba62da80797015e86de050db81ea5a07050527 + md5: 5d2ff29d465097458cc3ff6569151991 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 58529 + timestamp: 1785276664143 +- conda: https://conda.anaconda.org/conda-forge/win-64/lld-23.1.2-he13e66b_0.conda + sha256: d05cfe66fffff5c278e9887c886ec89e99a0a1e876493956b068c92781f143a2 + md5: dc874c84df057bbf047699f61342e1c4 + depends: + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - llvm ==23.1.2 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: {} + size: 151343048 + timestamp: 1790193633680 +- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda + sha256: 8b462c021d6bf3f956749d305bd3f52deb82ae2901047c0c7061a21c3550e48f + md5: 4b07614a10496df13cb3e35d249caf3c + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - intel-openmp <0.0a0 + - openmp 23.1.2|23.1.2.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + run_exports: + strong: + - llvm-openmp >=23.1.2 + size: 343460 + timestamp: 1790195831140 +- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-tools-22.1.8-he5be12e_3.conda + sha256: 28c41f4a7c78bc49362365f93f2e66d312160d4db4ada252d0897982dd0bc113 + md5: fe067f91b36c104f79f32836cd85b77e + depends: + - libllvm22 22.1.8 h830ff33_3 + - libxml2 + - libxml2-16 >=2.15.4 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - clang 22.1.8 + - clang-tools 22.1.8 + - llvm 22.1.8 + - llvmdev 22.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + run_exports: {} + size: 257237449 + timestamp: 1790102979123 +- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_235.conda + sha256: bb8abe071f73765446df62924031e6599577e8ac9003264dc4569e78c0fea16d + md5: ace316c48c178d7faa403dee51e30c7b + depends: + - llvm-openmp >=22.1.8 + - tbb >=2023.0.0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + run_exports: {} + size: 114686732 + timestamp: 1787725739779 +- conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_1.conda + sha256: 002bce37e87e39c6a1e5577b1018d294cd4517ba9c4be2ece92e5706acac41f5 + md5: 3a6804d04ecaf02987a075d5faf34877 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 309772 + timestamp: 1786713090968 +- conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.2.6-py310h4987827_0.conda + sha256: 6f628e51763b86a535a723664e3aa1e38cb7147a2697f80b75c1980c1ed52f3e + md5: d2596785ac2cf5bab04e2ee9e5d04041 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.21,<3 + size: 6596153 + timestamp: 1747545352390 +- conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.5.3-py314h02f10f6_0.conda + sha256: 03e0def4425d045b9afb2e2c895bcd0233de6f1aeec53575ba00dd262c4f00e4 + md5: 806daade32d05870efd4d63931c12c9d + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - liblapack >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + - libcblas >=3.9.0,<4.0a0 + - libblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - numpy >=1.25,<3 + size: 7514382 + timestamp: 1788731986512 +- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + sha256: bc44625e0c6d83f3e02b5f6adc01e0e3ca7001d3d94e24959591a57f5a011b9a + md5: f002ec2237836867bfd3d1299a6005da + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + run_exports: + weak: + - openssl >=3.6.5,<4.0a0 + size: 9402647 + timestamp: 1791099870810 +- conda: https://conda.anaconda.org/conda-forge/win-64/pango-1.58.2-h13911b6_1.conda + sha256: 110d2731a105c0b9bd6396ad371401db90bd53179a283ff77f774872beb5bcd4 + md5: 7953b4cc0a7a47a0d91fa2e664269a0c + depends: + - cairo >=1.18.4,<2.0a0 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - fribidi >=1.0.16,<2.0a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.88.3,<3.0a0 + - libharfbuzz >=14.4.0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: LGPL-2.1-or-later + run_exports: + weak: + - pango >=1.58.2,<2.0a0 + size: 465040 + timestamp: 1788490491378 +- conda: https://conda.anaconda.org/conda-forge/win-64/pcre2-10.47-h8466c1e_1.conda + sha256: d8e9ea26b52a09d880d1e5371830c8dd5b4c099a6db64dbdf8236440744b7499 + md5: 009af999dbe2d1db36a37187a4ca4eb4 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 + size: 993241 + timestamp: 1787294653206 +- conda: https://conda.anaconda.org/conda-forge/win-64/pixman-0.46.4-h5112557_3.conda + sha256: cad8b94c2b00264a15d469eed6dc53aac1c59c6d46f27ad1d91bfaf227cf136a + md5: 27c5be39d9e4d25fe85b89a069360d1e + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 + size: 257473 + timestamp: 1786106677325 +- conda: https://conda.anaconda.org/conda-forge/win-64/pthread-stubs-0.4-hfa92662_1004.conda + sha256: 2418cf449df76b0da851cb59b7c826a9ade81914eaff799fbfd3f509ba1edf46 + md5: fda2f9fedee1b85ba855ea26a9b6bbf8 + depends: + - libgcc >=15 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: {} + size: 10612 + timestamp: 1788382011501 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.10.22-hc20f281_0_cpython.conda + sha256: ef2d4feaa760b8a4059e5b3307867d3aa65fcb58282a4084ddacaacb16f957ae + md5: 6cfea346c7aacb6f4daeb279bfb88beb + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.4,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.9,<4.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.10.* *_cp310 + noarch: + - python + size: 16178075 + timestamp: 1791327673101 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.8-h53f6dd8_101_cp314.conda + build_number: 101 + sha256: 6372598cff41f4145686a9bfa3a0399354f34fc3f813b0218a4760428a33d3db + md5: e10e1e2dc571bc18b72d7b231d448cb5 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libpython 3.14.8 h4f90d01_101_cp314 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.14.* *_cp314 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 18253133 + timestamp: 1791333695156 + python_site_packages_path: Lib/site-packages +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + sha256: a2aff34027aa810ff36a190b75002d2ff6f9fbef71ec66e567616ac3a679d997 + md5: 0cd9b88826d0f8db142071eb830bce56 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + run_exports: {} + size: 181257 + timestamp: 1770223460931 +- conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py314hc5dbbe4_5.conda + sha256: a754af80a883b2bad3ab291e6458d8a6994b60a6e4b19c1310283d7ee205e206 + md5: 73fd03bb5e578d5d0c16fc7356faf84c + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + run_exports: {} + size: 118716 + timestamp: 1788881215870 +- conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.15.2-py310h15c175c_0.conda + sha256: f19350c2061b1cdc3151a33c3dd4f71a1a481f9b10ac186674f957814bc839bc + md5: 81798168111d1021e3d815217c444418 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.5 + - numpy >=1.19,<3 + - numpy >=1.23.5 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 14352068 + timestamp: 1739793156239 +- conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.18.1-py314h67d5eaa_1.conda + sha256: 7c61859f318f779c91c3451ae1afeded04edd255e84fbf97738410c42332a331 + md5: 75ebc6f541ecf3f49a9e6b40d4ffa412 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.8 + - numpy >=1.25,<3 + - numpy >=2.0.0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 14991924 + timestamp: 1790022987236 +- conda: https://conda.anaconda.org/conda-forge/win-64/simde-0.8.2-hc790b64_0.conda + sha256: 518995344f4ac4c94c2eb207fb806af960a82fca5f87cab066de6ada20a974c0 + md5: 3dc81609aedcf489d8c2abe82c9ceb46 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + run_exports: {} + size: 483090 + timestamp: 1714665491492 +- conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.1.0-h272cf33_2.conda + sha256: 65f5a52eb5250ca0d627e6958e703583dca008988695284fc2181b3a0a790efd + md5: 83371bd3f796b3c2d3f0436692d3ea73 + depends: + - libhwloc >=2.15.0,<2.15.1.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: APACHE + run_exports: {} + size: 157572 + timestamp: 1790591966816 +- conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + sha256: f19618a3a82cc483dacf1c70a30367ee7b0c7e71b90f1f80e14feff44fbd3688 + md5: dd9eb33c99d352b6356f86964d6040f7 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3782376 + timestamp: 1787272860855 +- conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 + md5: 71b24316859acd00bdb8b38f5e2ce328 + constrains: + - vc14_runtime >=14.29.30037 + - vs2015_runtime >=14.29.30037 + license: LicenseRef-MicrosoftWindowsSDK10 + run_exports: {} + size: 694692 + timestamp: 1756385147981 +- conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py314h909e829_0.conda + sha256: 96990a5948e0c30788360836d94bf6145fdac0c187695ed9b3c2d61d9e11d267 + md5: 54e012b629ac5a40c9b3fa32738375dc + depends: + - cffi + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + run_exports: {} + size: 18504 + timestamp: 1769438844417 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + sha256: 35444c55a92e2f7f7ba26bc70f81e56e52344f7d064c0fd4b40a46a58517b79c + md5: aa805b5522c2a98fa286e551a1f48546 + depends: + - vc14_runtime >=14.51.36247 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + run_exports: {} + size: 21383 + timestamp: 1785359368566 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + sha256: 4e4cb599cdc41bf2109d1464c127b5bcbddf548ce3e322e612afb691338b48f8 + md5: ac5333bb3d429361f23adf704cc49a78 + depends: + - ucrt >=10.0.20348.0 + - vcomp14 14.51.36247 habf1de7_41 + constrains: + - vs2015_runtime 14.51.36247.* *_41 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + run_exports: {} + size: 767955 + timestamp: 1785359364369 +- conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + sha256: 731e043390c9457299484d39e427221fc868a9249540a498a5a4f6456c7744d1 + md5: 350bb67a5c8e5f1c53347ac544ab6600 + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.51.36247.* *_41 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + run_exports: + strong: + - vcomp14 >=14.51.36247 + size: 155910 + timestamp: 1785359349999 +- conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + sha256: 9d7d1b43cf4af5a8e8b1646175c9f899ffbcab189a33ac41127a96e7bcf41af0 + md5: 04190e0ebd886433300ce9343ee98942 + depends: + - vswhere + constrains: + - vs_win-64 2022.14 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + run_exports: + strong: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + size: 25462 + timestamp: 1785358620723 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libice-1.1.2-hd74fcf3_0.conda + sha256: 85832f409756e78d6d0a92756cd5463fa253219041e40a681d5e8d4c9d21ec8b + md5: a1629a20e5b128c4512b80a93bb1ae55 + depends: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - libgcc >=14 + - ucrt >=10.0.20348.0 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libice >=1.1.2,<2.0a0 + size: 168856 + timestamp: 1786474456144 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libsm-1.2.6-hd74fcf3_1.conda + sha256: bc043a818313abfd836e4e662df1cc9edd6d81994c87a8b35004ca286cebe7c8 + md5: edb94e6121d977d7bc2cc0f56d656c14 + depends: + - libgcc >=14 + - ucrt >=10.0.20348.0 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - xorg-libice >=1.1.2,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libsm >=1.2.6,<2.0a0 + size: 116838 + timestamp: 1786545424783 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libx11-1.8.13-hfa52320_1.conda + sha256: 4f86b6f9e8bd76e219440be595bbd7aeba3fe9ad56e4f10c7b41dfd03fb9c3a6 + md5: 369df5999d1a5baf57b53fd892aafc7e + depends: + - libgcc >=14 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - libxcb >=1.17.0,<2.0a0 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libx11 >=1.8.13,<2.0a0 + size: 954803 + timestamp: 1787087422301 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxau-1.0.12-hfa92662_2.conda + sha256: b9f063792e4d50ef2669c30dfc4ba14aefb4fdc37e384241a71093bee0493ad1 + md5: 68403004c805ce03b71a5889a4c47fa1 + depends: + - libgcc >=15 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxau >=1.0.12,<2.0a0 + size: 112892 + timestamp: 1788960775276 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxdmcp-1.1.5-hfa92662_2.conda + sha256: 6265afeeaab391aa245e173dba5e18c8e69ac5a73f60fe20d8057ebadafbb4a4 + md5: 17274cf7d62e029e62653a3e6c80b379 + depends: + - libgcc >=15 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxdmcp >=1.1.5,<2.0a0 + size: 72768 + timestamp: 1789677202037 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxext-1.3.7-hfa92662_1.conda + sha256: bd39b2950d5144eb6bd5fafc4002fa7bbdcf2f72c32e4709aa080cb4c158ec4a + md5: ff2351642e25ff00ae484a6b533c0c9e + depends: + - libgcc >=15 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxext >=1.3.7,<2.0a0 + size: 288484 + timestamp: 1787101089071 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxpm-3.5.19-hba3369d_0.conda + sha256: 1d3907533a6e26bb62f109a33107064e2140503a8076de5b28b384ef3e473d27 + md5: 39d8a6b9a87047c817e5881fc0706684 + depends: + - libgcc >=14 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxt >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxpm >=3.5.19,<4.0a0 + size: 237565 + timestamp: 1776790287445 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxt-1.3.1-hfa92662_1.conda + sha256: 4d1d9b59dc7c2e90f0a1388dd6feb87b54a033bba29f7a7269e35487d332c5be + md5: 41eebca909ba9e18a69eba80152ffb1c + depends: + - libgcc >=15 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + - xorg-libice >=1.1.2,<2.0a0 + - xorg-libsm >=1.2.6,<2.0a0 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + run_exports: + weak: + - xorg-libxt >=1.3.1,<2.0a0 + size: 927081 + timestamp: 1787103397071 +- conda: https://conda.anaconda.org/conda-forge/win-64/xxhash-0.8.3-h39ac402_1.conda + sha256: c7513e6a88e5517341ae9270356b11a6e5303ea5b432fcfccaa43026556907a4 + md5: 0deb212e7a828d55704fd701f953c662 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + run_exports: + weak: + - xxhash >=0.8.3,<0.8.4.0a0 + size: 106862 + timestamp: 1785949407819 +- conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + sha256: 80ee68c1e7683a35295232ea79bcc87279d31ffeda04a1665efdb43cbd50a309 + md5: 433699cba6602098ae8957a323da2664 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 + size: 63944 + timestamp: 1753484092156 +- conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + sha256: 5a0b55df66ff07b4342e04967cef69f8bf348f6a0fb1cc1eca741c7b015dfe77 + md5: 945092a9bc1d0f250f7d5ecf51ecd471 + depends: + - libzlib 1.3.2 hfd05255_3 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Zlib + license_family: Other + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 851288 + timestamp: 1785276674755 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + sha256: ca7daae4f218a11fab82cc2857f0ea518ec3f46acec60490485347a4c22c6b3e + md5: e4ac308c39d6d0e131154976da67cf3b + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 387535 + timestamp: 1786599623274 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 000000000..c551ec9ce --- /dev/null +++ b/pixi.toml @@ -0,0 +1,302 @@ +[workspace] +name = "proxsuite" +version = "0.7.2" +description = "The Advanced Proximal Optimization Toolbox" +platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"] +channels = ["conda-forge"] +license = "BSD-2-Clause" +license-file = "LICENSE" +preview = ["pixi-build"] + +[dependencies] +ccache = "*" +cmake = ">=3.22" +cxx-compiler = "*" +ninja = "*" +jrl-cmakemodules = ">=2.1.0" +eigen = ">=3.4.0" +simde = ">=0.8.2" +cereal = ">=1.3.0" + +[package] +name = { workspace = true } +version = { workspace = true } + +[package.build] +backend = { name = "pixi-build-cmake", version = "*" } + +[package.build.config] +extra-args = [ + "--log-level=DEBUG", + "-DBUILD_WITH_VECTORIZATION_SUPPORT=ON", + "-DPROXSUITE_BUILD_EXAMPLES=OFF", + "-DBUILD_BENCHMARK=OFF", + "-DBUILD_TESTING=OFF", + "-DPROXSUITE_BUILD_MAROS_MESZAROS_TESTS=OFF", + "-DBUILD_PYTHON_INTERFACE=ON", +] + +[package.build-dependencies] +ccache = "*" +cmake = ">=3.22" +cxx-compiler = "*" +ninja = "*" +jrl-cmakemodules = ">=2.1.0" + +[package.host-dependencies] +eigen = ">=3.4.0" +simde = ">=0.8.2" +python = ">=3.10" +numpy = ">=1.24.0" +nanobind = ">=2.5.0" +cereal = ">=1.3.0" + +[package.run-dependencies] +eigen = ">=3.4.0" +simde = ">=0.8.2" +cereal = ">=1.3.0" + +[target.unix.activation] +scripts = ["development/scripts/pixi/activation.sh"] + +[target.win-64.activation] +scripts = ["development/scripts/pixi/activation.bat"] + +[activation.env] +# Setup ccache +CMAKE_CXX_COMPILER_LAUNCHER = "ccache" +# Create compile_commands.json for language server +CMAKE_EXPORT_COMPILE_COMMANDS = "ON" +# Activate color output with Ninja +CMAKE_COLOR_DIAGNOSTICS = "ON" +# Help ccache manage generated files and PCH (https://ccache.dev/manual/latest.html#_precompiled_headers) +CCACHE_SLOPPINESS = "include_file_ctime,include_file_mtime,pch_defines,time_macros" + +[tasks] +configure = { cmd = [ + "CXXFLAGS=$PROXSUITE_CXX_FLAGS", + "cmake", + "-G", + "Ninja", + "-B", + "build", + "-S", + ".", + "-DJRL_CMAKEMODULES_SOURCE_DIR=$JRL_CMAKEMODULES_SOURCE_DIR", + "-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX", + "-DCMAKE_BUILD_TYPE=$PROXSUITE_BUILD_TYPE", + "-DBUILD_WITH_VECTORIZATION_SUPPORT=$PROXSUITE_BUILD_VECTORIZATION", + "-DPROXSUITE_BUILD_MAROS_MESZAROS_TESTS=$PROXSUITE_BUILD_MAROS_MESZAROS_TESTS", + "-DPROXSUITE_BUILD_EXAMPLES=ON", + "-DBUILD_BENCHMARK=ON", + "-DBUILD_TESTING=$PROXSUITE_BUILD_TESTING", + "-DBUILD_PYTHON_INTERFACE=$PROXSUITE_BUILD_PYTHON_INTERFACE", +] } +build = { cmd = "cmake --build build", depends-on = ["configure"] } +clean = { cmd = "rm -rf build" } +test = { cmd = "ctest --test-dir build -LE maros_meszaros --output-on-failure", depends-on = [ + "build", +] } +install = { cmd = "cmake --build build --target install", depends-on = [ + "build", +] } +uninstall = { cmd = "cmake --build build --target uninstall", depends-on = [ + "install", +] } + +test-import-python = { depends-on = [ + "install", +], cmd = [ + "python", + "-c", + "import proxsuite; print(proxsuite.helpers.printVersion())", +] } + +_test-packaging-simple-configure = { depends-on = [ + "install", +], cmd = [ + "cmake", + "-G", + "Ninja", + "-S", + "test/packaging/cmake", + "-B", + "build/packaging", + "-DJRL_CMAKEMODULES_SOURCE_DIR=$JRL_CMAKEMODULES_SOURCE_DIR", + "--log-level=DEBUG", +] } +_test-packaging-simple = { depends-on = [ + "_test-packaging-simple-configure", +], cmd = [ + "cmake", + "--build", + "build/packaging", + "--verbose", +] } +_test-packaging-components-configure = { depends-on = [ + "install", +], cmd = [ + "cmake", + "-G", + "Ninja", + "-S", + "test/packaging/cmake-components", + "-B", + "build/packaging-components", + "-DJRL_CMAKEMODULES_SOURCE_DIR=$JRL_CMAKEMODULES_SOURCE_DIR", + "--log-level=DEBUG", +] } +_test-packaging-components = { depends-on = [ + "_test-packaging-components-configure", +], cmd = [ + "cmake", + "--build", + "build/packaging-components", + "--verbose", +] } +_test-packaging-fetchcontent-configure = { cmd = [ + "cmake", + "-G", + "Ninja", + "-S", + "test/packaging/fetchcontent", + "-B", + "build/packaging-fetchcontent", + "-DJRL_CMAKEMODULES_SOURCE_DIR=$JRL_CMAKEMODULES_SOURCE_DIR", + "-DPROXSUITE_FETCHCONTENT_SOURCE_DIR=$PIXI_PROJECT_ROOT", + "--log-level=DEBUG", +] } +_test-packaging-fetchcontent = { depends-on = [ + "_test-packaging-fetchcontent-configure", +], cmd = [ + "cmake", + "--build", + "build/packaging-fetchcontent", + "--verbose", +] } +test-packaging = { depends-on = [ + "_test-packaging-simple", + "_test-packaging-components", + "_test-packaging-fetchcontent", +] } + +# --- Python Feature --- +[feature.python.dependencies] +python = ">=3.10" +numpy = ">=1.24.0" +nanobind = ">=2.5.0" + +[feature.python.activation.env] +PROXSUITE_BUILD_PYTHON_INTERFACE = "ON" + +[feature.python-latest.dependencies] +python = "3.14.*" + +[feature.python-oldest.dependencies] +python = "3.10.*" + +# --- Test Feature --- +[feature.test.dependencies] +catch2 = ">=3.4.0" +scipy = ">=1.7.0" +libmatio = ">=1.5.0" + +[feature.test.activation.env] +PROXSUITE_BUILD_TESTING = "ON" + +[feature.maros-meszaros.activation.env] +PROXSUITE_BUILD_MAROS_MESZAROS_TESTS = "ON" + +[feature.maros-meszaros.tasks] +test-maros-meszaros = { cmd = "ctest --test-dir build -L maros_meszaros --output-on-failure", depends-on = [ + "build", +] } + +# --- Documentation Feature --- +[feature.doc.dependencies] +doxygen = ">=1.10.0" +graphviz = ">=10.0.0" + +[feature.doc.tasks] +_configure-documentation = { cmd = [ + "cmake", + "-S", + ".", + "-B", + "build/doc_build", + "-G", + "Ninja", + "-DJRL_CMAKEMODULES_SOURCE_DIR=$JRL_CMAKEMODULES_SOURCE_DIR", + "-DCMAKE_INSTALL_PREFIX=build/doc_install", + "-DCMAKE_BUILD_TYPE=Release", + "-DBUILD_TESTING=OFF", + "-DBUILD_PYTHON_INTERFACE=OFF", + "-DBUILD_DOCUMENTATION=ON", + "-DINSTALL_DOCUMENTATION=ON", +] } +build-documentation = { depends-on = [ + "_configure-documentation", +], cmd = [ + "cmake", + "--build", + "build/doc_build", + "--target", + "proxsuite-doc", +] } +install-documentation = { depends-on = [ + "build-documentation", +], cmd = [ + "cmake", + "--install", + "build/doc_build", + "--component", + "doc", +] } + +# --- Lint Feature --- +[feature.lint.dependencies] +pre-commit = "*" + +[feature.lint.tasks] +lint = { cmd = "pre-commit run --all" } + +# --- New version Feature --- +[feature.new-version] +dependencies = { jrl-cmakemodules-scripts = "*" } + +# --- Clang Feature --- +[feature.clang] +activation = { env = { CC = "clang", CXX = "clang++" } } +dependencies = { clangxx = "*", lld = "*" } + +[feature.clang.target.win-64.dependencies] +llvm-tools = "*" + +# --- Environments --- +[environments] +default = { features = [ + "python", + "test", + "python-latest", +], solve-group = "python-latest" } +clang = { features = ["clang", "python", "test", "python-latest"] } +all-clang = { features = [ + "clang", + "python", + "test", + "python-latest", +], solve-group = "python-latest" } +lint = { features = ["lint"], no-default-feature = true } +new-version = { features = ["new-version"], no-default-feature = true } +python-oldest = { features = [ + "python", + "test", + "python-oldest", +], solve-group = "python-oldest" } +maros-meszaros = { features = [ + "python", + "test", + "maros-meszaros", + "python-latest", +], solve-group = "python-latest" } +doc = { features = ["doc"] } diff --git a/pyproject.toml b/pyproject.toml index 584df75c3..0e55c942a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,9 +6,9 @@ name = "proxsuite" version = "0.7.3" description = "Quadratic Programming Solver for Robotics and beyond." readme = "README.md" -requires-python = ">= 3.8" +requires-python = ">=3.10" license = "BSD-2-Clause" -dependencies = ["numpy","scipy"] +dependencies = ["numpy>=1.24.0", "scipy>=1.8.0"] [project.urls] homepage = "https://github.com/Simple-Robotics/proxsuite" @@ -16,5 +16,4 @@ repository = "https://github.com/Simple-Robotics/proxsuite.git" [tool.ruff.lint] ignore = [ "E741" ] -extend-select = ["W605"] -exclude = [ "cmake-module/*", "bindings/python/external/nanobind/*" ] +extend-select = [ "W605" ] diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dbea3694d..0963552ce 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,116 +1,12 @@ -include(../cmake-external/doctest.cmake) -find_package(Matio REQUIRED) - -add_library(${PROJECT_NAME}-doctest STATIC doctest/doctest.cpp) -target_include_directories(${PROJECT_NAME}-doctest PUBLIC ./doctest) -add_library(cnpy OBJECT src/cnpy.cpp) -target_link_libraries(cnpy Eigen3::Eigen) -target_include_directories(cnpy PUBLIC ./include) - -file(GLOB_RECURSE TEST_HEADERS ./include/*.hpp) -ADD_HEADER_GROUP(TEST_HEADERS) - -add_library( - proxsuite-test-util - STATIC - ./src/util_f64.cpp - ./src/util_f32.cpp - ${TEST_HEADERS} -) -target_include_directories(proxsuite-test-util PUBLIC ./include) -if(BUILD_WITH_VECTORIZATION_SUPPORT) - target_link_libraries(proxsuite-test-util proxsuite-vectorized matio) -else() - target_link_libraries(proxsuite-test-util proxsuite matio) -endif() - -macro(proxsuite_test name path) - set(target_name ${PROJECT_NAME}-test-cpp-${name}) - add_executable(${target_name} ${path}) - doctest_discover_tests(${target_name}) - target_link_libraries( - ${target_name} - PUBLIC proxsuite ${PROJECT_NAME}-doctest proxsuite-test-util - ) - target_compile_definitions( - ${target_name} - PRIVATE PROBLEM_PATH="${CMAKE_CURRENT_SOURCE_DIR}" - ) - add_dependencies(build_tests ${target_name}) -endmacro() - -proxsuite_test(dense_ruiz_equilibration src/dense_ruiz_equilibration.cpp) -proxsuite_test(dense_qp_eq src/dense_qp_eq.cpp) -proxsuite_test(dense_qp_with_eq_and_in src/dense_qp_with_eq_and_in.cpp) -proxsuite_test(dense_qp_unconstrained src/dense_unconstrained_qp.cpp) -proxsuite_test(dense_backward src/dense_backward.cpp) -proxsuite_test(dense_qp_wrapper src/dense_qp_wrapper.cpp) -proxsuite_test(dense_qp_solve src/dense_qp_solve.cpp) -proxsuite_test(sparse_ruiz_equilibration src/sparse_ruiz_equilibration.cpp) -proxsuite_test(sparse_qp src/sparse_qp.cpp) -proxsuite_test(sparse_qp_wrapper src/sparse_qp_wrapper.cpp) -proxsuite_test(sparse_qp_solve src/sparse_qp_solve.cpp) -proxsuite_test(sparse_factorization src/sparse_factorization.cpp) -proxsuite_test(cvxpy src/cvxpy.cpp) - -if(BUILD_WITH_OPENMP_SUPPORT) - proxsuite_test(parallel src/parallel_qp_solve.cpp) - target_link_libraries( - ${PROJECT_NAME}-test-cpp-parallel - PRIVATE OpenMP::OpenMP_CXX - ) -endif() - -# Test serialization -macro(ADD_TEST_CFLAGS target flag) - set_property(TARGET ${target} APPEND_STRING PROPERTY COMPILE_FLAGS " ${flag}") -endmacro() - -make_directory("${CMAKE_CURRENT_BINARY_DIR}/serialization-data") -proxsuite_test(serialization src/serialization.cpp) -add_test_cflags( - ${PROJECT_NAME}-test-cpp-serialization - "-DTEST_SERIALIZATION_FOLDER=\\\\\"${CMAKE_CURRENT_BINARY_DIR}/serialization-data\\\\\"" +find_path( + MAROS_MESZAROS_DIR + NAMES AUG2D.mat QPCBOEI1.mat + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/data/maros_meszaros_data + REQUIRED ) -if(cereal_FOUND) - target_link_libraries( - ${PROJECT_NAME}-test-cpp-serialization - PRIVATE cereal::cereal - ) -else() - target_include_directories( - ${PROJECT_NAME}-test-cpp-serialization - SYSTEM - PRIVATE ${PROJECT_SOURCE_DIR}/external/cereal/include - ) -endif() -if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT MSVC) - proxsuite_test(dense_maros_meszaros src/dense_maros_meszaros.cpp) - proxsuite_test(sparse_maros_meszaros src/sparse_maros_meszaros.cpp) -endif() +add_subdirectory(cpp) if(BUILD_PYTHON_INTERFACE) - file(GLOB_RECURSE ${PROJECT_NAME}_PYTHON_UNITTEST *.py) - - if( - (CMAKE_BUILD_TYPE STREQUAL "Debug" AND MSVC) - OR NOT BUILD_WITH_OPENMP_SUPPORT - ) - list_filter( - "${${PROJECT_NAME}_PYTHON_UNITTEST}" - "parallel_qp_solve" - ${PROJECT_NAME}_PYTHON_UNITTEST - ) - endif() - - foreach(TEST_FILE ${${PROJECT_NAME}_PYTHON_UNITTEST}) - get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) - string(REGEX REPLACE "${PROJECT_SOURCE_DIR}/" "" TEST_FILE ${TEST_FILE}) - ADD_PYTHON_UNIT_TEST( - "${PROJECT_NAME}-test-py-${TEST_NAME}" - "${TEST_FILE}" - "bindings/python" - ) - endforeach() -endif(BUILD_PYTHON_INTERFACE) + add_subdirectory(python) +endif() diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt new file mode 100644 index 000000000..fec0e9b18 --- /dev/null +++ b/test/cpp/CMakeLists.txt @@ -0,0 +1,96 @@ +add_library(proxsuite-test-util STATIC util_f64.cpp util_f32.cpp) +target_link_libraries(proxsuite-test-util PUBLIC proxsuite) +proxsuite_set_default_target_options(proxsuite-test-util) + +if(BUILD_WITH_VECTORIZATION_SUPPORT) + add_library(proxsuite-test-util-vectorized STATIC util_f64.cpp util_f32.cpp) + target_include_directories(proxsuite-test-util-vectorized PRIVATE include) + target_link_libraries(proxsuite-test-util-vectorized PUBLIC proxsuite-vectorized) + proxsuite_set_default_target_options(proxsuite-test-util-vectorized) +endif() + +function(proxsuite_add_test name) + set(options) + set(oneValueArgs) + set(multiValueArgs COMPILE_DEFINITIONS LINK_LIBRARIES LABELS) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + add_executable(proxsuite-test-cpp-${name} ${name}.cpp) + target_link_libraries( + proxsuite-test-cpp-${name} + PRIVATE proxsuite-test-util Catch2::Catch2WithMain ${arg_LINK_LIBRARIES} + ) + target_compile_definitions(proxsuite-test-cpp-${name} PRIVATE ${arg_COMPILE_DEFINITIONS}) + proxsuite_set_default_target_options(proxsuite-test-cpp-${name}) + add_test(NAME proxsuite-test-cpp.${name} COMMAND proxsuite-test-cpp-${name}) + + if(arg_LABELS) + set_tests_properties(proxsuite-test-cpp.${name} PROPERTIES LABELS "${arg_LABELS}") + endif() + + if(BUILD_WITH_VECTORIZATION_SUPPORT) + add_executable(proxsuite-vectorized-test-cpp-${name} ${name}.cpp) + target_link_libraries( + proxsuite-vectorized-test-cpp-${name} + PRIVATE proxsuite-test-util-vectorized Catch2::Catch2WithMain ${arg_LINK_LIBRARIES} + ) + target_compile_definitions( + proxsuite-vectorized-test-cpp-${name} + PRIVATE ${arg_COMPILE_DEFINITIONS} + ) + proxsuite_set_default_target_options(proxsuite-vectorized-test-cpp-${name}) + add_test( + NAME proxsuite-test-cpp.vectorized.${name} + COMMAND proxsuite-vectorized-test-cpp-${name} + ) + if(arg_LABELS) + set_tests_properties( + proxsuite-test-cpp.vectorized.${name} + PROPERTIES LABELS "vectorized;${arg_LABELS}" + ) + endif() + endif() +endfunction() + +proxsuite_add_test(uint128) +proxsuite_add_test(cvxpy) +proxsuite_add_test(dense_backward) +proxsuite_add_test(dense_qp_eq) +proxsuite_add_test(dense_qp_solve) +proxsuite_add_test(dense_qp_with_eq_and_in) +proxsuite_add_test(dense_qp_wrapper) +proxsuite_add_test(dense_ruiz_equilibration) +proxsuite_add_test(dense_unconstrained_qp) +proxsuite_add_test(sparse_factorization) +proxsuite_add_test(sparse_qp_solve) +proxsuite_add_test(sparse_qp_wrapper) +proxsuite_add_test(sparse_qp) +proxsuite_add_test(sparse_ruiz_equilibration) + +if(BUILD_WITH_OPENMP_SUPPORT) + proxsuite_add_test(parallel_qp_solve LINK_LIBRARIES proxsuite-parallel) +endif() + +if(PROXSUITE_BUILD_WITH_SERIALIZATION) + # We have to create the folder for the output data, tests don't do that. + make_directory(${CMAKE_BINARY_DIR}/serialization-data) + proxsuite_add_test( + serialization + COMPILE_DEFINITIONS TEST_SERIALIZATION_FOLDER="${CMAKE_BINARY_DIR}/serialization-data" + ) +endif() + +if(PROXSUITE_BUILD_MAROS_MESZAROS_TESTS) + proxsuite_add_test( + dense_maros_meszaros + COMPILE_DEFINITIONS MAROS_MESZAROS_DIR="${MAROS_MESZAROS_DIR}/" + LINK_LIBRARIES matio::matio + LABELS maros_meszaros + ) + proxsuite_add_test( + sparse_maros_meszaros + COMPILE_DEFINITIONS MAROS_MESZAROS_DIR="${MAROS_MESZAROS_DIR}/" + LINK_LIBRARIES matio::matio + LABELS maros_meszaros + ) +endif() diff --git a/test/src/cvxpy.cpp b/test/cpp/cvxpy.cpp similarity index 86% rename from test/src/cvxpy.cpp rename to test/cpp/cvxpy.cpp index dfdb6df2e..437badc2b 100644 --- a/test/src/cvxpy.cpp +++ b/test/cpp/cvxpy.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 INRIA // #include -#include +#include #include #include @@ -19,7 +19,7 @@ using Mat = template using Vec = Eigen::Matrix; -DOCTEST_TEST_CASE("3 dim test case from cvxpy, check feasibility") +TEST_CASE("3 dim test case from cvxpy, check feasibility") { std::cout << "---3 dim test case from cvxpy, check feasibility " << std::endl; @@ -48,8 +48,8 @@ DOCTEST_TEST_CASE("3 dim test case from cvxpy, check feasibility") .lpNorm(); T dua_res = (H * results.x + g + C.transpose() * results.z).lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "primal residual: " << pri_res << std::endl; std::cout << "dual residual: " << dua_res << std::endl; @@ -58,7 +58,7 @@ DOCTEST_TEST_CASE("3 dim test case from cvxpy, check feasibility") << results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE("simple test case from cvxpy, check feasibility") +TEST_CASE("simple test case from cvxpy, check feasibility") { std::cout << "---simple test case from cvxpy, check feasibility " @@ -90,9 +90,9 @@ DOCTEST_TEST_CASE("simple test case from cvxpy, check feasibility") (H * results.x + g + C.transpose() * results.z).lpNorm(); T x_sol = 0.5; - DOCTEST_CHECK((x_sol - results.x.coeff(0, 0)) <= eps_abs); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK((x_sol - results.x.coeff(0, 0)) <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "primal residual: " << pri_res << std::endl; std::cout << "dual residual: " << dua_res << std::endl; @@ -101,8 +101,8 @@ DOCTEST_TEST_CASE("simple test case from cvxpy, check feasibility") << results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE("simple test case from cvxpy, init with solution, check that " - "solver stays there") +TEST_CASE("simple test case from cvxpy, init with solution, check that " + "solver stays there") { std::cout << "---simple test case from cvxpy, init with solution, check that " @@ -147,10 +147,10 @@ DOCTEST_TEST_CASE("simple test case from cvxpy, init with solution, check that " T dua_res = (H * qp.results.x + g + C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(qp.results.info.iter <= 0); - DOCTEST_CHECK((x_sol - qp.results.x.coeff(0, 0)) <= eps_abs); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(qp.results.info.iter <= 0); + CHECK((x_sol - qp.results.x.coeff(0, 0)) <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "primal residual: " << pri_res << std::endl; std::cout << "dual residual: " << dua_res << std::endl; diff --git a/test/src/dense_backward.cpp b/test/cpp/dense_backward.cpp similarity index 92% rename from test/src/dense_backward.cpp rename to test/cpp/dense_backward.cpp index 346275161..9a70aaeac 100644 --- a/test/src/dense_backward.cpp +++ b/test/cpp/dense_backward.cpp @@ -2,9 +2,7 @@ // Copyright (c) 2023 INRIA // #include -#include -#include -#include +#include #include #include #include @@ -13,7 +11,7 @@ using T = double; using namespace proxsuite; using namespace proxsuite::proxqp; -DOCTEST_TEST_CASE("proxqp::dense: test compute backward for g (feasible QP)") +TEST_CASE("proxqp::dense: test compute backward for g (feasible QP)") { double sparsity_factor = 0.85; T eps_abs = T(1e-9); @@ -74,12 +72,12 @@ DOCTEST_TEST_CASE("proxqp::dense: test compute backward for g (feasible QP)") // Compare dx_dg_fd with the result from the backward function for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { - DOCTEST_CHECK(std::abs(dx_dg_fd(i, j) - dx_dg(i, j)) < 1e-5); + CHECK(std::abs(dx_dg_fd(i, j) - dx_dg(i, j)) < 1e-5); } } } -DOCTEST_TEST_CASE("proxqp::dense: test compute backward for b (feasible QP)") +TEST_CASE("proxqp::dense: test compute backward for b (feasible QP)") { double sparsity_factor = 0.85; T eps_abs = T(1e-9); @@ -140,13 +138,13 @@ DOCTEST_TEST_CASE("proxqp::dense: test compute backward for b (feasible QP)") // Compare dx_db_fd with the result from the backward function for (int i = 0; i < dim; i++) { for (int j = 0; j < n_eq; j++) { - DOCTEST_CHECK(std::abs(dx_db_fd(i, j) - dx_db(i, j)) < 1e-5); + CHECK(std::abs(dx_db_fd(i, j) - dx_db(i, j)) < 1e-5); } } } -DOCTEST_TEST_CASE("proxqp::dense: test compute backward for g (QP with " - "saturating inequality constraints)") +TEST_CASE("proxqp::dense: test compute backward for g (QP with " + "saturating inequality constraints)") { double sparsity_factor = 0.85; T eps_abs = T(1e-9); @@ -216,7 +214,7 @@ DOCTEST_TEST_CASE("proxqp::dense: test compute backward for g (QP with " // Compare dx_dg_fd with the result from the backward function for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { - DOCTEST_CHECK(std::abs(dx_dg_fd(i, j) - dx_dg(i, j)) < 1e-5); + CHECK(std::abs(dx_dg_fd(i, j) - dx_dg(i, j)) < 1e-5); } } } \ No newline at end of file diff --git a/test/src/dense_maros_meszaros.cpp b/test/cpp/dense_maros_meszaros.cpp similarity index 98% rename from test/src/dense_maros_meszaros.cpp rename to test/cpp/dense_maros_meszaros.cpp index 9fcc4a88e..d3a5017df 100644 --- a/test/src/dense_maros_meszaros.cpp +++ b/test/cpp/dense_maros_meszaros.cpp @@ -1,15 +1,13 @@ // // Copyright (c) 2022 INRIA // -#include -#include +#include +#include "maros_meszaros.hpp" #include #include using namespace proxsuite; -#define MAROS_MESZAROS_DIR PROBLEM_PATH "/data/maros_meszaros_data/" - char const* files[] = { MAROS_MESZAROS_DIR "AUG2D.mat", MAROS_MESZAROS_DIR "AUG2DC.mat", MAROS_MESZAROS_DIR "AUG2DCQP.mat", MAROS_MESZAROS_DIR "AUG2DQP.mat", diff --git a/test/src/dense_qp_eq.cpp b/test/cpp/dense_qp_eq.cpp similarity index 87% rename from test/src/dense_qp_eq.cpp rename to test/cpp/dense_qp_eq.cpp index 2a6aa2541..2d707e60a 100644 --- a/test/src/dense_qp_eq.cpp +++ b/test/cpp/dense_qp_eq.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 - 2024 INRIA // #include -#include +#include #include #include #include @@ -11,7 +11,7 @@ using T = double; using namespace proxsuite; -DOCTEST_TEST_CASE("qp: start from solution using the wrapper framework") +TEST_CASE("qp: start from solution using the wrapper framework") { proxqp::isize dim = 30; proxqp::isize n_eq = 6; @@ -49,12 +49,12 @@ DOCTEST_TEST_CASE("qp: start from solution using the wrapper framework") qp.init(H, g, A, b, C, l, u); qp.solve(primal_solution, dual_solution, dual_init_in); - DOCTEST_CHECK((A * qp.results.x - b).lpNorm() <= eps_abs); - DOCTEST_CHECK((H * qp.results.x + g + A.transpose() * qp.results.y) - .lpNorm() <= eps_abs); + CHECK((A * qp.results.x - b).lpNorm() <= eps_abs); + CHECK((H * qp.results.x + g + A.transpose() * qp.results.y) + .lpNorm() <= eps_abs); } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality constraints " - "and increasing dimension with the wrapper API") +TEST_CASE("sparse random strongly convex qp with equality constraints " + "and increasing dimension with the wrapper API") { std::cout << "---testing sparse random strongly convex qp with equality " @@ -89,8 +89,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality constraints " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using wrapper API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -100,8 +100,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality constraints " << std::endl; } } -DOCTEST_TEST_CASE("linear problem with equality with equality constraints and " - "linar cost and increasing dimension using wrapper API") +TEST_CASE("linear problem with equality with equality constraints and " + "linar cost and increasing dimension using wrapper API") { std::cout << "---testing linear problem with equality constraints and " @@ -143,8 +143,8 @@ DOCTEST_TEST_CASE("linear problem with equality with equality constraints and " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using wrapper API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -155,9 +155,9 @@ DOCTEST_TEST_CASE("linear problem with equality with equality constraints and " } } -DOCTEST_TEST_CASE("linear problem with equality with equality constraints and " - "linear cost and increasing dimension using wrapper API and " - "the dedicated LP interface") +TEST_CASE("linear problem with equality with equality constraints and " + "linear cost and increasing dimension using wrapper API and " + "the dedicated LP interface") { std::cout @@ -202,8 +202,8 @@ DOCTEST_TEST_CASE("linear problem with equality with equality constraints and " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using wrapper API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -214,7 +214,7 @@ DOCTEST_TEST_CASE("linear problem with equality with equality constraints and " } } -DOCTEST_TEST_CASE("infeasible qp") +TEST_CASE("infeasible qp") { // (x1- 9)^2 + (x2-6)^2 // s.t. @@ -251,6 +251,6 @@ DOCTEST_TEST_CASE("infeasible qp") qp.solve(); - DOCTEST_CHECK(qp.results.info.status == - proxsuite::proxqp::QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE); + CHECK(qp.results.info.status == + proxsuite::proxqp::QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE); } \ No newline at end of file diff --git a/test/src/dense_qp_solve.cpp b/test/cpp/dense_qp_solve.cpp similarity index 91% rename from test/src/dense_qp_solve.cpp rename to test/cpp/dense_qp_solve.cpp index 012bcb4c5..9da18ebac 100644 --- a/test/src/dense_qp_solve.cpp +++ b/test/cpp/dense_qp_solve.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 INRIA // #include -#include +#include #include #include #include @@ -13,7 +13,7 @@ using T = double; using namespace proxsuite; using namespace proxsuite::proxqp; -DOCTEST_TEST_CASE("proxqp::dense: test init with fixed sizes matrices") +TEST_CASE("proxqp::dense: test init with fixed sizes matrices") { double sparsity_factor = 0.15; T eps_abs = T(1e-9); @@ -44,8 +44,8 @@ DOCTEST_TEST_CASE("proxqp::dense: test init with fixed sizes matrices") T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -68,8 +68,8 @@ DOCTEST_TEST_CASE("proxqp::dense: test init with fixed sizes matrices") T pri_res = (qp.A * results.x - qp.b).lpNorm(); T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -82,8 +82,8 @@ DOCTEST_TEST_CASE("proxqp::dense: test init with fixed sizes matrices") } } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test solve function") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test solve function") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -119,8 +119,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -131,8 +131,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " << results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test solve with different rho value") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test solve with different rho value") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -161,7 +161,7 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " eps_abs, 0, T(1.E-7)); - DOCTEST_CHECK(results.info.rho == T(1.E-7)); + CHECK(results.info.rho == T(1.E-7)); T pri_res = std::max((qp.A * results.x - qp.b).lpNorm(), (helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l)) @@ -169,8 +169,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -181,7 +181,7 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " << results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex qp with equality and " "inequality constraints: test solve with different mu_eq and mu_in values") { @@ -222,8 +222,8 @@ DOCTEST_TEST_CASE( T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -234,8 +234,8 @@ DOCTEST_TEST_CASE( << results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test warm starting") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test warm starting") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -263,8 +263,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -275,8 +275,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " << results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test verbose = true") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test verbose = true") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -316,8 +316,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -328,8 +328,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " << results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test no initial guess") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test no initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -373,8 +373,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " T dua_res = (qp.H * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; diff --git a/test/src/dense_qp_with_eq_and_in.cpp b/test/cpp/dense_qp_with_eq_and_in.cpp similarity index 89% rename from test/src/dense_qp_with_eq_and_in.cpp rename to test/cpp/dense_qp_with_eq_and_in.cpp index cb7e1d808..b77be02a8 100644 --- a/test/src/dense_qp_with_eq_and_in.cpp +++ b/test/cpp/dense_qp_with_eq_and_in.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 INRIA // #include -#include +#include #include #include #include @@ -11,7 +11,7 @@ using T = double; using namespace proxsuite; -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex qp with equality and inequality constraints " "and increasing dimension using wrapper API") { @@ -52,8 +52,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -64,8 +64,8 @@ DOCTEST_TEST_CASE( } } -DOCTEST_TEST_CASE("sparse random strongly convex qp with box inequality " - "constraints and increasing dimension using the API") +TEST_CASE("sparse random strongly convex qp with box inequality " + "constraints and increasing dimension using the API") { std::cout @@ -102,8 +102,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with box inequality " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -114,8 +114,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with box inequality " } } -DOCTEST_TEST_CASE("sparse random not strongly convex qp with inequality " - "constraints and increasing dimension using the API") +TEST_CASE("sparse random not strongly convex qp with inequality " + "constraints and increasing dimension using the API") { std::cout @@ -152,8 +152,8 @@ DOCTEST_TEST_CASE("sparse random not strongly convex qp with inequality " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -164,8 +164,8 @@ DOCTEST_TEST_CASE("sparse random not strongly convex qp with inequality " } } -DOCTEST_TEST_CASE("sparse random strongly convex qp with degenerate inequality " - "constraints and increasing dimension using the API") +TEST_CASE("sparse random strongly convex qp with degenerate inequality " + "constraints and increasing dimension using the API") { std::cout @@ -197,8 +197,7 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with degenerate inequality " qp_random.l, qp_random.u); qp.solve(); - DOCTEST_CHECK(qp.results.info.status == - proxqp::QPSolverOutput::PROXQP_SOLVED); + CHECK(qp.results.info.status == proxqp::QPSolverOutput::PROXQP_SOLVED); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -208,8 +207,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with degenerate inequality " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -220,8 +219,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with degenerate inequality " } } -DOCTEST_TEST_CASE("linear problem with equality inequality constraints and " - "increasing dimension using the API") +TEST_CASE("linear problem with equality inequality constraints and " + "increasing dimension using the API") { srand(1); std::cout << "---testing linear problem with inequality constraints and " @@ -263,8 +262,8 @@ DOCTEST_TEST_CASE("linear problem with equality inequality constraints and " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; diff --git a/test/src/dense_qp_wrapper.cpp b/test/cpp/dense_qp_wrapper.cpp similarity index 89% rename from test/src/dense_qp_wrapper.cpp rename to test/cpp/dense_qp_wrapper.cpp index 353fb7dce..f2a7372f7 100644 --- a/test/src/dense_qp_wrapper.cpp +++ b/test/cpp/dense_qp_wrapper.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022-2024 INRIA // #include -#include +#include #include #include #include @@ -13,7 +13,7 @@ using T = double; using namespace proxsuite; using namespace proxsuite::proxqp; -DOCTEST_TEST_CASE( +TEST_CASE( "ProxQP::dense: sparse random strongly convex qp with inequality constraints" "and empty equality constraints") { @@ -67,8 +67,8 @@ DOCTEST_TEST_CASE( T dua_res = (qp_random.H * qp.results.x + qp_random.g + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -116,8 +116,8 @@ DOCTEST_TEST_CASE( dua_res = (qp_random.H * qp.results.x + qp_random.g + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -148,8 +148,8 @@ DOCTEST_TEST_CASE( dua_res = (qp_random.H * qp.results.x + qp_random.g + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -160,9 +160,8 @@ DOCTEST_TEST_CASE( std::cout << "setup timing " << qp.results.info.setup_time << " solve time " << qp.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update H") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update H") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test update H---" @@ -199,8 +198,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -243,8 +242,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -277,8 +276,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -291,9 +290,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update A") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update A") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -331,8 +329,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -377,8 +375,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -410,8 +408,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -424,9 +422,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update C") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update C") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -464,8 +461,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -510,8 +507,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -543,8 +540,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -557,9 +554,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update b") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update b") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -597,8 +593,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -643,8 +639,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -676,8 +672,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -690,9 +686,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update u") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update u") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -728,8 +723,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -779,8 +774,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -812,8 +807,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -826,9 +821,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update g") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update g") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -864,8 +858,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -911,8 +905,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -944,8 +938,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -958,9 +952,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "sparse random strongly convex qp with equality and inequality " - "constraints: test update H and A and b and u and l") +TEST_CASE("sparse random strongly convex qp with equality and inequality " + "constraints: test update H and A and b and u and l") { std::cout @@ -997,8 +990,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1059,8 +1052,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1092,8 +1085,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -1106,9 +1099,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update rho") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update rho") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1144,8 +1136,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1184,8 +1176,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1222,8 +1214,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -1236,9 +1228,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test update mu_eq and mu_in") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test update mu_eq and mu_in") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1274,8 +1265,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1317,8 +1308,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1355,8 +1346,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -1369,9 +1360,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test warm starting") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test warm starting") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1408,8 +1398,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1439,8 +1429,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim after updating: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -1474,8 +1464,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------ conter factual check with another QP object starting at " "the updated model : " @@ -1488,9 +1478,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test dense init") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test dense init") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1532,13 +1521,12 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test with no initial guess") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test with no initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1577,8 +1565,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1610,8 +1598,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp2: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1622,7 +1610,7 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex qp with equality and " "inequality constraints: test with equality constrained initial guess") { @@ -1665,8 +1653,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1699,8 +1687,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp2: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1711,9 +1699,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "sparse random strongly convex qp with equality and " - "inequality constraints: test with warm start with previous result") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test with warm start with previous result") { std::cout @@ -1754,8 +1741,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1822,8 +1809,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp2: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1834,9 +1821,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test with cold start option") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test with cold start option") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1876,8 +1862,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1944,8 +1930,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with cold start option: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1956,7 +1942,7 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex qp with equality and " "inequality constraints: test equilibration options at initialization") { @@ -2000,8 +1986,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp with " "preconditioner derived: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -2037,8 +2023,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp without preconditioner derivation: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -2051,9 +2037,8 @@ DOCTEST_TEST_CASE( << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "sparse random strongly convex qp with equality and " - "inequality constraints: test equilibration options at update") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test equilibration options at update") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -2093,8 +2078,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp with " "preconditioner derived: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -2124,8 +2109,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with preconditioner re derived " "after an update (should get exact same results): " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -2179,8 +2164,8 @@ DOCTEST_TEST_CASE( nullopt, false); // use previous preconditioner: should get same result as well qp2.solve(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp without preconditioner derivation: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -2194,9 +2179,9 @@ DOCTEST_TEST_CASE( } ///// TESTS ALL INITIAL GUESS OPTIONS FOR MULTIPLE SOLVES AT ONCE -TEST_CASE( - "sparse random strongly convex qp with equality and " - "inequality constraints: test multiple solve at once with no initial guess") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test multiple solves at once with no " + "initial guess in dense wrapper") { double sparsity_factor = 0.15; @@ -2445,7 +2430,7 @@ TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " "inequality constraints: test multiple solve at once with equality " - "constrained initial guess") + "constrained initial guess and warm start") { double sparsity_factor = 0.15; @@ -2572,9 +2557,9 @@ TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " << qp.results.info.solve_time << std::endl; } -TEST_CASE( - "sparse random strongly convex qp with equality and " - "inequality constraints: test multiple solve at once with no initial guess") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test multiple solve at once with no initial " + "guess and warm start") { double sparsity_factor = 0.15; @@ -3484,7 +3469,6 @@ TEST_CASE( dim, n_eq, n_in, sparsity_factor, strong_convexity_factor); dense::QP qp(dim, n_eq, n_in); - qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.settings.initial_guess = InitialGuessStatus::NO_INITIAL_GUESS; @@ -5049,10 +5033,9 @@ TEST_CASE("ProxQP::dense: Test g update for different warm start with previous " << qp2.results.info.solve_time << std::endl; } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using warm start with previous results") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using warm start with previous results") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5074,8 +5057,8 @@ DOCTEST_TEST_CASE( bool compute_preconditioner = true; dense::QP qp{ dim, n_eq, n_in }; // creating QP object - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -5087,11 +5070,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5102,8 +5085,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -5117,11 +5100,11 @@ DOCTEST_TEST_CASE( qp.settings.initial_guess = proxsuite::proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5132,12 +5115,12 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5150,13 +5133,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -5167,13 +5150,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5186,17 +5169,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5207,8 +5190,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -5221,11 +5204,11 @@ DOCTEST_TEST_CASE( 1.e-3); qp3.settings.initial_guess = proxsuite::proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5236,14 +5219,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using cold start with previous results") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using cold start with previous results") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5267,8 +5249,8 @@ DOCTEST_TEST_CASE( dense::QP qp{ dim, n_eq, n_in }; // creating QP object qp.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -5280,11 +5262,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5295,8 +5277,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -5307,11 +5289,11 @@ DOCTEST_TEST_CASE( nullopt, compute_preconditioner, 1.e-6); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5322,14 +5304,14 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object qp2.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5342,13 +5324,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -5359,15 +5341,15 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object qp3.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5380,17 +5362,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5401,8 +5383,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -5413,11 +5395,11 @@ DOCTEST_TEST_CASE( compute_preconditioner, 1.e-6, 1.e-3); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5428,14 +5410,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using equality constrained initial guess") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using equality constrained initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5459,8 +5440,8 @@ DOCTEST_TEST_CASE( dense::QP qp{ dim, n_eq, n_in }; // creating QP object qp.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -5472,11 +5453,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5487,8 +5468,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -5499,11 +5480,11 @@ DOCTEST_TEST_CASE( nullopt, compute_preconditioner, 1.e-6); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5514,14 +5495,14 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object qp2.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5534,13 +5515,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -5551,15 +5532,15 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object qp3.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5572,17 +5553,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5593,8 +5574,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -5605,11 +5586,11 @@ DOCTEST_TEST_CASE( compute_preconditioner, 1.e-6, 1.e-3); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5620,14 +5601,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using no initial guess") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using no initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5650,8 +5630,8 @@ DOCTEST_TEST_CASE( dense::QP qp{ dim, n_eq, n_in }; // creating QP object qp.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -5663,11 +5643,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5678,8 +5658,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -5690,11 +5670,11 @@ DOCTEST_TEST_CASE( nullopt, compute_preconditioner, 1.e-6); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5705,13 +5685,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object qp2.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5724,13 +5704,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -5741,14 +5721,14 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object qp3.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5761,17 +5741,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5782,8 +5762,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -5794,11 +5774,11 @@ DOCTEST_TEST_CASE( compute_preconditioner, 1.e-6, 1.e-3); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5809,14 +5789,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after several solves using warm start with previous results") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after several solves using warm start with previous results") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5838,8 +5817,8 @@ DOCTEST_TEST_CASE( bool compute_preconditioner = true; dense::QP qp{ dim, n_eq, n_in }; // creating QP object - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -5851,11 +5830,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5866,15 +5845,15 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.settings.initial_guess = proxsuite::proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5884,8 +5863,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -5899,8 +5878,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5910,14 +5889,14 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5930,13 +5909,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.settings.initial_guess = proxsuite::proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; @@ -5944,13 +5923,13 @@ DOCTEST_TEST_CASE( // warm start with previous result used, hence if the qp is small and // simple, the parameters should not changed during first solve, and also // after as we start at the solution - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp2.results.x - qp_random.u) + @@ -5960,14 +5939,14 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.settings.verbose = true; @@ -5986,17 +5965,17 @@ DOCTEST_TEST_CASE( // warm start with previous result used, hence if the qp is small and // simple, the parameters should not changed during first solve, and also // after as we start at the solution - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6006,8 +5985,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -6024,17 +6003,17 @@ DOCTEST_TEST_CASE( // warm start with previous result used, hence if the qp is small and // simple, the parameters should not changed during first solve, and also // after as we start at the solution - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6044,15 +6023,14 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after several solves using cold start with previous results") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after several solves using cold start with previous results") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -6076,8 +6054,8 @@ DOCTEST_TEST_CASE( dense::QP qp{ dim, n_eq, n_in }; // creating QP object qp.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -6089,11 +6067,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -6104,13 +6082,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -6120,8 +6098,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -6135,8 +6113,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -6146,16 +6124,16 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object qp2.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -6168,22 +6146,22 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp2.results.x - qp_random.u) + @@ -6193,16 +6171,16 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object qp3.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -6217,17 +6195,17 @@ DOCTEST_TEST_CASE( mu_eq); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6237,8 +6215,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -6252,17 +6230,17 @@ DOCTEST_TEST_CASE( 1.e-6, 1.e-3); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6272,12 +6250,12 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after several solves " "using equality constrained initial guess") @@ -6304,8 +6282,8 @@ DOCTEST_TEST_CASE( dense::QP qp{ dim, n_eq, n_in }; // creating QP object qp.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -6317,11 +6295,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -6332,13 +6310,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -6348,8 +6326,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -6363,8 +6341,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -6374,16 +6352,16 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object qp2.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -6396,22 +6374,22 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp2.results.x - qp_random.u) + @@ -6421,16 +6399,16 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object qp3.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -6445,17 +6423,17 @@ DOCTEST_TEST_CASE( mu_eq); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6465,8 +6443,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -6480,17 +6458,17 @@ DOCTEST_TEST_CASE( 1.e-6, 1.e-3); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6500,15 +6478,14 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } -DOCTEST_TEST_CASE( - "ProxQP::dense: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after several solves using no initial guess") +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after several solves using no initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -6531,8 +6508,8 @@ DOCTEST_TEST_CASE( dense::QP qp{ dim, n_eq, n_in }; // creating QP object qp.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -6544,11 +6521,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -6559,13 +6536,13 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -6575,8 +6552,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -6590,8 +6567,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -6601,15 +6578,15 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp2{ dim, n_eq, n_in }; // creating QP object qp2.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -6622,22 +6599,22 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp2.results.x - qp_random.u) + @@ -6647,15 +6624,15 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model dense::QP qp3{ dim, n_eq, n_in }; // creating QP object qp3.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -6670,17 +6647,17 @@ DOCTEST_TEST_CASE( mu_eq); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6690,8 +6667,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -6705,17 +6682,17 @@ DOCTEST_TEST_CASE( 1.e-6, 1.e-3); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp3.results.x - qp_random.u) + @@ -6725,8 +6702,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } @@ -7153,7 +7130,7 @@ TEST_CASE("ProxQP::dense: check updates work when there are box constraints") TEST_CASE("ProxQP::dense: test primal infeasibility solving") { double sparsity_factor = 0.15; - T eps_abs = T(1e-5); + T eps_abs = T(1e-3); utils::rand::set_seed(1); dense::isize dim = 20; @@ -7204,8 +7181,8 @@ TEST_CASE("ProxQP::dense: test primal infeasibility solving") qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= scaled_eps); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= scaled_eps); + CHECK(dua_res <= eps_abs); } } @@ -7249,8 +7226,7 @@ TEST_CASE("ProxQP::dense: estimate of minimal eigenvalues using Eigen") nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate + 1) <= - tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate + 1) <= tol); } dim = 50; n_eq = dim; @@ -7285,8 +7261,8 @@ TEST_CASE("ProxQP::dense: estimate of minimal eigenvalues using Eigen") nullopt, nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } dim = 50; n_eq = dim; @@ -7323,8 +7299,8 @@ TEST_CASE("ProxQP::dense: estimate of minimal eigenvalues using Eigen") nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } } @@ -7365,8 +7341,7 @@ TEST_CASE( nullopt, -1); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate + 1) <= - tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate + 1) <= tol); } dim = 50; n_eq = dim; @@ -7397,8 +7372,8 @@ TEST_CASE( nullopt, nullopt, minimal_eigenvalue); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } dim = 50; n_eq = dim; @@ -7431,8 +7406,8 @@ TEST_CASE( nullopt, minimal_eigenvalue); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } } @@ -7480,8 +7455,7 @@ TEST_CASE( nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK( - std::abs(qp.results.info.minimal_H_eigenvalue_estimate + 0.5) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate + 0.5) <= tol); } dim = 50; n_eq = dim; @@ -7519,8 +7493,8 @@ TEST_CASE( nullopt, nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } dim = 50; n_eq = dim; @@ -7561,13 +7535,13 @@ TEST_CASE( nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } } -DOCTEST_TEST_CASE("check that model.is_valid function for symmetric matrices " - "works for epsilon precision") +TEST_CASE("check that model.is_valid function for symmetric matrices " + "works for epsilon precision") { Eigen::Matrix matrix = Eigen::Matrix::Random(); Eigen::Matrix symmetric_mat = matrix + matrix.transpose(); @@ -7581,8 +7555,8 @@ DOCTEST_TEST_CASE("check that model.is_valid function for symmetric matrices " bool is_symmetric_with_tolerance = symmetric_mat.isApprox( symmetric_mat.transpose(), std::numeric_limits::epsilon()); - DOCTEST_CHECK(is_symmetric_without_tolerance == false); - DOCTEST_CHECK(is_symmetric_with_tolerance == true); + CHECK(is_symmetric_without_tolerance == false); + CHECK(is_symmetric_with_tolerance == true); // initialize a model with a symmetric matrix as Hessian, this runs // model.is_valid() that performs the check above @@ -7652,15 +7626,15 @@ TEST_CASE("ProxQP::dense: sparse random strongly convex qp with" qp_random.u); qp.solve(); - DOCTEST_CHECK(qp.results.info.mu_updates > 0); + CHECK(qp.results.info.mu_updates > 0); T pri_res = (helpers::negative_part(qp_random.C * qp.results.x - qp_random.l)) .lpNorm(); T dua_res = (qp_random.H * qp.results.x + qp_random.g + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; diff --git a/test/src/dense_ruiz_equilibration.cpp b/test/cpp/dense_ruiz_equilibration.cpp similarity index 84% rename from test/src/dense_ruiz_equilibration.cpp rename to test/cpp/dense_ruiz_equilibration.cpp index d1bff6479..4861e24ed 100644 --- a/test/src/dense_ruiz_equilibration.cpp +++ b/test/cpp/dense_ruiz_equilibration.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022-2023 INRIA // #include -#include +#include #include #include #include @@ -12,7 +12,7 @@ using namespace proxsuite; using Scalar = double; -DOCTEST_TEST_CASE("ruiz preconditioner") +TEST_CASE("ruiz preconditioner") { int dim = 5; int n_eq = 6; @@ -65,8 +65,8 @@ DOCTEST_TEST_CASE("ruiz preconditioner") auto A_new = (tail * A * head).eval(); auto b_new = (tail * b).eval(); - DOCTEST_CHECK((H_new - qp.work.H_scaled).norm() <= Scalar(1e-10)); - DOCTEST_CHECK((g_new - qp.work.g_scaled).norm() <= Scalar(1e-10)); - DOCTEST_CHECK((A_new - qp.work.A_scaled).norm() <= Scalar(1e-10)); - DOCTEST_CHECK((b_new - qp.work.b_scaled).norm() <= Scalar(1e-10)); + CHECK((H_new - qp.work.H_scaled).norm() <= Scalar(1e-10)); + CHECK((g_new - qp.work.g_scaled).norm() <= Scalar(1e-10)); + CHECK((A_new - qp.work.A_scaled).norm() <= Scalar(1e-10)); + CHECK((b_new - qp.work.b_scaled).norm() <= Scalar(1e-10)); } diff --git a/test/src/dense_unconstrained_qp.cpp b/test/cpp/dense_unconstrained_qp.cpp similarity index 92% rename from test/src/dense_unconstrained_qp.cpp rename to test/cpp/dense_unconstrained_qp.cpp index eed71aecc..1ac37ef88 100644 --- a/test/src/dense_unconstrained_qp.cpp +++ b/test/cpp/dense_unconstrained_qp.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 INRIA // #include -#include +#include #include #include #include @@ -12,7 +12,7 @@ using namespace proxsuite; using T = double; -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex unconstrained qp and increasing dimension") { @@ -48,8 +48,8 @@ DOCTEST_TEST_CASE( qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -60,8 +60,8 @@ DOCTEST_TEST_CASE( } } -DOCTEST_TEST_CASE("sparse random not strongly convex unconstrained qp and " - "increasing dimension") +TEST_CASE("sparse random not strongly convex unconstrained qp and " + "increasing dimension") { std::cout << "---testing sparse random not strongly convex unconstrained qp " @@ -101,8 +101,8 @@ DOCTEST_TEST_CASE("sparse random not strongly convex unconstrained qp and " qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -113,7 +113,7 @@ DOCTEST_TEST_CASE("sparse random not strongly convex unconstrained qp and " } } -DOCTEST_TEST_CASE("unconstrained qp with H = Id and g random") +TEST_CASE("unconstrained qp with H = Id and g random") { std::cout << "---unconstrained qp with H = Id and g random---" << std::endl; @@ -149,8 +149,8 @@ DOCTEST_TEST_CASE("unconstrained qp with H = Id and g random") qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -160,7 +160,7 @@ DOCTEST_TEST_CASE("unconstrained qp with H = Id and g random") << std::endl; } -DOCTEST_TEST_CASE("unconstrained qp with H = Id and g = 0") +TEST_CASE("unconstrained qp with H = Id and g = 0") { std::cout << "---unconstrained qp with H = Id and g = 0---" << std::endl; @@ -197,8 +197,8 @@ DOCTEST_TEST_CASE("unconstrained qp with H = Id and g = 0") qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------solving qp with dim: " << dim << " neq: " << n_eq << " nin: " << n_in << std::endl; diff --git a/test/include/maros_meszaros.hpp b/test/cpp/maros_meszaros.hpp similarity index 100% rename from test/include/maros_meszaros.hpp rename to test/cpp/maros_meszaros.hpp diff --git a/test/src/parallel_qp_solve.cpp b/test/cpp/parallel_qp_solve.cpp similarity index 96% rename from test/src/parallel_qp_solve.cpp rename to test/cpp/parallel_qp_solve.cpp index b60d25f53..ab271d948 100644 --- a/test/src/parallel_qp_solve.cpp +++ b/test/cpp/parallel_qp_solve.cpp @@ -1,7 +1,7 @@ // // Copyright (c) 2023 INRIA // -#include +#include #include #include #include @@ -16,7 +16,7 @@ using T = double; using I = c_int; using namespace proxsuite::linalg::sparse::tags; -DOCTEST_TEST_CASE("test parallel qp_solve for dense qps") +TEST_CASE("test parallel qp_solve for dense qps") { double sparsity_factor = 0.15; T eps_abs = T(1e-9); @@ -76,7 +76,7 @@ DOCTEST_TEST_CASE("test parallel qp_solve for dense qps") } } -DOCTEST_TEST_CASE("test dense BatchQP and optional NUM_THREADS") +TEST_CASE("test dense BatchQP and optional NUM_THREADS") { double sparsity_factor = 0.15; T eps_abs = T(1e-9); @@ -132,7 +132,7 @@ DOCTEST_TEST_CASE("test dense BatchQP and optional NUM_THREADS") } } -DOCTEST_TEST_CASE("test parallel qp_solve for sparse qps") +TEST_CASE("test parallel qp_solve for sparse qps") { sparse::isize dim = 500; sparse::isize n_eq(10); @@ -193,7 +193,7 @@ DOCTEST_TEST_CASE("test parallel qp_solve for sparse qps") } } -DOCTEST_TEST_CASE("test sparse BatchQP") +TEST_CASE("test sparse BatchQP") { sparse::isize dim = 500; sparse::isize n_eq(10); diff --git a/test/src/serialization.cpp b/test/cpp/serialization.cpp similarity index 89% rename from test/src/serialization.cpp rename to test/cpp/serialization.cpp index d9fe67693..506b2af3b 100644 --- a/test/src/serialization.cpp +++ b/test/cpp/serialization.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 INRIA // #include -#include +#include #include #include #include @@ -78,7 +78,7 @@ generic_test(const T& object, const std::string& filename) loadFromXML(object_loaded, xml_filename); // Check - DOCTEST_CHECK(object_loaded == object); + CHECK(object_loaded == object); } // Load and save as json @@ -90,7 +90,7 @@ generic_test(const T& object, const std::string& filename) loadFromJSON(object_loaded, json_filename); // Check - DOCTEST_CHECK(object_loaded == object); + CHECK(object_loaded == object); } // Load and save as binary @@ -102,7 +102,7 @@ generic_test(const T& object, const std::string& filename) loadFromBinary(object_loaded, bin_filename); // Check - DOCTEST_CHECK(object_loaded == object); + CHECK(object_loaded == object); } } @@ -110,7 +110,7 @@ using T = double; using namespace proxsuite; using namespace proxsuite::proxqp; -DOCTEST_TEST_CASE("test serialization of qp model, results and settings") +TEST_CASE("test serialization of qp model, results and settings") { std::cout << "--- serialization ---" << std::endl; double sparsity_factor = 0.15; @@ -140,8 +140,7 @@ DOCTEST_TEST_CASE("test serialization of qp model, results and settings") generic_test(qp, TEST_SERIALIZATION_FOLDER "/qp_wrapper"); } -DOCTEST_TEST_CASE( - "test serialization of eigen matrices with different storage orders") +TEST_CASE("test serialization of eigen matrices with different storage orders") { Eigen::Matrix row_matrix; Eigen::Matrix row_matrix_loaded; @@ -153,6 +152,6 @@ DOCTEST_TEST_CASE( proxsuite::serialization::loadFromJSON(row_matrix_loaded, "row_matrix"); proxsuite::serialization::loadFromJSON(col_matrix_loaded, "row_matrix"); - DOCTEST_CHECK(row_matrix_loaded == row_matrix); - DOCTEST_CHECK(col_matrix_loaded == row_matrix); + CHECK(row_matrix_loaded == row_matrix); + CHECK(col_matrix_loaded == row_matrix); } \ No newline at end of file diff --git a/test/src/sparse_factorization.cpp b/test/cpp/sparse_factorization.cpp similarity index 99% rename from test/src/sparse_factorization.cpp rename to test/cpp/sparse_factorization.cpp index d60e00fba..7f7b82e81 100644 --- a/test/src/sparse_factorization.cpp +++ b/test/cpp/sparse_factorization.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include template diff --git a/test/src/sparse_maros_meszaros.cpp b/test/cpp/sparse_maros_meszaros.cpp similarity index 98% rename from test/src/sparse_maros_meszaros.cpp rename to test/cpp/sparse_maros_meszaros.cpp index 01f701e79..8f2baa342 100644 --- a/test/src/sparse_maros_meszaros.cpp +++ b/test/cpp/sparse_maros_meszaros.cpp @@ -3,14 +3,12 @@ // #include -#include -#include +#include +#include "maros_meszaros.hpp" #include using namespace proxsuite; -#define MAROS_MESZAROS_DIR PROBLEM_PATH "/data/maros_meszaros_data/" - template void compute_primal_dual_feasibility(const PreprocessedQpSparse& preprocessed, diff --git a/test/src/sparse_qp.cpp b/test/cpp/sparse_qp.cpp similarity index 99% rename from test/src/sparse_qp.cpp rename to test/cpp/sparse_qp.cpp index 6aec4a872..8598f6305 100644 --- a/test/src/sparse_qp.cpp +++ b/test/cpp/sparse_qp.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include using namespace proxsuite; diff --git a/test/src/sparse_qp_solve.cpp b/test/cpp/sparse_qp_solve.cpp similarity index 93% rename from test/src/sparse_qp_solve.cpp rename to test/cpp/sparse_qp_solve.cpp index 112fca202..fb3238ec5 100644 --- a/test/src/sparse_qp_solve.cpp +++ b/test/cpp/sparse_qp_solve.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 INRIA // #include -#include +#include #include #include #include @@ -14,8 +14,8 @@ using T = double; using I = c_int; using namespace proxsuite::linalg::sparse::tags; -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test solve function") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test solve function") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -82,8 +82,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " proxqp::dense::infty_norm( helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -96,8 +96,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " } } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test solve with different rho value") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test solve with different rho value") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -131,7 +131,7 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " eps_abs, nullopt, T(1.E-7)); - DOCTEST_CHECK(results.info.rho == T(1.E-7)); + CHECK(results.info.rho == T(1.E-7)); T dua_res = proxqp::dense::infty_norm( qp.H.selfadjointView() * results.x + qp.g + qp.A.transpose() * results.y + qp.C.transpose() * results.z); @@ -139,8 +139,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " proxqp::dense::infty_norm( helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -153,7 +153,7 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " } } -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex qp with equality and " "inequality constraints: test solve with different mu_eq and mu_in values") { @@ -199,8 +199,8 @@ DOCTEST_TEST_CASE( proxqp::dense::infty_norm( helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -213,9 +213,8 @@ DOCTEST_TEST_CASE( } } -DOCTEST_TEST_CASE( - "sparse random strongly convex qp with equality and " - "inequality constraints: test setting specific sparse backend") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test setting specific sparse backend") { std::cout @@ -269,9 +268,9 @@ DOCTEST_TEST_CASE( proxqp::dense::infty_norm( helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); - DOCTEST_CHECK(results.info.sparse_backend == SparseBackend::MatrixFree); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); + CHECK(results.info.sparse_backend == SparseBackend::MatrixFree); std::cout << "------using API solving qp with dim: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -284,8 +283,8 @@ DOCTEST_TEST_CASE( } } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test warm starting") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test warm starting") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -318,8 +317,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " proxqp::dense::infty_norm( helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -332,8 +331,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " } } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test verbose = true") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test verbose = true") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -378,8 +377,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " proxqp::dense::infty_norm( helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; @@ -392,8 +391,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " } } -DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " - "inequality constraints: test no initial guess") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test no initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -443,8 +442,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with equality and " proxqp::dense::infty_norm( helpers::positive_part(qp.C * results.x - qp.u) + helpers::negative_part(qp.C * results.x - qp.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; diff --git a/test/src/sparse_qp_wrapper.cpp b/test/cpp/sparse_qp_wrapper.cpp similarity index 90% rename from test/src/sparse_qp_wrapper.cpp rename to test/cpp/sparse_qp_wrapper.cpp index f8d07398a..154323893 100644 --- a/test/src/sparse_qp_wrapper.cpp +++ b/test/cpp/sparse_qp_wrapper.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include using namespace proxsuite; @@ -14,7 +14,7 @@ using T = double; using I = c_int; using namespace proxsuite::linalg::sparse::tags; -DOCTEST_TEST_CASE( +TEST_CASE( "ProxQP::sparse: sparse random strongly convex qp with inequality constraints" "and empty equality constraints") { @@ -727,9 +727,8 @@ TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " } } -DOCTEST_TEST_CASE( - "sparse random strongly convex qp with equality and " - "inequality constraints: test with warm start with previous result") +TEST_CASE("sparse random strongly convex qp with equality and " + "inequality constraints: test with warm start with previous result") { std::cout @@ -774,8 +773,8 @@ DOCTEST_TEST_CASE( proxqp::dense::infty_norm( helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + helpers::negative_part(qp_random.C * qp.results.x - qp_random.l))); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -832,8 +831,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp2: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -845,9 +844,8 @@ DOCTEST_TEST_CASE( } } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test with cold start option") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test with cold start option") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -891,8 +889,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -956,8 +954,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with cold start option: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -969,9 +967,8 @@ DOCTEST_TEST_CASE( } } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test equilibration option") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test equilibration option") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1016,8 +1013,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1047,8 +1044,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp2: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1060,9 +1057,8 @@ DOCTEST_TEST_CASE( } } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test equilibration option at update") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test equilibration option at update") { std::cout << "---testing sparse random strongly convex qp with equality and " @@ -1106,8 +1102,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1127,8 +1123,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1159,8 +1155,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp2: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1182,8 +1178,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); std::cout << "------using API solving qp with dim with qp2: " << n << " neq: " << n_eq << " nin: " << n_in << std::endl; std::cout << "primal residual: " << pri_res << std::endl; @@ -1256,7 +1252,7 @@ TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " } TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test new init") + "inequality constraints: test new init 2") { for (auto const& dims : { // proxsuite::linalg::veg::tuplify(50, 0, 0), @@ -1604,7 +1600,7 @@ TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " "inequality constraints: test multiple solve at once with equality " - "constrained initial guess") + "constrained initial guess 2") { for (auto const& dims : { // proxsuite::linalg::veg::tuplify(50, 0, 0), @@ -1738,7 +1734,7 @@ TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " } TEST_CASE( "sparse random strongly convex qp with equality and " - "inequality constraints: test multiple solve at once with no initial guess") + "inequality constraints: test multiple solve at once with no initial guess 2") { for (auto const& dims : { // proxsuite::linalg::veg::tuplify(50, 0, 0), @@ -2677,7 +2673,7 @@ TEST_CASE( } TEST_CASE( "sparse random strongly convex qp with equality and " - "inequality constraints: test multiple solve at once with no initial guess") + "inequality constraints: test multiple solve at once with no initial guess 3") { for (auto const& dims : { // proxsuite::linalg::veg::tuplify(50, 0, 0), @@ -4239,10 +4235,9 @@ TEST_CASE("ProxQP::sparse: Test rho update for different initial guess") } } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using no initial guess") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using no initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -4269,8 +4264,8 @@ DOCTEST_TEST_CASE( bool compute_preconditioner = true; qp.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -4282,11 +4277,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4297,8 +4292,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -4309,11 +4304,11 @@ DOCTEST_TEST_CASE( nullopt, compute_preconditioner, 1.e-6); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4324,15 +4319,15 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp2(qp_random.H.cast(), qp_random.A.cast(), qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; @@ -4346,13 +4341,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -4363,16 +4358,16 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp3(qp_random.H.cast(), qp_random.A.cast(), qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -4385,17 +4380,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -4406,8 +4401,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -4418,11 +4413,11 @@ DOCTEST_TEST_CASE( compute_preconditioner, 1.e-6, 1.e-3); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -4433,13 +4428,12 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using EQUALITY_CONSTRAINED_INITIAL_GUESS") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using EQUALITY_CONSTRAINED_INITIAL_GUESS") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -4467,8 +4461,8 @@ DOCTEST_TEST_CASE( qp.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -4480,11 +4474,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4495,8 +4489,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -4507,11 +4501,11 @@ DOCTEST_TEST_CASE( nullopt, compute_preconditioner, 1.e-6); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4522,16 +4516,16 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp2(qp_random.H.cast(), qp_random.A.cast(), qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -4545,9 +4539,9 @@ DOCTEST_TEST_CASE( nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -4558,8 +4552,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp3(qp_random.H.cast(), @@ -4567,8 +4561,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -4581,17 +4575,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -4602,8 +4596,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -4614,11 +4608,11 @@ DOCTEST_TEST_CASE( compute_preconditioner, 1.e-6, 1.e-3); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -4629,13 +4623,12 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using COLD_START_WITH_PREVIOUS_RESULT") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using COLD_START_WITH_PREVIOUS_RESULT") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -4663,8 +4656,8 @@ DOCTEST_TEST_CASE( qp.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -4676,11 +4669,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4691,8 +4684,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -4703,11 +4696,11 @@ DOCTEST_TEST_CASE( nullopt, compute_preconditioner, 1.e-6); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4718,16 +4711,16 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp2(qp_random.H.cast(), qp_random.A.cast(), qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; @@ -4741,13 +4734,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -4758,8 +4751,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp3(qp_random.H.cast(), @@ -4767,8 +4760,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -4781,17 +4774,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -4802,8 +4795,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -4814,11 +4807,11 @@ DOCTEST_TEST_CASE( compute_preconditioner, 1.e-6, 1.e-3); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -4829,14 +4822,13 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after updates using WARM_START_WITH_PREVIOUS_RESULT") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after updates using WARM_START_WITH_PREVIOUS_RESULT") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -4864,8 +4856,8 @@ DOCTEST_TEST_CASE( qp.settings.initial_guess = proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; qp.init(qp_random.H, @@ -4877,11 +4869,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4892,8 +4884,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp.update(nullopt, nullopt, @@ -4904,11 +4896,11 @@ DOCTEST_TEST_CASE( nullopt, compute_preconditioner, 1.e-6); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -4919,16 +4911,16 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp2(qp_random.H.cast(), qp_random.A.cast(), qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; @@ -4942,13 +4934,13 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), @@ -4959,8 +4951,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); // conter factual check with another QP object starting at the updated model proxqp::sparse::QP qp3(qp_random.H.cast(), @@ -4968,8 +4960,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -4982,17 +4974,17 @@ DOCTEST_TEST_CASE( compute_preconditioner, rho, mu_eq); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5003,8 +4995,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp3.update(nullopt, nullopt, nullopt, @@ -5015,11 +5007,11 @@ DOCTEST_TEST_CASE( compute_preconditioner, 1.e-6, 1.e-3); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), @@ -5030,14 +5022,13 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after several solves using no initial guess") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after several solves using no initial guess") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5071,8 +5062,8 @@ DOCTEST_TEST_CASE( bool compute_preconditioner = true; qp.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; // qp.settings.verbose = true; @@ -5085,11 +5076,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5100,13 +5091,13 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5116,8 +5107,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -5131,8 +5122,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5142,8 +5133,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5151,8 +5142,8 @@ DOCTEST_TEST_CASE( qp_random.A.cast(), qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5165,16 +5156,16 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5184,8 +5175,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5193,8 +5184,8 @@ DOCTEST_TEST_CASE( qp_random.A.cast(), qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::NO_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::NO_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::NO_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5209,13 +5200,13 @@ DOCTEST_TEST_CASE( mu_eq); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5225,8 +5216,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -5240,13 +5231,13 @@ DOCTEST_TEST_CASE( 1.e-6, 1.e-3); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5256,12 +5247,12 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } -DOCTEST_TEST_CASE( +TEST_CASE( "sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after several solves " "using equality constrained initial guess") @@ -5299,8 +5290,8 @@ DOCTEST_TEST_CASE( qp.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; // qp.settings.verbose = true; @@ -5313,11 +5304,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5328,13 +5319,13 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5344,8 +5335,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -5359,8 +5350,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5370,8 +5361,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5380,8 +5371,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5394,16 +5385,16 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5413,8 +5404,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5423,8 +5414,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5439,12 +5430,12 @@ DOCTEST_TEST_CASE( mu_eq); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5454,8 +5445,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -5469,13 +5460,13 @@ DOCTEST_TEST_CASE( 1.e-6, 1.e-3); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5485,15 +5476,14 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after several solves using cold start with previous result") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after several solves using cold start with previous result") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5528,8 +5518,8 @@ DOCTEST_TEST_CASE( qp.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; // qp.settings.verbose = true; @@ -5542,11 +5532,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5557,13 +5547,13 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5573,8 +5563,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -5588,8 +5578,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5599,8 +5589,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5609,8 +5599,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5623,22 +5613,22 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5648,8 +5638,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5658,8 +5648,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5674,17 +5664,17 @@ DOCTEST_TEST_CASE( mu_eq); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5694,8 +5684,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -5709,17 +5699,17 @@ DOCTEST_TEST_CASE( 1.e-6, 1.e-3); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5729,15 +5719,14 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } -DOCTEST_TEST_CASE( - "ProxQP::sparse: sparse random strongly convex qp with equality and " - "inequality constraints: test changing default settings " - "after several solves using warm start with previous result") +TEST_CASE("ProxQP::sparse: sparse random strongly convex qp with equality and " + "inequality constraints: test changing default settings " + "after several solves using warm start with previous result") { std::cout << "---testing sparse random strongly convex qp with equality and " "inequality constraints: test changing default settings after " @@ -5772,8 +5761,8 @@ DOCTEST_TEST_CASE( qp.settings.initial_guess = proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp.settings.initial_guess == - proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); + CHECK(qp.settings.initial_guess == + proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); qp.settings.eps_abs = eps_abs; qp.settings.eps_rel = 0; // qp.settings.verbose = true; @@ -5786,11 +5775,11 @@ DOCTEST_TEST_CASE( qp_random.u, compute_preconditioner, rho); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); + CHECK(std::abs(rho - qp.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp.results.info.rho) <= 1.E-9); T pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), @@ -5801,13 +5790,13 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(rho - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(rho - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5817,8 +5806,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp.update(nullopt, @@ -5832,8 +5821,8 @@ DOCTEST_TEST_CASE( 1.e-6); for (isize iter = 0; iter < 10; ++iter) { qp.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.settings.default_rho) < 1.e-9); + CHECK(std::abs(1.e-6 - qp.results.info.rho) < 1.e-9); pri_res = std::max( (qp_random.A * qp.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5843,8 +5832,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5853,8 +5842,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp2.settings.initial_guess = proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp2.settings.initial_guess == - proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); + CHECK(qp2.settings.initial_guess == + proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); qp2.settings.eps_abs = eps_abs; qp2.settings.eps_rel = 0; qp2.init(qp_random.H, @@ -5867,22 +5856,22 @@ DOCTEST_TEST_CASE( compute_preconditioner, nullopt, mu_eq); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); qp2.solve(); - DOCTEST_CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp2.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp2.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp2.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5892,8 +5881,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp2.results.y + qp_random.C.transpose() * qp2.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } // conter factual check with another QP object starting at the updated model @@ -5902,8 +5891,8 @@ DOCTEST_TEST_CASE( qp_random.C.cast()); qp3.settings.initial_guess = proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT; - DOCTEST_CHECK(qp3.settings.initial_guess == - proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); + CHECK(qp3.settings.initial_guess == + proxqp::InitialGuessStatus::WARM_START_WITH_PREVIOUS_RESULT); qp3.settings.eps_abs = eps_abs; qp3.settings.eps_rel = 0; qp3.init(qp_random.H, @@ -5918,17 +5907,17 @@ DOCTEST_TEST_CASE( mu_eq); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(rho - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(rho - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(mu_eq - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(T(1) / mu_eq - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5938,8 +5927,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } qp3.update(nullopt, @@ -5953,17 +5942,17 @@ DOCTEST_TEST_CASE( 1.e-6, 1.e-3); for (isize iter = 0; iter < 10; ++iter) { - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); qp3.solve(); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); - DOCTEST_CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.settings.default_rho) <= 1.E-9); + CHECK(std::abs(1.e-6 - qp3.results.info.rho) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.settings.default_mu_eq) <= 1.E-9); + CHECK(std::abs(1.e-3 - qp3.results.info.mu_eq) <= 1.E-9); + CHECK(std::abs(1.e3 - qp3.results.info.mu_eq_inv) <= 1.E-9); pri_res = std::max( (qp_random.A * qp3.results.x - qp_random.b).lpNorm(), (helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) + @@ -5973,8 +5962,8 @@ DOCTEST_TEST_CASE( qp_random.g + qp_random.A.transpose() * qp3.results.y + qp_random.C.transpose() * qp3.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } } @@ -6022,8 +6011,8 @@ TEST_CASE("ProxQP::sparse: init must be called before update") qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); qp_random.H = 2 * qp_random.H; // keep same sparsity structure qp_random.g = utils::rand::vector_rand(dim); @@ -6047,8 +6036,8 @@ TEST_CASE("ProxQP::sparse: init must be called before update") qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= eps_abs); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= eps_abs); + CHECK(dua_res <= eps_abs); } TEST_CASE("ProxQP::sparse: test primal infeasibility solving") @@ -6107,8 +6096,8 @@ TEST_CASE("ProxQP::sparse: test primal infeasibility solving") qp_random.g + qp_random.A.transpose() * qp.results.y + qp_random.C.transpose() * qp.results.z) .lpNorm(); - DOCTEST_CHECK(pri_res <= scaled_eps); - DOCTEST_CHECK(dua_res <= eps_abs); + CHECK(pri_res <= scaled_eps); + CHECK(dua_res <= eps_abs); } } // TEST_CASE("ProxQP::sparse: estimate of minimal eigenvalues using Eigen") @@ -6153,7 +6142,7 @@ TEST_CASE("ProxQP::sparse: test primal infeasibility solving") // C_sparse, // qp_random.l, // qp_random.u); -// DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - +// CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - // minimal_eigenvalue) <= tol); // } // dim = 50; @@ -6187,7 +6176,7 @@ TEST_CASE("ProxQP::sparse: test primal infeasibility solving") // C_sparse, // qp_random.l, // qp_random.u); -// DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - +// CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - // minimal_eigenvalue) <= 1.); // } // } @@ -6235,8 +6224,8 @@ TEST_CASE("ProxQP::sparse: estimate of minimal eigenvalues using manual choice") nullopt, nullopt, minimal_eigenvalue); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } dim = 50; n_eq = dim; @@ -6271,8 +6260,8 @@ TEST_CASE("ProxQP::sparse: estimate of minimal eigenvalues using manual choice") nullopt, nullopt, minimal_eigenvalue); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= 1.); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= 1.); } } @@ -6326,8 +6315,8 @@ TEST_CASE( nullopt, nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= tol); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= tol); } dim = 50; n_eq = dim; @@ -6365,7 +6354,7 @@ TEST_CASE( nullopt, nullopt, estimate_minimal_eigen_value); - DOCTEST_CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - - minimal_eigenvalue) <= 1.); + CHECK(std::abs(qp.results.info.minimal_H_eigenvalue_estimate - + minimal_eigenvalue) <= 1.); } } diff --git a/test/src/sparse_ruiz_equilibration.cpp b/test/cpp/sparse_ruiz_equilibration.cpp similarity index 99% rename from test/src/sparse_ruiz_equilibration.cpp rename to test/cpp/sparse_ruiz_equilibration.cpp index 04f6b67f4..7c92feafc 100644 --- a/test/src/sparse_ruiz_equilibration.cpp +++ b/test/cpp/sparse_ruiz_equilibration.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include using namespace proxsuite; diff --git a/test/cpp/uint128.cpp b/test/cpp/uint128.cpp new file mode 100644 index 000000000..d6edd0b88 --- /dev/null +++ b/test/cpp/uint128.cpp @@ -0,0 +1,322 @@ +// +// Copyright (c) 2023 INRIA +// +#include +#include +#include +#include + +#if defined(_MSC_VER) +#include +using u128 = uint128_t; +#define MAKE_U128(low, high) u128(low, high) +#define CHECK_HIGH(val, expected) CHECK((val).high == (expected)) +#define CHECK_LOW(val, expected) CHECK((val).low == (expected)) + +// Compile-time checks: verify constexpr operators are truly constexpr +static_assert(uint128_t(0) == uint128_t(0), "== must be constexpr"); +static_assert(uint128_t(1) != uint128_t(2), "!= must be constexpr"); +static_assert(uint128_t(1) < uint128_t(2), "< must be constexpr"); +static_assert(uint128_t(2) > uint128_t(1), "> must be constexpr"); +static_assert(uint128_t(1) <= uint128_t(1), "<= must be constexpr"); +static_assert(uint128_t(1) >= uint128_t(1), ">= must be constexpr"); +static_assert(static_cast(uint128_t(1)), + "operator bool must be constexpr"); +static_assert(!static_cast(uint128_t(0)), + "operator bool(0) must be constexpr"); +static_assert(static_cast(uint128_t(42)) == 42, + "operator uint64_t must be constexpr"); +static_assert(static_cast(uint128_t(7)) == 7, + "operator int64_t must be constexpr"); +static_assert((uint128_t(0xFF) | uint128_t(0x100)) == uint128_t(0x1FF), + "| must be constexpr"); +static_assert((uint128_t(0xFF) & uint128_t(0x0F)) == uint128_t(0x0F), + "& must be constexpr"); +static_assert((uint128_t(0xFF) ^ uint128_t(0x0F)) == uint128_t(0xF0), + "^ must be constexpr"); +static_assert((~uint128_t(0)) == + uint128_t(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), + "~ must be constexpr"); +static_assert((uint128_t(1) << 4) == uint128_t(16), "<< int must be constexpr"); +static_assert((uint128_t(16) >> 4) == uint128_t(1), ">> int must be constexpr"); +static_assert((uint128_t(1) << uint128_t(4)) == uint128_t(16), + "<< u128 must be constexpr"); +static_assert((uint128_t(16) >> uint128_t(4)) == uint128_t(1), + ">> u128 must be constexpr"); + +#else +using u128 = __uint128_t; +#define MAKE_U128(low, high) ((u128(high) << 64) | low) +#define CHECK_HIGH(val, expected) \ + CHECK(static_cast(val >> 64) == (expected)) +#define CHECK_LOW(val, expected) CHECK(static_cast(val) == (expected)) +#endif + +std::ostream& +operator<<(std::ostream& os, u128 n) +{ + if (n == u128(0)) { + return os << "0"; + } + std::string s; + while (n > u128(0)) { + // Cast remainder to uint64_t for char addition. + // Works for both custom struct (via explicit operator) and built-in type. + u128 rem = n % u128(10); + s += (char)('0' + static_cast(rem)); + n = n / u128(10); + } + std::reverse(s.begin(), s.end()); + return os << s; +} + +TEST_CASE("Constructors and Equality", "[uint128]") +{ + u128 zero(0); + CHECK_LOW(zero, 0); + CHECK_HIGH(zero, 0); + + u128 val(12345); + CHECK_LOW(val, 12345); + CHECK_HIGH(val, 0); + + u128 big = MAKE_U128(0xFFFFFFFFFFFFFFFF, 0x1); + CHECK_LOW(big, 0xFFFFFFFFFFFFFFFF); + CHECK_HIGH(big, 1); + + REQUIRE(u128(10) == u128(10)); + REQUIRE(u128(10) != u128(11)); +} + +TEST_CASE("Bitwise Shifts with u128 (The Fix)", "[uint128][shift]") +{ + u128 val = u128(0); + u128 shift_amt = u128(64); + + REQUIRE((val >> shift_amt) == u128(0)); + + u128 one(1); + REQUIRE((one << one) == u128(2)); + + u128 large_shift(100); + u128 shifted = one << large_shift; + + // 1 << 100 results in high bit (1 << (100-64)) = 1 << 36 + CHECK_HIGH(shifted, (1ULL << 36)); + CHECK_LOW(shifted, 0); + +#if defined(_MSC_VER) + u128 huge_shift(128); + u128 pattern = MAKE_U128(0xFF, 0xFF); + REQUIRE((pattern >> huge_shift) == pattern); +#endif +} + +TEST_CASE("Standard Bitwise Shifts (int)", "[uint128][shift]") +{ + u128 val = MAKE_U128(1, 0); // low=1, high=0 + + u128 res = val << 64; + CHECK_HIGH(res, 1); + CHECK_LOW(res, 0); + + u128 high_val = MAKE_U128(0, 1); // low=0, high=1 + res = high_val >> 64; + CHECK_HIGH(res, 0); + CHECK_LOW(res, 1); + + u128 mix = MAKE_U128(0, 2); + REQUIRE((mix << 1) == MAKE_U128(0, 4)); +} + +TEST_CASE("Arithmetic Operations", "[uint128][math]") +{ + SECTION("Addition") + { + u128 max_low = MAKE_U128(0xFFFFFFFFFFFFFFFF, 0); + u128 one(1); + u128 result = max_low + one; + CHECK_HIGH(result, 1); + CHECK_LOW(result, 0); + } + + SECTION("Subtraction") + { + u128 zero = MAKE_U128(0, 0); + u128 one(1); + u128 result = zero - one; + CHECK_HIGH(result, 0xFFFFFFFFFFFFFFFF); + CHECK_LOW(result, 0xFFFFFFFFFFFFFFFF); + } + + SECTION("Multiplication") + { + u128 a(2); + u128 b(3); + REQUIRE((a * b) == u128(6)); + + u128 two_64 = MAKE_U128(0, 1); + u128 two(2); + u128 res = two_64 * two; + CHECK_HIGH(res, 2); + CHECK_LOW(res, 0); + } + + SECTION("Division (Decimal Printing Helper)") + { + u128 a(100); + u128 b(10); + REQUIRE((a / b) == u128(10)); + + // Test the optimize 64-bit divisor path + u128 large = MAKE_U128(0, 1); // 2^64 + u128 two(2); + u128 half_large = large / two; // 2^63 + CHECK_HIGH(half_large, 0); + CHECK_LOW(half_large, (1ULL << 63)); + } +} + +TEST_CASE("Comparison Operators", "[uint128][compare]") +{ + u128 small(10); + u128 big(20); + u128 huge = MAKE_U128(0, 1); // 2^64 + + REQUIRE(small < big); + REQUIRE(big > small); + REQUIRE(huge > big); + REQUIRE(small <= u128(10)); + REQUIRE(big >= u128(20)); +} + +TEST_CASE("Lehmer Constant Generation", "[uint128][lehmer]") +{ + constexpr u128 lehmer64_constant(0xda942042e4dd58b5); + CHECK_LOW(lehmer64_constant, 0xda942042e4dd58b5); + CHECK_HIGH(lehmer64_constant, 0); +} + +TEST_CASE("String Output (Decimal)", "[uint128][print]") +{ + std::stringstream ss; + + u128 val(12345); + ss << val; + REQUIRE(ss.str() == "12345"); + + ss.str(""); + u128 zero(0); + ss << zero; + REQUIRE(ss.str() == "0"); + + ss.str(""); + u128 big = MAKE_U128(0, 1); + ss << big; + REQUIRE(ss.str() == "18446744073709551616"); +} + +TEST_CASE("Division by Zero Guard", "[uint128][division][error]") +{ +#if defined(_MSC_VER) + u128 numerator(100); + u128 zero(0); + REQUIRE_THROWS_AS(numerator / zero, std::domain_error); + + u128 zero_via_macro = MAKE_U128(0, 0); + REQUIRE_THROWS_AS(numerator / zero_via_macro, std::domain_error); + + u128 ten(10); + REQUIRE_NOTHROW(numerator / ten); +#endif +} + +TEST_CASE("Shift by uint128_t with shift.low > INT_MAX", + "[uint128][shift][large_shift_amount]") +{ +#if defined(_MSC_VER) + u128 one(1); + u128 shift_large(0x80000003ULL); + REQUIRE((one << shift_large) == u128(8)); + REQUIRE((u128(8) >> shift_large) == u128(1)); + + u128 shift_zero_bits(0xFFFFFFFF80000000ULL); + u128 val = MAKE_U128(0x123456789ABCDEF0ULL, 0xFEDCBA9876543210ULL); + REQUIRE((val << shift_zero_bits) == val); + REQUIRE((val >> shift_zero_bits) == val); +#endif +} + +TEST_CASE("Compound Shift Operators with uint128_t", + "[uint128][shift][compound]") +{ + SECTION("Left Shift Compound Operator (uint128_t)") + { + u128 val = u128(1); + u128 shift_amt = u128(1); + + val <<= shift_amt; + REQUIRE(val == u128(2)); + + u128 val2 = u128(1); + u128 shift_64 = u128(64); + val2 <<= shift_64; + CHECK_HIGH(val2, 1); + CHECK_LOW(val2, 0); + } + + SECTION("Right Shift Compound Operator (uint128_t)") + { + u128 val = MAKE_U128(0, 1); // high=1, low=0 (represents 2^64) + u128 shift_amt = u128(1); + + val >>= shift_amt; + CHECK_HIGH(val, 0); + CHECK_LOW(val, (1ULL << 63)); // 2^63 + + u128 val2 = MAKE_U128(0, 1); + u128 shift_64 = u128(64); + val2 >>= shift_64; + CHECK_HIGH(val2, 0); + CHECK_LOW(val2, 1); + } + + SECTION("Chained Shift Operations (uint128_t)") + { + u128 val = u128(1); + u128 shift1 = u128(3); + u128 shift2 = u128(2); + + // (1 << 3) << 2 = 1 << 5 = 32 + val <<= shift1; + val <<= shift2; + REQUIRE(val == u128(32)); + } + + SECTION("Large Shift via uint128_t") + { + u128 one(1); + u128 shift_100(100); + + one <<= shift_100; + // 1 << 100 results in high bit (1 << (100-64)) = 1 << 36 + CHECK_HIGH(one, (1ULL << 36)); + CHECK_LOW(one, 0); + } + + SECTION("Over-shift Behavior (uint128_t)") + { +#if defined(_MSC_VER) + u128 pattern = MAKE_U128(0xFF, 0xFF); + u128 huge_shift(128); + + // pattern <<= 128 should wrap (modulo 128) + pattern <<= huge_shift; + REQUIRE(pattern == MAKE_U128(0xFF, 0xFF)); + + u128 pattern2 = MAKE_U128(0xFF, 0xFF); + pattern2 >>= huge_shift; + REQUIRE(pattern2 == MAKE_U128(0xFF, 0xFF)); +#endif + } +} diff --git a/test/src/util_f32.cpp b/test/cpp/util_f32.cpp similarity index 97% rename from test/src/util_f32.cpp rename to test/cpp/util_f32.cpp index 06afe7ffa..f4cbfd19d 100644 --- a/test/src/util_f32.cpp +++ b/test/cpp/util_f32.cpp @@ -1,4 +1,4 @@ -#include "util_f64.hpp" +#include "util_f32.hpp" namespace proxsuite { namespace proxqp { diff --git a/test/include/util_f32.hpp b/test/cpp/util_f32.hpp similarity index 99% rename from test/include/util_f32.hpp rename to test/cpp/util_f32.hpp index c8415220c..740a0ad97 100644 --- a/test/include/util_f32.hpp +++ b/test/cpp/util_f32.hpp @@ -12,6 +12,7 @@ LDLT_EXPLICIT_TPL_DECL(2, ldlt_compute>); LDLT_EXPLICIT_TPL_DECL(2, llt_compute>); LDLT_EXPLICIT_TPL_DECL(2, ldlt_compute>); } // namespace eigen + namespace rand { LDLT_EXPLICIT_TPL_DECL(2, matrix_rand); LDLT_EXPLICIT_TPL_DECL(1, vector_rand); diff --git a/test/src/util_f64.cpp b/test/cpp/util_f64.cpp similarity index 100% rename from test/src/util_f64.cpp rename to test/cpp/util_f64.cpp diff --git a/test/include/util_f64.hpp b/test/cpp/util_f64.hpp similarity index 100% rename from test/include/util_f64.hpp rename to test/cpp/util_f64.hpp diff --git a/test/cpp/utils.hpp b/test/cpp/utils.hpp new file mode 100644 index 000000000..c7a9b791a --- /dev/null +++ b/test/cpp/utils.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "utils/util_f32.hpp" +#include "utils/util_f64.hpp" diff --git a/test/doctest/doctest.cpp b/test/doctest/doctest.cpp deleted file mode 100644 index 6a4a5dba9..000000000 --- a/test/doctest/doctest.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN - -#include "doctest.hpp" diff --git a/test/doctest/doctest.hpp b/test/doctest/doctest.hpp deleted file mode 100644 index fd4072374..000000000 --- a/test/doctest/doctest.hpp +++ /dev/null @@ -1,8694 +0,0 @@ -// ====================================================================== lgtm -// [cpp/missing-header-guard] -// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == -// ====================================================================== -// -// doctest.h - the lightest feature-rich C++ single-header testing framework for -// unit tests and TDD -// -// Copyright (c) 2016-2021 Viktor Kirilov -// -// Distributed under the MIT Software License -// See accompanying file LICENSE.txt or copy at -// https://opensource.org/licenses/MIT -// -// The documentation can be found at the library's page: -// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md -// -// ================================================================================================= -// ================================================================================================= -// ================================================================================================= -// -// The library is heavily influenced by Catch - -// https://github.com/catchorg/Catch2 which uses the Boost Software License - -// Version 1.0 see here - -// https://github.com/catchorg/Catch2/blob/master/LICENSE.txt -// -// The concept of subcases (sections in Catch) and expression decomposition are -// from there. Some parts of the code are taken directly: -// - stringification - the detection of "ostream& operator<<(ostream&, const -// T&)" and StringMaker<> -// - the Approx() helper class for floating point comparison -// - colors in the console -// - breaking into a debugger -// - signal / SEH handling -// - timer -// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA -// copy/paste) -// -// The expression decomposing templates are taken from lest - -// https://github.com/martinmoene/lest which uses the Boost Software License - -// Version 1.0 see here - -// https://github.com/martinmoene/lest/blob/master/LICENSE.txt -// -// ================================================================================================= -// ================================================================================================= -// ================================================================================================= - -#ifndef DOCTEST_LIBRARY_INCLUDED -#define DOCTEST_LIBRARY_INCLUDED - -// ================================================================================================= -// == VERSION -// ====================================================================================== -// ================================================================================================= - -#define DOCTEST_VERSION_MAJOR 2 -#define DOCTEST_VERSION_MINOR 4 -#define DOCTEST_VERSION_PATCH 9 - -// util we need here -#define DOCTEST_TOSTR_IMPL(x) #x -#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) - -#define DOCTEST_VERSION_STR \ - DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) \ - "." DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." DOCTEST_TOSTR( \ - DOCTEST_VERSION_PATCH) - -#define DOCTEST_VERSION \ - (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + \ - DOCTEST_VERSION_PATCH) - -// ================================================================================================= -// == COMPILER VERSION -// ============================================================================= -// ================================================================================================= - -// ideas for the version stuff are taken from here: -// https://github.com/cxxstuff/cxx_detect - -#ifdef _MSC_VER -#define DOCTEST_CPLUSPLUS _MSVC_LANG -#else -#define DOCTEST_CPLUSPLUS __cplusplus -#endif - -#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) \ - ((MAJOR) * 10000000 + (MINOR) * 100000 + (PATCH)) - -// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because -// of clang-cl... -#if defined(_MSC_VER) && defined(_MSC_FULL_VER) -#if _MSC_VER == _MSC_FULL_VER / 10000 -#define DOCTEST_MSVC \ - DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000) -#else // MSVC -#define DOCTEST_MSVC \ - DOCTEST_COMPILER( \ - _MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) -#endif // MSVC -#endif // MSVC -#if defined(__clang__) && defined(__clang_minor__) -#define DOCTEST_CLANG \ - DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && \ - defined(__GNUC_PATCHLEVEL__) && !defined(__INTEL_COMPILER) -#define DOCTEST_GCC \ - DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#endif // GCC - -#ifndef DOCTEST_MSVC -#define DOCTEST_MSVC 0 -#endif // DOCTEST_MSVC -#ifndef DOCTEST_CLANG -#define DOCTEST_CLANG 0 -#endif // DOCTEST_CLANG -#ifndef DOCTEST_GCC -#define DOCTEST_GCC 0 -#endif // DOCTEST_GCC - -// ================================================================================================= -// == COMPILER WARNINGS HELPERS -// ==================================================================== -// ================================================================================================= - -#if DOCTEST_CLANG -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) -#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push") -#define DOCTEST_CLANG_SUPPRESS_WARNING(w) \ - DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) -#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") -#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) -#else // DOCTEST_CLANG -#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -#define DOCTEST_CLANG_SUPPRESS_WARNING(w) -#define DOCTEST_CLANG_SUPPRESS_WARNING_POP -#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) -#endif // DOCTEST_CLANG - -#if DOCTEST_GCC -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) -#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push") -#define DOCTEST_GCC_SUPPRESS_WARNING(w) \ - DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) -#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") -#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) -#else // DOCTEST_GCC -#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH -#define DOCTEST_GCC_SUPPRESS_WARNING(w) -#define DOCTEST_GCC_SUPPRESS_WARNING_POP -#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) -#endif // DOCTEST_GCC - -#if DOCTEST_MSVC -#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push)) -#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) -#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) -#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) -#else // DOCTEST_MSVC -#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -#define DOCTEST_MSVC_SUPPRESS_WARNING(w) -#define DOCTEST_MSVC_SUPPRESS_WARNING_POP -#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) -#endif // DOCTEST_MSVC - -// ================================================================================================= -// == COMPILER WARNINGS -// ============================================================================ -// ================================================================================================= - -// both the header and the implementation suppress all of these, -// so it only makes sense to aggregrate them like so -#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ - \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ - \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - /* these 4 also disabled globally via cmake: */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4514) /* unreferenced inline function has been removed */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4711) /* function selected for inline expansion*/ \ - /* */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4996) /* The compiler encountered a deprecated declaration */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4706) /* assignment within conditional expression */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4512) /* 'class' : assignment operator could not be generated */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4640) /* construction of local static object not thread-safe */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - /* static analysis */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 26439) /* Function may not throw. Declare it 'noexcept' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 26495) /* Always initialize a member variable */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ - -#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH - -DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated") - -DOCTEST_GCC_SUPPRESS_WARNING_PUSH -DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy") -DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor") -DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo") - -DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -DOCTEST_MSVC_SUPPRESS_WARNING( - 4623) // default constructor was implicitly defined as deleted - -#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4548) /* before comma no effect; expected side - effect */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4265) /* virtual functions, but destructor is not virtual */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4986) /* exception specification does not match previous */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4350) /* 'member1' called instead of 'member2' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4668) /* not defined as a preprocessor macro */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4623) /* default constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 5039) /* pointer to pot. throwing function passed to extern C */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 5105) /* macro producing 'defined' has undefined behavior */ \ - DOCTEST_MSVC_SUPPRESS_WARNING( \ - 4738) /* storing float result in memory, loss of performance */ - -#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP - -// ================================================================================================= -// == FEATURE DETECTION -// ============================================================================ -// ================================================================================================= - -// general compiler feature support table: -// https://en.cppreference.com/w/cpp/compiler_support MSVC C++11 feature support -// table: https://msdn.microsoft.com/en-us/library/hh567368.aspx GCC C++11 -// feature support table: https://gcc.gnu.org/projects/cxx-status.html MSVC -// version table: -// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering -// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022) -// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) -// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) -// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) -// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) -// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) -// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) -// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) -// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) - -// Universal Windows Platform support -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -#define DOCTEST_CONFIG_NO_WINDOWS_SEH -#endif // WINAPI_FAMILY -#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH) -#define DOCTEST_CONFIG_WINDOWS_SEH -#endif // MSVC -#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && \ - defined(DOCTEST_CONFIG_WINDOWS_SEH) -#undef DOCTEST_CONFIG_WINDOWS_SEH -#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH - -#if !defined(_WIN32) && !defined(__QNX__) && \ - !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(__EMSCRIPTEN__) && \ - !defined(__wasi__) -#define DOCTEST_CONFIG_POSIX_SIGNALS -#endif // _WIN32 -#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && \ - defined(DOCTEST_CONFIG_POSIX_SIGNALS) -#undef DOCTEST_CONFIG_POSIX_SIGNALS -#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && \ - !defined(_CPPUNWIND) || \ - defined(__wasi__) -#define DOCTEST_CONFIG_NO_EXCEPTIONS -#endif // no exceptions -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#define DOCTEST_CONFIG_NO_EXCEPTIONS -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS - -#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && \ - !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS) -#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && - // !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS - -#ifdef __wasi__ -#define DOCTEST_CONFIG_NO_MULTITHREADING -#endif - -#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && \ - !defined(DOCTEST_CONFIG_IMPLEMENT) -#define DOCTEST_CONFIG_IMPLEMENT -#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN - -#if defined(_WIN32) || defined(__CYGWIN__) -#if DOCTEST_MSVC -#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport) -#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport) -#else // MSVC -#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport)) -#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport)) -#endif // MSVC -#else // _WIN32 -#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default"))) -#define DOCTEST_SYMBOL_IMPORT -#endif // _WIN32 - -#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL -#ifdef DOCTEST_CONFIG_IMPLEMENT -#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT -#else // DOCTEST_CONFIG_IMPLEMENT -#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT -#endif // DOCTEST_CONFIG_IMPLEMENT -#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL -#define DOCTEST_INTERFACE -#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL - -// needed for extern template instantiations -// see https://github.com/fmtlib/fmt/issues/2228 -#if DOCTEST_MSVC -#define DOCTEST_INTERFACE_DECL -#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE -#else // DOCTEST_MSVC -#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE -#define DOCTEST_INTERFACE_DEF -#endif // DOCTEST_MSVC - -#define DOCTEST_EMPTY - -#if DOCTEST_MSVC -#define DOCTEST_NOINLINE __declspec(noinline) -#define DOCTEST_UNUSED -#define DOCTEST_ALIGNMENT(x) -#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0) -#define DOCTEST_NOINLINE -#define DOCTEST_UNUSED -#define DOCTEST_ALIGNMENT(x) -#else -#define DOCTEST_NOINLINE __attribute__((noinline)) -#define DOCTEST_UNUSED __attribute__((unused)) -#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) -#endif - -#ifndef DOCTEST_NORETURN -#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_NORETURN -#else // DOCTEST_MSVC -#define DOCTEST_NORETURN [[noreturn]] -#endif // DOCTEST_MSVC -#endif // DOCTEST_NORETURN - -#ifndef DOCTEST_NOEXCEPT -#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_NOEXCEPT -#else // DOCTEST_MSVC -#define DOCTEST_NOEXCEPT noexcept -#endif // DOCTEST_MSVC -#endif // DOCTEST_NOEXCEPT - -#ifndef DOCTEST_CONSTEXPR -#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_CONSTEXPR const -#define DOCTEST_CONSTEXPR_FUNC inline -#else // DOCTEST_MSVC -#define DOCTEST_CONSTEXPR constexpr -#define DOCTEST_CONSTEXPR_FUNC constexpr -#endif // DOCTEST_MSVC -#endif // DOCTEST_CONSTEXPR - -// ================================================================================================= -// == FEATURE DETECTION END -// ======================================================================== -// ================================================================================================= - -#define DOCTEST_DECLARE_INTERFACE(name) \ - virtual ~name(); \ - name() = default; \ - name(const name&) = delete; \ - name(name&&) = delete; \ - name& operator=(const name&) = delete; \ - name& operator=(name&&) = delete; - -#define DOCTEST_DEFINE_INTERFACE(name) name::~name() = default; - -// internal macros for string concatenation and anonymous variable name -// generation -#define DOCTEST_CAT_IMPL(s1, s2) s1##s2 -#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) -#ifdef __COUNTER__ // not standard and may be missing for some compilers -#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) -#else // __COUNTER__ -#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__) -#endif // __COUNTER__ - -#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE -#define DOCTEST_REF_WRAP(x) x& -#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE -#define DOCTEST_REF_WRAP(x) x -#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE - -// not using __APPLE__ because... this is how Catch does it -#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED -#define DOCTEST_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -#define DOCTEST_PLATFORM_IPHONE -#elif defined(_WIN32) -#define DOCTEST_PLATFORM_WINDOWS -#elif defined(__wasi__) -#define DOCTEST_PLATFORM_WASI -#else // DOCTEST_PLATFORM -#define DOCTEST_PLATFORM_LINUX -#endif // DOCTEST_PLATFORM - -namespace doctest { -namespace detail { -static DOCTEST_CONSTEXPR int -consume(const int*, int) noexcept -{ - return 0; -} -} -} - -#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ - static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP - -#ifndef DOCTEST_BREAK_INTO_DEBUGGER -// should probably take a look at https://github.com/scottt/debugbreak -#ifdef DOCTEST_PLATFORM_LINUX -#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) -// Break at the location of the failing check if possible -#define DOCTEST_BREAK_INTO_DEBUGGER() \ - __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) -#else -#include -#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) -#endif -#elif defined(DOCTEST_PLATFORM_MAC) -#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || \ - defined(__i386) -#define DOCTEST_BREAK_INTO_DEBUGGER() \ - __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) -#elif defined(__ppc__) || defined(__ppc64__) -// https://www.cocoawithlove.com/2008/03/break-into-debugger.html -#define DOCTEST_BREAK_INTO_DEBUGGER() \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : \ - : \ - : "memory", "r0", "r3", "r4") // NOLINT(hicpp-no-assembler) -#else -#define DOCTEST_BREAK_INTO_DEBUGGER() \ - __asm__("brk #0"); // NOLINT(hicpp-no-assembler) -#endif -#elif DOCTEST_MSVC -#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() -#elif defined(__MINGW32__) -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls") -extern "C" __declspec(dllimport) void __stdcall -DebugBreak(); -DOCTEST_GCC_SUPPRESS_WARNING_POP -#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() -#else // linux -#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0)) -#endif // linux -#endif // DOCTEST_BREAK_INTO_DEBUGGER - -// this is kept here for backwards compatibility since the config option was -// changed -#ifdef DOCTEST_CONFIG_USE_IOSFWD -#ifndef DOCTEST_CONFIG_USE_STD_HEADERS -#define DOCTEST_CONFIG_USE_STD_HEADERS -#endif -#endif // DOCTEST_CONFIG_USE_IOSFWD - -// for clang - always include ciso646 (which drags some std stuff) because -// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in -// which case we don't want to forward declare stuff from std - for reference: -// https://github.com/doctest/doctest/issues/126 -// https://github.com/doctest/doctest/issues/356 -#if DOCTEST_CLANG -#include -#ifdef _LIBCPP_VERSION -#ifndef DOCTEST_CONFIG_USE_STD_HEADERS -#define DOCTEST_CONFIG_USE_STD_HEADERS -#endif -#endif // _LIBCPP_VERSION -#endif // clang - -#ifdef DOCTEST_CONFIG_USE_STD_HEADERS -#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN -#include -#include -#include -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END -#else // DOCTEST_CONFIG_USE_STD_HEADERS - -// Forward declaring 'X' in namespace std is not permitted by the C++ Standard. -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) - -namespace std { // NOLINT(cert-dcl58-cpp) -typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) -typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using) -template -struct char_traits; -template<> -struct char_traits; -template -class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) -typedef basic_ostream> - ostream; // NOLINT(modernize-use-using) -template -// NOLINTNEXTLINE -basic_ostream& -operator<<(basic_ostream&, const char*); -template -class basic_istream; -typedef basic_istream> - istream; // NOLINT(modernize-use-using) -template -class tuple; -#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: -// https://github.com/doctest/doctest/issues/183 -template -class allocator; -template -class basic_string; -using string = basic_string, allocator>; -#endif // VS 2019 -} // namespace std - -DOCTEST_MSVC_SUPPRESS_WARNING_POP - -#endif // DOCTEST_CONFIG_USE_STD_HEADERS - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#include -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - -namespace doctest { - -using std::size_t; - -DOCTEST_INTERFACE extern bool is_running_in_test; - -#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE -#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned -#endif - -// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that -// can hold strings with length of up to 23 chars on the stack before going on -// the heap - the last byte of the buffer is used for: -// - "is small" bit - the highest bit - if "0" then it is small - otherwise its -// "1" (128) -// - if small - capacity left before going on the heap - using the lowest 5 bits -// - if small - 2 bits are left unused - the second and third highest ones -// - if small - acts as a null terminator if strlen() is 23 (24 including the -// null terminator) -// and the "is small" bit remains "0" ("as well as the capacity -// left") so its OK -// Idea taken from this lecture about the string implementation of -// facebook/folly - fbstring https://www.youtube.com/watch?v=kPR8h4-qZdk -// TODO: -// - optimizations - like not deleting memory unnecessarily in operator= and -// etc. -// - resize/reserve/clear -// - replace -// - back/front -// - iterator stuff -// - find & friends -// - push_back/pop_back -// - assign/insert/erase -// - relational operators as free functions - taking const char* as one of the -// params -class DOCTEST_INTERFACE String -{ -public: - using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; - -private: - static DOCTEST_CONSTEXPR size_type len = - 24; //! OCLINT avoid private static members - static DOCTEST_CONSTEXPR size_type last = - len - 1; //! OCLINT avoid private static members - - struct view // len should be more than sizeof(view) - because of the final - // byte for flags - { - char* ptr; - size_type size; - size_type capacity; - }; - - union - { - char buf[len]; // NOLINT(*-avoid-c-arrays) - view data; - }; - - char* allocate(size_type sz); - - bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } - void setOnHeap() noexcept; - void setLast(size_type in = last) noexcept; - void setSize(size_type sz) noexcept; - - void copy(const String& other); - -public: - static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); - - String() noexcept; - ~String(); - - // cppcheck-suppress noExplicitConstructor - String(const char* in); - String(const char* in, size_type in_size); - - String(std::istream& in, size_type in_size); - - String(const String& other); - String& operator=(const String& other); - - String& operator+=(const String& other); - - String(String&& other) noexcept; - String& operator=(String&& other) noexcept; - - char operator[](size_type i) const; - char& operator[](size_type i); - - // the only functions I'm willing to leave in the interface - available for - // inlining - const char* c_str() const - { - return const_cast(this)->c_str(); - } // NOLINT - char* c_str() - { - if (isOnStack()) { - return reinterpret_cast(buf); - } - return data.ptr; - } - - size_type size() const; - size_type capacity() const; - - String substr(size_type pos, size_type cnt = npos) &&; - String substr(size_type pos, size_type cnt = npos) const&; - - size_type find(char ch, size_type pos = 0) const; - size_type rfind(char ch, size_type pos = npos) const; - - int compare(const char* other, bool no_case = false) const; - int compare(const String& other, bool no_case = false) const; - - friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, - const String& in); -}; - -DOCTEST_INTERFACE String -operator+(const String& lhs, const String& rhs); - -DOCTEST_INTERFACE bool -operator==(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool -operator!=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool -operator<(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool -operator>(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool -operator<=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool -operator>=(const String& lhs, const String& rhs); - -class DOCTEST_INTERFACE Contains -{ -public: - explicit Contains(const String& string); - - bool checkWith(const String& other) const; - - String string; -}; - -DOCTEST_INTERFACE String -toString(const Contains& in); - -DOCTEST_INTERFACE bool -operator==(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool -operator==(const Contains& lhs, const String& rhs); -DOCTEST_INTERFACE bool -operator!=(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool -operator!=(const Contains& lhs, const String& rhs); - -namespace Color { -enum Enum -{ - None = 0, - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White -}; - -DOCTEST_INTERFACE std::ostream& -operator<<(std::ostream& s, Color::Enum code); -} // namespace Color - -namespace assertType { -enum Enum -{ - // macro traits - - is_warn = 1, - is_check = 2 * is_warn, - is_require = 2 * is_check, - - is_normal = 2 * is_require, - is_throws = 2 * is_normal, - is_throws_as = 2 * is_throws, - is_throws_with = 2 * is_throws_as, - is_nothrow = 2 * is_throws_with, - - is_false = 2 * is_nothrow, - is_unary = - 2 * is_false, // not checked anywhere - used just to distinguish the types - - is_eq = 2 * is_unary, - is_ne = 2 * is_eq, - - is_lt = 2 * is_ne, - is_gt = 2 * is_lt, - - is_ge = 2 * is_gt, - is_le = 2 * is_ge, - - // macro types - - DT_WARN = is_normal | is_warn, - DT_CHECK = is_normal | is_check, - DT_REQUIRE = is_normal | is_require, - - DT_WARN_FALSE = is_normal | is_false | is_warn, - DT_CHECK_FALSE = is_normal | is_false | is_check, - DT_REQUIRE_FALSE = is_normal | is_false | is_require, - - DT_WARN_THROWS = is_throws | is_warn, - DT_CHECK_THROWS = is_throws | is_check, - DT_REQUIRE_THROWS = is_throws | is_require, - - DT_WARN_THROWS_AS = is_throws_as | is_warn, - DT_CHECK_THROWS_AS = is_throws_as | is_check, - DT_REQUIRE_THROWS_AS = is_throws_as | is_require, - - DT_WARN_THROWS_WITH = is_throws_with | is_warn, - DT_CHECK_THROWS_WITH = is_throws_with | is_check, - DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, - - DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, - DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, - DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, - - DT_WARN_NOTHROW = is_nothrow | is_warn, - DT_CHECK_NOTHROW = is_nothrow | is_check, - DT_REQUIRE_NOTHROW = is_nothrow | is_require, - - DT_WARN_EQ = is_normal | is_eq | is_warn, - DT_CHECK_EQ = is_normal | is_eq | is_check, - DT_REQUIRE_EQ = is_normal | is_eq | is_require, - - DT_WARN_NE = is_normal | is_ne | is_warn, - DT_CHECK_NE = is_normal | is_ne | is_check, - DT_REQUIRE_NE = is_normal | is_ne | is_require, - - DT_WARN_GT = is_normal | is_gt | is_warn, - DT_CHECK_GT = is_normal | is_gt | is_check, - DT_REQUIRE_GT = is_normal | is_gt | is_require, - - DT_WARN_LT = is_normal | is_lt | is_warn, - DT_CHECK_LT = is_normal | is_lt | is_check, - DT_REQUIRE_LT = is_normal | is_lt | is_require, - - DT_WARN_GE = is_normal | is_ge | is_warn, - DT_CHECK_GE = is_normal | is_ge | is_check, - DT_REQUIRE_GE = is_normal | is_ge | is_require, - - DT_WARN_LE = is_normal | is_le | is_warn, - DT_CHECK_LE = is_normal | is_le | is_check, - DT_REQUIRE_LE = is_normal | is_le | is_require, - - DT_WARN_UNARY = is_normal | is_unary | is_warn, - DT_CHECK_UNARY = is_normal | is_unary | is_check, - DT_REQUIRE_UNARY = is_normal | is_unary | is_require, - - DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, - DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, - DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, -}; -} // namespace assertType - -DOCTEST_INTERFACE const char* -assertString(assertType::Enum at); -DOCTEST_INTERFACE const char* -failureString(assertType::Enum at); -DOCTEST_INTERFACE const char* -skipPathFromFilename(const char* file); - -struct DOCTEST_INTERFACE TestCaseData -{ - String m_file; // the file in which the test was registered (using String - - // see #350) - unsigned m_line; // the line where the test was registered - const char* m_name; // name of the test case - const char* m_test_suite; // the test suite in which the test was added - const char* m_description; - bool m_skip; - bool m_no_breaks; - bool m_no_output; - bool m_may_fail; - bool m_should_fail; - int m_expected_failures; - double m_timeout; -}; - -struct DOCTEST_INTERFACE AssertData -{ - // common - for all asserts - const TestCaseData* m_test_case; - assertType::Enum m_at; - const char* m_file; - int m_line; - const char* m_expr; - bool m_failed; - - // exception-related - for all asserts - bool m_threw; - String m_exception; - - // for normal asserts - String m_decomp; - - // for specific exception-related asserts - bool m_threw_as; - const char* m_exception_type; - - class DOCTEST_INTERFACE StringContains - { - private: - Contains content; - bool isContains; - - public: - StringContains(const String& str) - : content(str) - , isContains(false) - { - } - StringContains(Contains cntn) - : content(static_cast(cntn)) - , isContains(true) - { - } - - bool check(const String& str) - { - return isContains ? (content == str) : (content.string == str); - } - - operator const String&() const { return content.string; } - - const char* c_str() const { return content.string.c_str(); } - } m_exception_string; - - AssertData(assertType::Enum at, - const char* file, - int line, - const char* expr, - const char* exception_type, - const StringContains& exception_string); -}; - -struct DOCTEST_INTERFACE MessageData -{ - String m_string; - const char* m_file; - int m_line; - assertType::Enum m_severity; -}; - -struct DOCTEST_INTERFACE SubcaseSignature -{ - String m_name; - const char* m_file; - int m_line; - - bool operator==(const SubcaseSignature& other) const; - bool operator<(const SubcaseSignature& other) const; -}; - -struct DOCTEST_INTERFACE IContextScope -{ - DOCTEST_DECLARE_INTERFACE(IContextScope) - virtual void stringify(std::ostream*) const = 0; -}; - -namespace detail { -struct DOCTEST_INTERFACE TestCase; -} // namespace detail - -struct ContextOptions //! OCLINT too many fields -{ - std::ostream* cout = nullptr; // stdout stream - String binary_name; // the test binary name - - const detail::TestCase* currentTest = nullptr; - - // == parameters from the command line - String out; // output filename - String order_by; // how tests should be ordered - unsigned rand_seed; // the seed for rand ordering - - unsigned first; // the first (matching) test to be executed - unsigned last; // the last (matching) test to be executed - - int abort_after; // stop tests after this many failed assertions - int subcase_filter_levels; // apply the subcase filters for the first N levels - - bool success; // include successful assertions in output - bool case_sensitive; // if filtering should be case sensitive - bool exit; // if the program should be exited after the tests are ran/whatever - bool duration; // print the time duration of each test case - bool minimal; // minimal console output (only test failures) - bool quiet; // no console output - bool no_throw; // to skip exceptions-related assertion macros - bool no_exitcode; // if the framework should return 0 as the exitcode - bool no_run; // to not run the tests at all (can be done with an "*" exclude) - bool no_intro; // to not print the intro of the framework - bool no_version; // to not print the version of the framework - bool no_colors; // if output to the console should be colorized - bool - force_colors; // forces the use of colors even when a tty cannot be detected - bool no_breaks; // to not break into the debugger - bool no_skip; // don't skip test cases which are marked to be skipped - bool - gnu_file_line; // if line numbers should be surrounded with :x: and not (x): - bool no_path_in_filenames; // if the path to files should be removed from the - // output - bool no_line_numbers; // if source code line numbers should be omitted from - // the output - bool no_debug_output; // no output in the debug console when a debugger is - // attached - bool no_skipped_summary; // don't print "skipped" in the summary !!! - // UNDOCUMENTED !!! - bool no_time_in_output; // omit any time/timestamps from output !!! - // UNDOCUMENTED !!! - - bool help; // to print the help - bool version; // to print the version - bool count; // if only the count of matching tests is to be retrieved - bool list_test_cases; // to list all tests matching the filters - bool list_test_suites; // to list all suites matching the filters - bool list_reporters; // lists all registered reporters -}; - -namespace detail { -namespace types { -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -using namespace std; -#else -template -struct enable_if -{}; - -template -struct enable_if -{ - using type = T; -}; - -struct true_type -{ - static DOCTEST_CONSTEXPR bool value = true; -}; -struct false_type -{ - static DOCTEST_CONSTEXPR bool value = false; -}; - -template -struct remove_reference -{ - using type = T; -}; -template -struct remove_reference -{ - using type = T; -}; -template -struct remove_reference -{ - using type = T; -}; - -template -struct is_rvalue_reference : false_type -{}; -template -struct is_rvalue_reference : true_type -{}; - -template -struct remove_const -{ - using type = T; -}; -template -struct remove_const -{ - using type = T; -}; - -// Compiler intrinsics -template -struct is_enum -{ - static DOCTEST_CONSTEXPR bool value = __is_enum(T); -}; -template -struct underlying_type -{ - using type = __underlying_type(T); -}; - -template -struct is_pointer : false_type -{}; -template -struct is_pointer : true_type -{}; - -template -struct is_array : false_type -{}; -// NOLINTNEXTLINE(*-avoid-c-arrays) -template -struct is_array : true_type -{}; -#endif -} - -// -template -T&& -declval(); - -template -DOCTEST_CONSTEXPR_FUNC T&& -forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT -{ - return static_cast(t); -} - -template -DOCTEST_CONSTEXPR_FUNC T&& -forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT -{ - return static_cast(t); -} - -template -struct deferred_false : types::false_type -{}; - -// MSVS 2015 :( -#if defined(_MSC_VER) && _MSC_VER <= 1900 -template -struct has_global_insertion_operator : types::false_type -{}; - -template -struct has_global_insertion_operator< - T, - decltype(::operator<<(declval(), declval()), void())> - : types::true_type -{}; - -template -struct has_insertion_operator -{ - static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; -}; - -template -struct insert_hack; - -template -struct insert_hack -{ - static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } -}; - -template -struct insert_hack -{ - static void insert(std::ostream& os, const T& t) { operator<<(os, t); } -}; - -template -using insert_hack_t = insert_hack::value>; -#else -template -struct has_insertion_operator : types::false_type -{}; -#endif - -template -struct has_insertion_operator< - T, - decltype(operator<<(declval(), declval()), void())> - : types::true_type -{}; - -DOCTEST_INTERFACE std::ostream* -tlssPush(); -DOCTEST_INTERFACE String -tlssPop(); - -template -struct StringMakerBase -{ - template - static String convert(const DOCTEST_REF_WRAP(T)) - { -#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES - static_assert( - deferred_false::value, - "No stringification detected for type T. See string conversion manual"); -#endif - return "{?}"; - } -}; - -template -struct filldata; - -template -void -filloss(std::ostream* stream, const T& in) -{ - filldata::fill(stream, in); -} - -template -void -filloss(std::ostream* stream, const T (&in)[N]) -{ // NOLINT(*-avoid-c-arrays) - // T[N], T(&)[N], T(&&)[N] have same behaviour. - // Hence remove reference. - filloss::type>(stream, in); -} - -template -String -toStream(const T& in) -{ - std::ostream* stream = tlssPush(); - filloss(stream, in); - return tlssPop(); -} - -template<> -struct StringMakerBase -{ - template - static String convert(const DOCTEST_REF_WRAP(T) in) - { - return toStream(in); - } -}; -} // namespace detail - -template -struct StringMaker - : public detail::StringMakerBase::value || - detail::types::is_pointer::value || - detail::types::is_array::value> -{}; - -#ifndef DOCTEST_STRINGIFY -#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY -#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__)) -#else -#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__) -#endif -#endif - -template -String -toString() -{ -#if DOCTEST_MSVC >= 0 && DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 - String ret = - __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) - String::size_type beginPos = ret.find('<'); - return ret.substr(beginPos + 1, - ret.size() - beginPos - - static_cast(sizeof(">(void)"))); -#else - String ret = - __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] - String::size_type begin = ret.find('=') + 2; - return ret.substr(begin, ret.size() - begin - 1); -#endif -} - -template::value, - bool>::type = true> -String -toString(const DOCTEST_REF_WRAP(T) value) -{ - return StringMaker::convert(value); -} - -#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -DOCTEST_INTERFACE String -toString(const char* in); -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - -#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: -// https://github.com/doctest/doctest/issues/183 -DOCTEST_INTERFACE String -toString(const std::string& in); -#endif // VS 2019 - -DOCTEST_INTERFACE String -toString(String in); - -DOCTEST_INTERFACE String toString(std::nullptr_t); - -DOCTEST_INTERFACE String -toString(bool in); - -DOCTEST_INTERFACE String -toString(float in); -DOCTEST_INTERFACE String -toString(double in); -DOCTEST_INTERFACE String -toString(double long in); - -DOCTEST_INTERFACE String -toString(char in); -DOCTEST_INTERFACE String -toString(char signed in); -DOCTEST_INTERFACE String -toString(char unsigned in); -DOCTEST_INTERFACE String -toString(short in); -DOCTEST_INTERFACE String -toString(short unsigned in); -DOCTEST_INTERFACE String -toString(signed in); -DOCTEST_INTERFACE String -toString(unsigned in); -DOCTEST_INTERFACE String -toString(long in); -DOCTEST_INTERFACE String -toString(long unsigned in); -DOCTEST_INTERFACE String -toString(long long in); -DOCTEST_INTERFACE String -toString(long long unsigned in); - -template::value, - bool>::type = true> -String -toString(const DOCTEST_REF_WRAP(T) value) -{ - using UT = typename detail::types::underlying_type::type; - return (DOCTEST_STRINGIFY(static_cast(value))); -} - -namespace detail { -template -struct filldata -{ - static void fill(std::ostream* stream, const T& in) - { -#if defined(_MSC_VER) && _MSC_VER <= 1900 - insert_hack_t::insert(*stream, in); -#else - operator<<(*stream, in); -#endif - } -}; - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) -// NOLINTBEGIN(*-avoid-c-arrays) -template -struct filldata -{ - static void fill(std::ostream* stream, const T (&in)[N]) - { - *stream << "["; - for (size_t i = 0; i < N; i++) { - if (i != 0) { - *stream << ", "; - } - *stream << (DOCTEST_STRINGIFY(in[i])); - } - *stream << "]"; - } -}; -// NOLINTEND(*-avoid-c-arrays) -DOCTEST_MSVC_SUPPRESS_WARNING_POP - -// Specialized since we don't want the terminating null byte! -// NOLINTBEGIN(*-avoid-c-arrays) -template -struct filldata -{ - static void fill(std::ostream* stream, const char (&in)[N]) - { - *stream << String(in, in[N - 1] ? N : N - 1); - } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) -}; -// NOLINTEND(*-avoid-c-arrays) - -template<> -struct filldata -{ - static void fill(std::ostream* stream, const void* in); -}; - -template -struct filldata -{ - static void fill(std::ostream* stream, const T* in) - { - filldata::fill(stream, in); - } -}; -} - -struct DOCTEST_INTERFACE Approx -{ - Approx(double value); - - Approx operator()(double value) const; - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - explicit Approx(const T& value, - typename detail::types::enable_if< - std::is_constructible::value>::type* = - static_cast(nullptr)) - { - *this = static_cast(value); - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - Approx& epsilon(double newEpsilon); - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - typename std::enable_if::value, - Approx&>::type epsilon(const T& newEpsilon) - { - m_epsilon = static_cast(newEpsilon); - return *this; - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - Approx& scale(double newScale); - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - typename std::enable_if::value, - Approx&>::type scale(const T& newScale) - { - m_scale = static_cast(newScale); - return *this; - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - // clang-format off - DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs); - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#define DOCTEST_APPROX_PREFIX \ - template friend typename std::enable_if::value, bool>::type - - DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); } - DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); } - DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); } - DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); } - DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; } -#undef DOCTEST_APPROX_PREFIX -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - // clang-format on - - double m_epsilon; - double m_scale; - double m_value; -}; - -DOCTEST_INTERFACE String -toString(const Approx& in); - -DOCTEST_INTERFACE const ContextOptions* -getContextOptions(); - -template -struct DOCTEST_INTERFACE_DECL IsNaN -{ - F value; - bool flipped; - IsNaN(F f, bool flip = false) - : value(f) - , flipped(flip) - { - } - IsNaN operator!() const { return { value, !flipped }; } - operator bool() const; -}; -#ifndef __MINGW32__ -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -#endif -DOCTEST_INTERFACE String -toString(IsNaN in); -DOCTEST_INTERFACE String -toString(IsNaN in); -DOCTEST_INTERFACE String -toString(IsNaN in); - -#ifndef DOCTEST_CONFIG_DISABLE - -namespace detail { -// clang-format off -#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - template struct decay_array { using type = T; }; - template struct decay_array { using type = T*; }; - template struct decay_array { using type = T*; }; - - template struct not_char_pointer { static DOCTEST_CONSTEXPR value = 1; }; - template<> struct not_char_pointer { static DOCTEST_CONSTEXPR value = 0; }; - template<> struct not_char_pointer { static DOCTEST_CONSTEXPR value = 0; }; - - template struct can_use_op : public not_char_pointer::type> {}; -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -// clang-format on - -struct DOCTEST_INTERFACE TestFailureException -{}; - -DOCTEST_INTERFACE bool -checkIfShouldThrow(assertType::Enum at); - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -DOCTEST_NORETURN -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -DOCTEST_INTERFACE void -throwException(); - -struct DOCTEST_INTERFACE Subcase -{ - SubcaseSignature m_signature; - bool m_entered = false; - - Subcase(const String& name, const char* file, int line); - Subcase(const Subcase&) = delete; - Subcase(Subcase&&) = delete; - Subcase& operator=(const Subcase&) = delete; - Subcase& operator=(Subcase&&) = delete; - ~Subcase(); - - operator bool() const; - -private: - bool checkFilters(); -}; - -template -String -stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, - const char* op, - const DOCTEST_REF_WRAP(R) rhs) -{ - return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); -} - -#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") -#endif - -// This will check if there is any way it could find a operator like member or -// friend and uses it. If not it doesn't find the operator or if the operator at -// global scope is defined after this template, the template won't be -// instantiated due to SFINAE. Once the template is not instantiated it can look -// for global operator using normal conversions. -#define SFINAE_OP(ret, op) \ - decltype((void)(doctest::detail::declval() \ - op doctest::detail::declval()), \ - ret{}) - -#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ - template \ - DOCTEST_NOINLINE SFINAE_OP(Result, op) operator op(R&& rhs) \ - { \ - bool res = op_macro(doctest::detail::forward(lhs), \ - doctest::detail::forward(rhs)); \ - if (m_at & assertType::is_false) \ - res = !res; \ - if (!res || doctest::getContextOptions()->success) \ - return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ - return Result(res); \ - } - -// more checks could be added - like in Catch: -// https://github.com/catchorg/Catch2/pull/1480/files -// https://github.com/catchorg/Catch2/pull/1481/files -#define DOCTEST_FORBIT_EXPRESSION(rt, op) \ - template \ - rt& operator op(const R&) \ - { \ - static_assert( \ - deferred_false::value, \ - "Expression Too Complex Please Rewrite As Binary Comparison!"); \ - return *this; \ - } - -struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) -{ - bool m_passed; - String m_decomp; - - Result() = default; // TODO: Why do we need this? (To remove NOLINT) - Result(bool passed, const String& decomposition = String()); - - // forbidding some expressions based on this table: - // https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Result, &) - DOCTEST_FORBIT_EXPRESSION(Result, ^) - DOCTEST_FORBIT_EXPRESSION(Result, |) - DOCTEST_FORBIT_EXPRESSION(Result, &&) - DOCTEST_FORBIT_EXPRESSION(Result, ||) - DOCTEST_FORBIT_EXPRESSION(Result, ==) - DOCTEST_FORBIT_EXPRESSION(Result, !=) - DOCTEST_FORBIT_EXPRESSION(Result, <) - DOCTEST_FORBIT_EXPRESSION(Result, >) - DOCTEST_FORBIT_EXPRESSION(Result, <=) - DOCTEST_FORBIT_EXPRESSION(Result, >=) - DOCTEST_FORBIT_EXPRESSION(Result, =) - DOCTEST_FORBIT_EXPRESSION(Result, +=) - DOCTEST_FORBIT_EXPRESSION(Result, -=) - DOCTEST_FORBIT_EXPRESSION(Result, *=) - DOCTEST_FORBIT_EXPRESSION(Result, /=) - DOCTEST_FORBIT_EXPRESSION(Result, %=) - DOCTEST_FORBIT_EXPRESSION(Result, <<=) - DOCTEST_FORBIT_EXPRESSION(Result, >>=) - DOCTEST_FORBIT_EXPRESSION(Result, &=) - DOCTEST_FORBIT_EXPRESSION(Result, ^=) - DOCTEST_FORBIT_EXPRESSION(Result, |=) -}; - -#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - -DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") -// DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") -// DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") -// DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") - -DOCTEST_GCC_SUPPRESS_WARNING_PUSH -DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") -DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") -// DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") -// DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") -// DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") - -DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -// https://stackoverflow.com/questions/39479163 what's the difference between -// 4018 and 4389 -DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch -DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch -DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch -// DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type -// 'type' and type 'type' in operation - -#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - -// clang-format off -#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_COMPARISON_RETURN_TYPE bool -#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type - inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } - inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } - inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } - inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } - inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } - inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -// clang-format on - -#define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ - const DOCTEST_REF_WRAP(R) rhs) \ - { \ - return lhs op rhs; \ - } - -DOCTEST_RELATIONAL_OP(eq, ==) -DOCTEST_RELATIONAL_OP(ne, !=) -DOCTEST_RELATIONAL_OP(lt, <) -DOCTEST_RELATIONAL_OP(gt, >) -DOCTEST_RELATIONAL_OP(le, <=) -DOCTEST_RELATIONAL_OP(ge, >=) - -#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_CMP_EQ(l, r) l == r -#define DOCTEST_CMP_NE(l, r) l != r -#define DOCTEST_CMP_GT(l, r) l > r -#define DOCTEST_CMP_LT(l, r) l < r -#define DOCTEST_CMP_GE(l, r) l >= r -#define DOCTEST_CMP_LE(l, r) l <= r -#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_CMP_EQ(l, r) eq(l, r) -#define DOCTEST_CMP_NE(l, r) ne(l, r) -#define DOCTEST_CMP_GT(l, r) gt(l, r) -#define DOCTEST_CMP_LT(l, r) lt(l, r) -#define DOCTEST_CMP_GE(l, r) ge(l, r) -#define DOCTEST_CMP_LE(l, r) le(l, r) -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - -template -// cppcheck-suppress copyCtorAndEqOperator -struct Expression_lhs -{ - L lhs; - assertType::Enum m_at; - - explicit Expression_lhs(L&& in, assertType::Enum at) - : lhs(static_cast(in)) - , m_at(at) - { - } - - DOCTEST_NOINLINE operator Result() - { - // this is needed only for MSVC 2015 - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH( - 4800) // 'int': forcing value to bool - bool res = static_cast(lhs); - DOCTEST_MSVC_SUPPRESS_WARNING_POP - if (m_at & assertType::is_false) { //! OCLINT bitwise operator in - //! conditional - res = !res; - } - - if (!res || getContextOptions()->success) { - return { res, (DOCTEST_STRINGIFY(lhs)) }; - } - return { res }; - } - - /* This is required for user-defined conversions from Expression_lhs to L */ - operator L() const { return lhs; } - - // clang-format off - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional - // clang-format on - - // forbidding some expressions based on this table: - // https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) - // these 2 are unfortunate because they should be allowed - they have higher - // precedence over the comparisons, but the ExpressionDecomposer class uses - // the left shift operator to capture the left operand of the binary - // expression... - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) -}; - -#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - -#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_POP -#endif - -struct DOCTEST_INTERFACE ExpressionDecomposer -{ - assertType::Enum m_at; - - ExpressionDecomposer(assertType::Enum at); - - // The right operator for capturing expressions is "<=" instead of "<<" (based - // on the operator precedence table) but then there will be warnings from GCC - // about "-Wparentheses" and since "_Pragma()" is problematic this will stay - // for now... https://github.com/catchorg/Catch2/issues/870 - // https://github.com/catchorg/Catch2/issues/565 - template - Expression_lhs operator<<(L&& operand) - { - return Expression_lhs(static_cast(operand), m_at); - } - - template::value, - void>::type* = nullptr> - Expression_lhs operator<<(const L& operand) - { - return Expression_lhs(operand, m_at); - } -}; - -struct DOCTEST_INTERFACE TestSuite -{ - const char* m_test_suite = nullptr; - const char* m_description = nullptr; - bool m_skip = false; - bool m_no_breaks = false; - bool m_no_output = false; - bool m_may_fail = false; - bool m_should_fail = false; - int m_expected_failures = 0; - double m_timeout = 0; - - TestSuite& operator*(const char* in); - - template - TestSuite& operator*(const T& in) - { - in.fill(*this); - return *this; - } -}; - -using funcType = void (*)(); - -struct DOCTEST_INTERFACE TestCase : public TestCaseData -{ - funcType m_test; // a function pointer to the test case - - String m_type; // for templated test cases - gets appended to the real name - int m_template_id; // an ID used to distinguish between the different versions - // of a templated test case - String m_full_name; // contains the name (only for templated test cases!) + - // the template type - - TestCase(funcType test, - const char* file, - unsigned line, - const TestSuite& test_suite, - const String& type = String(), - int template_id = -1); - - TestCase(const TestCase& other); - TestCase(TestCase&&) = delete; - - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& operator=(const TestCase& other); - DOCTEST_MSVC_SUPPRESS_WARNING_POP - - TestCase& operator=(TestCase&&) = delete; - - TestCase& operator*(const char* in); - - template - TestCase& operator*(const T& in) - { - in.fill(*this); - return *this; - } - - bool operator<(const TestCase& other) const; - - ~TestCase() = default; -}; - -// forward declarations of functions used by the macros -DOCTEST_INTERFACE int -regTest(const TestCase& tc); -DOCTEST_INTERFACE int -setTestSuite(const TestSuite& ts); -DOCTEST_INTERFACE bool -isDebuggerActive(); - -template -int -instantiationHelper(const T&) -{ - return 0; -} - -namespace binaryAssertComparison { -enum Enum -{ - eq = 0, - ne, - gt, - lt, - ge, - le -}; -} // namespace binaryAssertComparison - -// clang-format off - template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } }; - -#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \ - template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; -// clang-format on - -DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) -DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) -DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) -DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) -DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) -DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) - -struct DOCTEST_INTERFACE ResultBuilder : public AssertData -{ - ResultBuilder(assertType::Enum at, - const char* file, - int line, - const char* expr, - const char* exception_type = "", - const String& exception_string = ""); - - ResultBuilder(assertType::Enum at, - const char* file, - int line, - const char* expr, - const char* exception_type, - const Contains& exception_string); - - void setResult(const Result& res); - - template - DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) - { - m_failed = !RelationalComparator()(lhs, rhs); - if (m_failed || getContextOptions()->success) { - m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); - } - return !m_failed; - } - - template - DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) - { - m_failed = !val; - - if (m_at & assertType::is_false) { //! OCLINT bitwise operator in - //! conditional - m_failed = !m_failed; - } - - if (m_failed || getContextOptions()->success) { - m_decomp = (DOCTEST_STRINGIFY(val)); - } - - return !m_failed; - } - - void translateException(); - - bool log(); - void react() const; -}; - -namespace assertAction { -enum Enum -{ - nothing = 0, - dbgbreak = 1, - shouldthrow = 2 -}; -} // namespace assertAction - -DOCTEST_INTERFACE void -failed_out_of_a_testing_context(const AssertData& ad); - -DOCTEST_INTERFACE bool -decomp_assert(assertType::Enum at, - const char* file, - int line, - const char* expr, - const Result& result); - -#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ - do { \ - if (!is_running_in_test) { \ - if (failed) { \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - rb.m_decomp = decomp; \ - failed_out_of_a_testing_context(rb); \ - if (isDebuggerActive() && !getContextOptions()->no_breaks) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if (checkIfShouldThrow(at)) \ - throwException(); \ - } \ - return !failed; \ - } \ - } while (false) - -#define DOCTEST_ASSERT_IN_TESTS(decomp) \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - if (rb.m_failed || getContextOptions()->success) \ - rb.m_decomp = decomp; \ - if (rb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if (rb.m_failed && checkIfShouldThrow(at)) \ - throwException() - -template -DOCTEST_NOINLINE bool -binary_assert(assertType::Enum at, - const char* file, - int line, - const char* expr, - const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) -{ - bool failed = !RelationalComparator()(lhs, rhs); - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE - // FAILING ASSERT THIS IS THE EFFECT OF HAVING - // 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - return !failed; -} - -template -DOCTEST_NOINLINE bool -unary_assert(assertType::Enum at, - const char* file, - int line, - const char* expr, - const DOCTEST_REF_WRAP(L) val) -{ - bool failed = !val; - - if (at & assertType::is_false) //! OCLINT bitwise operator in conditional - failed = !failed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE - // FAILING ASSERT THIS IS THE EFFECT OF HAVING - // 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); - DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); - return !failed; -} - -struct DOCTEST_INTERFACE IExceptionTranslator -{ - DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) - virtual bool translate(String&) const = 0; -}; - -template -class ExceptionTranslator - : public IExceptionTranslator //! OCLINT destructor of virtual class -{ -public: - explicit ExceptionTranslator(String (*translateFunction)(T)) - : m_translateFunction(translateFunction) - { - } - - bool translate(String& res) const override - { -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { - throw; // lgtm [cpp/rethrow-no-exception] - // cppcheck-suppress catchExceptionByValue - } catch (const T& ex) { - res = m_translateFunction(ex); //! OCLINT parameter reassignment - return true; - } catch (...) { - } //! OCLINT - empty catch statement -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - static_cast(res); // to silence -Wunused-parameter - return false; - } - -private: - String (*m_translateFunction)(T); -}; - -DOCTEST_INTERFACE void -registerExceptionTranslatorImpl(const IExceptionTranslator* et); - -// ContextScope base class used to allow implementing methods of ContextScope -// that don't depend on the template parameter in doctest.cpp. -struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope -{ - ContextScopeBase(const ContextScopeBase&) = delete; - - ContextScopeBase& operator=(const ContextScopeBase&) = delete; - ContextScopeBase& operator=(ContextScopeBase&&) = delete; - - ~ContextScopeBase() override = default; - -protected: - ContextScopeBase(); - ContextScopeBase(ContextScopeBase&& other) noexcept; - - void destroy(); - bool need_to_destroy{ true }; -}; - -template -class ContextScope : public ContextScopeBase -{ - L lambda_; - -public: - explicit ContextScope(const L& lambda) - : lambda_(lambda) - { - } - explicit ContextScope(L&& lambda) - : lambda_(static_cast(lambda)) - { - } - - ContextScope(const ContextScope&) = delete; - ContextScope(ContextScope&&) noexcept = default; - - ContextScope& operator=(const ContextScope&) = delete; - ContextScope& operator=(ContextScope&&) = delete; - - void stringify(std::ostream* s) const override { lambda_(s); } - - ~ContextScope() override - { - if (need_to_destroy) { - destroy(); - } - } -}; - -struct DOCTEST_INTERFACE MessageBuilder : public MessageData -{ - std::ostream* m_stream; - bool logged = false; - - MessageBuilder(const char* file, int line, assertType::Enum severity); - - MessageBuilder(const MessageBuilder&) = delete; - MessageBuilder(MessageBuilder&&) = delete; - - MessageBuilder& operator=(const MessageBuilder&) = delete; - MessageBuilder& operator=(MessageBuilder&&) = delete; - - ~MessageBuilder(); - - // the preferred way of chaining parameters for stringification - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) - template - MessageBuilder& operator,(const T& in) - { - *m_stream << (DOCTEST_STRINGIFY(in)); - return *this; - } - DOCTEST_MSVC_SUPPRESS_WARNING_POP - - // kept here just for backwards-compatibility - the comma operator should be - // preferred now - template - MessageBuilder& operator<<(const T& in) - { - return this->operator,(in); - } - - // the `,` operator has the lowest operator precedence - if `<<` is used by - // the user then the `,` operator will be called last which is not what we - // want and thus the `*` operator is used first (has higher operator - // precedence compared to `<<`) so that we guarantee that an operator of the - // MessageBuilder class is called first before the rest of the parameters - template - MessageBuilder& operator*(const T& in) - { - return this->operator,(in); - } - - bool log(); - void react(); -}; - -template -ContextScope -MakeContextScope(const L& lambda) -{ - return ContextScope(lambda); -} -} // namespace detail - -#define DOCTEST_DEFINE_DECORATOR(name, type, def) \ - struct name \ - { \ - type data; \ - name(type in = def) \ - : data(in) \ - { \ - } \ - void fill(detail::TestCase& state) const \ - { \ - state.DOCTEST_CAT(m_, name) = data; \ - } \ - void fill(detail::TestSuite& state) const \ - { \ - state.DOCTEST_CAT(m_, name) = data; \ - } \ - } - -DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); -DOCTEST_DEFINE_DECORATOR(description, const char*, ""); -DOCTEST_DEFINE_DECORATOR(skip, bool, true); -DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); -DOCTEST_DEFINE_DECORATOR(no_output, bool, true); -DOCTEST_DEFINE_DECORATOR(timeout, double, 0); -DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); - -template -int -registerExceptionTranslator(String (*translateFunction)(T)) -{ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") - static detail::ExceptionTranslator exceptionTranslator(translateFunction); - DOCTEST_CLANG_SUPPRESS_WARNING_POP - detail::registerExceptionTranslatorImpl(&exceptionTranslator); - return 0; -} - -} // namespace doctest - -// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE -// macro introduces an anonymous namespace in which getCurrentTestSuite gets -// overridden -namespace doctest_detail_test_suite_ns { -DOCTEST_INTERFACE doctest::detail::TestSuite& -getCurrentTestSuite(); -} // namespace doctest_detail_test_suite_ns - -namespace doctest { -#else // DOCTEST_CONFIG_DISABLE -template -int -registerExceptionTranslator(String (*)(T)) -{ - return 0; -} -#endif // DOCTEST_CONFIG_DISABLE - -namespace detail { -using assert_handler = void (*)(const AssertData&); -struct ContextState; -} // namespace detail - -class DOCTEST_INTERFACE Context -{ - detail::ContextState* p; - - void parseArgs(int argc, const char* const* argv, bool withDefaults = false); - -public: - explicit Context(int argc = 0, const char* const* argv = nullptr); - - Context(const Context&) = delete; - Context(Context&&) = delete; - - Context& operator=(const Context&) = delete; - Context& operator=(Context&&) = delete; - - ~Context(); // NOLINT(performance-trivially-destructible) - - void applyCommandLine(int argc, const char* const* argv); - - void addFilter(const char* filter, const char* value); - void clearFilters(); - void setOption(const char* option, bool value); - void setOption(const char* option, int value); - void setOption(const char* option, const char* value); - - bool shouldExit(); - - void setAsDefaultForAssertsOutOfTestCases(); - - void setAssertHandler(detail::assert_handler ah); - - void setCout(std::ostream* out); - - int run(); -}; - -namespace TestCaseFailureReason { -enum Enum -{ - None = 0, - AssertFailure = 1, // an assertion has failed in the test case - Exception = 2, // test case threw an exception - Crash = 4, // a crash... - TooManyFailedAsserts = 8, // the abort-after option - Timeout = 16, // see the timeout decorator - ShouldHaveFailedButDidnt = 32, // see the should_fail decorator - ShouldHaveFailedAndDid = 64, // see the should_fail decorator - DidntFailExactlyNumTimes = 128, // see the expected_failures decorator - FailedExactlyNumTimes = 256, // see the expected_failures decorator - CouldHaveFailedAndDid = 512 // see the may_fail decorator -}; -} // namespace TestCaseFailureReason - -struct DOCTEST_INTERFACE CurrentTestCaseStats -{ - int numAssertsCurrentTest; - int numAssertsFailedCurrentTest; - double seconds; - int failure_flags; // use TestCaseFailureReason::Enum - bool testCaseSuccess; -}; - -struct DOCTEST_INTERFACE TestCaseException -{ - String error_string; - bool is_crash; -}; - -struct DOCTEST_INTERFACE TestRunStats -{ - unsigned numTestCases; - unsigned numTestCasesPassingFilters; - unsigned numTestSuitesPassingFilters; - unsigned numTestCasesFailed; - int numAsserts; - int numAssertsFailed; -}; - -struct QueryData -{ - const TestRunStats* run_stats = nullptr; - const TestCaseData** data = nullptr; - unsigned num_data = 0; -}; - -struct DOCTEST_INTERFACE IReporter -{ - // The constructor has to accept "const ContextOptions&" as a single argument - // which has most of the options for the run + a pointer to the stdout stream - // Reporter(const ContextOptions& in) - - // called when a query should be reported (listing test cases, printing the - // version, etc.) - virtual void report_query(const QueryData&) = 0; - - // called when the whole test run starts - virtual void test_run_start() = 0; - // called when the whole test run ends (caching a pointer to the input doesn't - // make sense here) - virtual void test_run_end(const TestRunStats&) = 0; - - // called when a test case is started (safe to cache a pointer to the input) - virtual void test_case_start(const TestCaseData&) = 0; - // called when a test case is reentered because of unfinished subcases (safe - // to cache a pointer to the input) - virtual void test_case_reenter(const TestCaseData&) = 0; - // called when a test case has ended - virtual void test_case_end(const CurrentTestCaseStats&) = 0; - - // called when an exception is thrown from the test case (or it crashes) - virtual void test_case_exception(const TestCaseException&) = 0; - - // called whenever a subcase is entered (don't cache pointers to the input) - virtual void subcase_start(const SubcaseSignature&) = 0; - // called whenever a subcase is exited (don't cache pointers to the input) - virtual void subcase_end() = 0; - - // called for each assert (don't cache pointers to the input) - virtual void log_assert(const AssertData&) = 0; - // called for each message (don't cache pointers to the input) - virtual void log_message(const MessageData&) = 0; - - // called when a test case is skipped either because it doesn't pass the - // filters, has a skip decorator or isn't in the execution range (between - // first and last) (safe to cache a pointer to the input) - virtual void test_case_skipped(const TestCaseData&) = 0; - - DOCTEST_DECLARE_INTERFACE(IReporter) - - // can obtain all currently active contexts and stringify them if one wishes - // to do so - static int get_num_active_contexts(); - static const IContextScope* const* get_active_contexts(); - - // can iterate through contexts which have been stringified automatically in - // their destructors when an exception has been thrown - static int get_num_stringified_contexts(); - static const String* get_stringified_contexts(); -}; - -namespace detail { -using reporterCreatorFunc = IReporter* (*)(const ContextOptions&); - -DOCTEST_INTERFACE void -registerReporterImpl(const char* name, - int prio, - reporterCreatorFunc c, - bool isReporter); - -template -IReporter* -reporterCreator(const ContextOptions& o) -{ - return new Reporter(o); -} -} // namespace detail - -template -int -registerReporter(const char* name, int priority, bool isReporter) -{ - detail::registerReporterImpl( - name, priority, detail::reporterCreator, isReporter); - return 0; -} -} // namespace doctest - -#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES -#define DOCTEST_FUNC_EMPTY [] { return false; }() -#else -#define DOCTEST_FUNC_EMPTY (void)0 -#endif - -// if registering is not disabled -#ifndef DOCTEST_CONFIG_DISABLE - -#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES -#define DOCTEST_FUNC_SCOPE_BEGIN [&] -#define DOCTEST_FUNC_SCOPE_END () -#define DOCTEST_FUNC_SCOPE_RET(v) return v -#else -#define DOCTEST_FUNC_SCOPE_BEGIN do -#define DOCTEST_FUNC_SCOPE_END while (false) -#define DOCTEST_FUNC_SCOPE_RET(v) (void)0 -#endif - -// common code in asserts - for convenience -#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ - if (b.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - b.react(); \ - DOCTEST_FUNC_SCOPE_RET(!b.m_failed) - -#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS -#define DOCTEST_WRAP_IN_TRY(x) x; -#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS -#define DOCTEST_WRAP_IN_TRY(x) \ - try { \ - x; \ - } catch (...) { \ - DOCTEST_RB.translateException(); \ - } -#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS - -#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS -#define DOCTEST_CAST_TO_VOID(...) \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ - static_cast(__VA_ARGS__); \ - DOCTEST_GCC_SUPPRESS_WARNING_POP -#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS -#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; -#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS - -// registers the test by initializing a dummy var with a function -#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ - global_prefix DOCTEST_GLOBAL_NO_WARNINGS( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ - doctest::detail::regTest( \ - doctest::detail::TestCase( \ - f, \ - __FILE__, \ - __LINE__, \ - doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ - decorators)) - -#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ - namespace { /* NOLINT */ \ - struct der : public base \ - { \ - void f(); \ - }; \ - static inline DOCTEST_NOINLINE void func() \ - { \ - der v; \ - v.f(); \ - } \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ - } \ - inline DOCTEST_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) - -#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \ - static void f(); \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ - static void f() - -#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ - static doctest::detail::funcType proxy() \ - { \ - return f; \ - } \ - DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ - static void f() - -// for registering tests -#define DOCTEST_TEST_CASE(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - decorators) - -// for registering tests in classes - requires C++17 for inline variables! -#if DOCTEST_CPLUSPLUS >= 201703L -#define DOCTEST_TEST_CASE_CLASS(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ - decorators) -#else // DOCTEST_TEST_CASE_CLASS -#define DOCTEST_TEST_CASE_CLASS(...) \ - TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER -#endif // DOCTEST_TEST_CASE_CLASS - -// for registering tests with a fixture -#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), \ - c, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - decorators) - -// for converting types to strings without the header and demangling -#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \ - namespace doctest { \ - template<> \ - inline String toString<__VA_ARGS__>() \ - { \ - return str; \ - } \ - } \ - static_assert(true, "") - -#define DOCTEST_TYPE_TO_STRING(...) \ - DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__) - -#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ - template \ - static void func(); \ - namespace { /* NOLINT */ \ - template \ - struct iter; \ - template \ - struct iter> \ - { \ - iter(const char* file, unsigned line, int index) \ - { \ - doctest::detail::regTest( \ - doctest::detail::TestCase( \ - func, \ - file, \ - line, \ - doctest_detail_test_suite_ns::getCurrentTestSuite(), \ - doctest::toString(), \ - int(line) * 1000 + index) * \ - dec); \ - iter>(file, line, index + 1); \ - } \ - }; \ - template<> \ - struct iter> \ - { \ - iter(const char*, unsigned, int) {} \ - }; \ - } \ - template \ - static void func() - -#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL( \ - dec, T, DOCTEST_CAT(id, ITERATOR), DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) - -#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ - DOCTEST_GLOBAL_NO_WARNINGS( \ - DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, \ - fuchsia-statically-constructed-objects) */ \ - doctest::detail::instantiationHelper( \ - DOCTEST_CAT(id, ITERATOR) < __VA_ARGS__ > (__FILE__, __LINE__, 0))) - -#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL( \ - id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ - static_assert(true, "") - -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL( \ - id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ - static_assert(true, "") - -#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL( \ - dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL( \ - anon, anon, std::tuple<__VA_ARGS__>) \ - template \ - static void anon() - -#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_IMPL( \ - dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) - -// for subcases -#define DOCTEST_SUBCASE(name) \ - if (const doctest::detail::Subcase& DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) \ - DOCTEST_UNUSED = doctest::detail::Subcase(name, __FILE__, __LINE__)) - -// for grouping tests in test suites by using code blocks -#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \ - namespace ns_name { \ - namespace doctest_detail_test_suite_ns { \ - static DOCTEST_NOINLINE doctest::detail::TestSuite& \ - getCurrentTestSuite() noexcept \ - { \ - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ - static doctest::detail::TestSuite data{}; \ - static bool inited = false; \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - if (!inited) { \ - data* decorators; \ - inited = true; \ - } \ - return data; \ - } \ - } \ - } \ - namespace ns_name - -#define DOCTEST_TEST_SUITE(decorators) \ - DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) - -// for starting a testsuite block -#define DOCTEST_TEST_SUITE_BEGIN(decorators) \ - DOCTEST_GLOBAL_NO_WARNINGS( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ - static_assert(true, "") - -// for ending a testsuite block -#define DOCTEST_TEST_SUITE_END \ - DOCTEST_GLOBAL_NO_WARNINGS( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ - using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int - -// for registering exception translators -#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ - inline doctest::String translatorName(signature); \ - DOCTEST_GLOBAL_NO_WARNINGS( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerExceptionTranslator(translatorName)) \ - doctest::String translatorName(signature) - -#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), signature) - -// for registering reporters -#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, true)) \ - static_assert(true, "") - -// for registering listeners -#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS( \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, false)) \ - static_assert(true, "") - -// clang-format off -// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 -#define DOCTEST_INFO(...) \ - DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \ - DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \ - __VA_ARGS__) -// clang-format on - -#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ - auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = \ - doctest::detail::MakeContextScope([&](std::ostream* s_name) { \ - doctest::detail::MessageBuilder mb_name( \ - __FILE__, __LINE__, doctest::assertType::is_warn); \ - mb_name.m_stream = s_name; \ - mb_name* __VA_ARGS__; \ - }) - -#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) - -#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN \ - { \ - doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ - mb* __VA_ARGS__; \ - if (mb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - mb.react(); \ - } \ - DOCTEST_FUNC_SCOPE_END - -// clang-format off -#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) -#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) -// clang-format on - -#define DOCTEST_MESSAGE(...) \ - DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) -#define DOCTEST_FAIL_CHECK(...) \ - DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) -#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) - -#define DOCTEST_TO_LVALUE(...) \ - __VA_ARGS__ // Not removed to keep backwards compatibility. - -#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH( \ - "-Woverloaded-shift-op-parentheses") \ - /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ - doctest::detail::ResultBuilder DOCTEST_RB( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) \ - */ \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP - -#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN \ - { \ - DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ - } \ - DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - -#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN \ - { \ - doctest::detail::ResultBuilder DOCTEST_RB( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY( \ - DOCTEST_RB.binary_assert( \ - __VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } \ - DOCTEST_FUNC_SCOPE_END - -#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN \ - { \ - doctest::detail::ResultBuilder DOCTEST_RB( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } \ - DOCTEST_FUNC_SCOPE_END - -#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -// necessary for _MESSAGE -#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 - -#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH( \ - "-Woverloaded-shift-op-parentheses") \ - doctest::detail::decomp_assert( \ - doctest::assertType::assert_type, \ - __FILE__, \ - __LINE__, \ - #__VA_ARGS__, \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP - -#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \ - doctest::detail::binary_assert< \ - doctest::detail::binaryAssertComparison::comparison>( \ - doctest::assertType::assert_type, \ - __FILE__, \ - __LINE__, \ - #__VA_ARGS__, \ - __VA_ARGS__) - -#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - doctest::detail::unary_assert(doctest::assertType::assert_type, \ - __FILE__, \ - __LINE__, \ - #__VA_ARGS__, \ - __VA_ARGS__) - -#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) -#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) -#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) -#define DOCTEST_WARN_FALSE(...) \ - DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_FALSE(...) \ - DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) -#define DOCTEST_REQUIRE_FALSE(...) \ - DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) - -// clang-format off -#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END -// clang-format on - -#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) -#define DOCTEST_CHECK_EQ(...) \ - DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) -#define DOCTEST_REQUIRE_EQ(...) \ - DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__) -#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) -#define DOCTEST_CHECK_NE(...) \ - DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) -#define DOCTEST_REQUIRE_NE(...) \ - DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__) -#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) -#define DOCTEST_CHECK_GT(...) \ - DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) -#define DOCTEST_REQUIRE_GT(...) \ - DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__) -#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) -#define DOCTEST_CHECK_LT(...) \ - DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) -#define DOCTEST_REQUIRE_LT(...) \ - DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__) -#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) -#define DOCTEST_CHECK_GE(...) \ - DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) -#define DOCTEST_REQUIRE_GE(...) \ - DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__) -#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) -#define DOCTEST_CHECK_LE(...) \ - DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) -#define DOCTEST_REQUIRE_LE(...) \ - DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__) - -#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY(...) \ - DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) -#define DOCTEST_REQUIRE_UNARY(...) \ - DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) -#define DOCTEST_WARN_UNARY_FALSE(...) \ - DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY_FALSE(...) \ - DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) -#define DOCTEST_REQUIRE_UNARY_FALSE(...) \ - DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - -#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN \ - { \ - if (!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB( \ - doctest::assertType::assert_type, \ - __FILE__, \ - __LINE__, \ - #expr, \ - #__VA_ARGS__, \ - message); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch (const typename doctest::detail::types::remove_const< \ - typename doctest::detail::types::remove_reference< \ - __VA_ARGS__>::type>::type&) { \ - DOCTEST_RB.translateException(); \ - DOCTEST_RB.m_threw_as = true; \ - } catch (...) { \ - DOCTEST_RB.translateException(); \ - } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } \ - DOCTEST_FUNC_SCOPE_END - -#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN \ - { \ - if (!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB( \ - doctest::assertType::assert_type, \ - __FILE__, \ - __LINE__, \ - expr_str, \ - "", \ - __VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch (...) { \ - DOCTEST_RB.translateException(); \ - } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } \ - DOCTEST_FUNC_SCOPE_END - -#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN \ - { \ - doctest::detail::ResultBuilder DOCTEST_RB( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ - } catch (...) { \ - DOCTEST_RB.translateException(); \ - } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } \ - DOCTEST_FUNC_SCOPE_END - -// clang-format off -#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") -#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "") -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "") - -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__) - -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) - -#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__) - -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__) -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END -// clang-format on - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -// ================================================================================================= -// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! == -// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! == -// ================================================================================================= -#else // DOCTEST_CONFIG_DISABLE - -#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ - namespace /* NOLINT */ { \ - template \ - struct der : public base \ - { \ - void f(); \ - }; \ - } \ - template \ - inline void der::f() - -#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ - template \ - static inline void f() - -// for registering tests -#define DOCTEST_TEST_CASE(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - name) - -// for registering tests in classes -#define DOCTEST_TEST_CASE_CLASS(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - name) - -// for registering tests with a fixture -#define DOCTEST_TEST_CASE_FIXTURE(x, name) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), \ - x, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - name) - -// for converting types to strings without the header and demangling -#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "") -#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") - -// for typed tests -#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() - -#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() - -#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") - -// for subcases -#define DOCTEST_SUBCASE(name) - -// for a testsuite block -#define DOCTEST_TEST_SUITE(name) namespace // NOLINT - -// for starting a testsuite block -#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") - -// for ending a testsuite block -#define DOCTEST_TEST_SUITE_END \ - using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int - -#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - template \ - static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)( \ - signature) - -#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) -#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) - -#define DOCTEST_INFO(...) (static_cast(0)) -#define DOCTEST_CAPTURE(x) (static_cast(0)) -#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_MESSAGE(...) (static_cast(0)) -#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) -#define DOCTEST_FAIL(...) (static_cast(0)) - -#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) && \ - defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) - -#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() - -#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() - -namespace doctest { -namespace detail { -#define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) \ - { \ - return lhs op rhs; \ - } - -DOCTEST_RELATIONAL_OP(eq, ==) -DOCTEST_RELATIONAL_OP(ne, !=) -DOCTEST_RELATIONAL_OP(lt, <) -DOCTEST_RELATIONAL_OP(gt, >) -DOCTEST_RELATIONAL_OP(le, <=) -DOCTEST_RELATIONAL_OP(ge, >=) -} // namespace detail -} // namespace doctest - -#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_EQ(...) \ - [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_NE(...) \ - [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LT(...) \ - [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GT(...) \ - [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LE(...) \ - [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GE(...) \ - [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - -#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) \ - [] { \ - static_assert( \ - false, \ - "Exception translation is not available when doctest is disabled."); \ - return false; \ - }() -#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) - -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_WARN_THROWS_WITH(, , ) - -#define DOCTEST_WARN_THROWS(...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return false; \ - } catch (...) { \ - return true; \ - } \ - }() -#define DOCTEST_CHECK_THROWS(...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return false; \ - } catch (...) { \ - return true; \ - } \ - }() -#define DOCTEST_REQUIRE_THROWS(...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return false; \ - } catch (...) { \ - return true; \ - } \ - }() -#define DOCTEST_WARN_THROWS_AS(expr, ...) \ - [&] { \ - try { \ - expr; \ - } catch (__VA_ARGS__) { \ - return true; \ - } catch (...) { \ - } \ - return false; \ - }() -#define DOCTEST_CHECK_THROWS_AS(expr, ...) \ - [&] { \ - try { \ - expr; \ - } catch (__VA_ARGS__) { \ - return true; \ - } catch (...) { \ - } \ - return false; \ - }() -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) \ - [&] { \ - try { \ - expr; \ - } catch (__VA_ARGS__) { \ - return true; \ - } catch (...) { \ - } \ - return false; \ - }() -#define DOCTEST_WARN_NOTHROW(...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return true; \ - } catch (...) { \ - return false; \ - } \ - }() -#define DOCTEST_CHECK_NOTHROW(...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return true; \ - } catch (...) { \ - return false; \ - } \ - }() -#define DOCTEST_REQUIRE_NOTHROW(...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return true; \ - } catch (...) { \ - return false; \ - } \ - }() - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return false; \ - } catch (...) { \ - return true; \ - } \ - }() -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return false; \ - } catch (...) { \ - return true; \ - } \ - }() -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return false; \ - } catch (...) { \ - return true; \ - } \ - }() -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) \ - [&] { \ - try { \ - expr; \ - } catch (__VA_ARGS__) { \ - return true; \ - } catch (...) { \ - } \ - return false; \ - }() -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) \ - [&] { \ - try { \ - expr; \ - } catch (__VA_ARGS__) { \ - return true; \ - } catch (...) { \ - } \ - return false; \ - }() -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) \ - [&] { \ - try { \ - expr; \ - } catch (__VA_ARGS__) { \ - return true; \ - } catch (...) { \ - } \ - return false; \ - }() -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return true; \ - } catch (...) { \ - return false; \ - } \ - }() -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return true; \ - } catch (...) { \ - return false; \ - } \ - }() -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) \ - [&] { \ - try { \ - __VA_ARGS__; \ - return true; \ - } catch (...) { \ - return false; \ - } \ - }() - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED - -#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - -#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED - -#endif // DOCTEST_CONFIG_DISABLE - -#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS - -#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY -#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_EXCEPTION_EMPTY_FUNC \ - [] { \ - static_assert(false, \ - "Exceptions are disabled! " \ - "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if " \ - "you want to compile with exceptions disabled."); \ - return false; \ - }() - -#undef DOCTEST_REQUIRE -#undef DOCTEST_REQUIRE_FALSE -#undef DOCTEST_REQUIRE_MESSAGE -#undef DOCTEST_REQUIRE_FALSE_MESSAGE -#undef DOCTEST_REQUIRE_EQ -#undef DOCTEST_REQUIRE_NE -#undef DOCTEST_REQUIRE_GT -#undef DOCTEST_REQUIRE_LT -#undef DOCTEST_REQUIRE_GE -#undef DOCTEST_REQUIRE_LE -#undef DOCTEST_REQUIRE_UNARY -#undef DOCTEST_REQUIRE_UNARY_FALSE - -#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS - -#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -// clang-format off -// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS -#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ -#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ -#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ -#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE -#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE -#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE -#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT -#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT -#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT -#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT -#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT -#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT -#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE -#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE -#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE -#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE -#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE -#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE - -#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY -#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY -#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY -#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE -#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE -#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE - -#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__) -// clang-format on - -// BDD style macros -// clang-format off -#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name) -#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name) -#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__) -#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id) - -#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name) -#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name) -#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name) -#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name) -#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name) -// clang-format on - -// == SHORT VERSIONS OF THE MACROS -#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES - -#define TEST_CASE(name) DOCTEST_TEST_CASE(name) -#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) -#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) -#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) -#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) -#define TEST_CASE_TEMPLATE(name, T, ...) \ - DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) -#define TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_APPLY(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) -#define SUBCASE(name) DOCTEST_SUBCASE(name) -#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) -#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) -#define TEST_SUITE_END DOCTEST_TEST_SUITE_END -#define REGISTER_EXCEPTION_TRANSLATOR(signature) \ - DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) -#define REGISTER_REPORTER(name, priority, reporter) \ - DOCTEST_REGISTER_REPORTER(name, priority, reporter) -#define REGISTER_LISTENER(name, priority, reporter) \ - DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define INFO(...) DOCTEST_INFO(__VA_ARGS__) -#define CAPTURE(x) DOCTEST_CAPTURE(x) -#define ADD_MESSAGE_AT(file, line, ...) \ - DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) -#define ADD_FAIL_CHECK_AT(file, line, ...) \ - DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) -#define ADD_FAIL_AT(file, line, ...) \ - DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) -#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) -#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) -#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) -#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) - -#define WARN(...) DOCTEST_WARN(__VA_ARGS__) -#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) -#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) -#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) -#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) -#define WARN_THROWS_WITH_AS(expr, with, ...) \ - DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) -#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) -#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) -#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) -#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) -#define CHECK_THROWS_WITH(expr, ...) \ - DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) -#define CHECK_THROWS_WITH_AS(expr, with, ...) \ - DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) -#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) -#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) -#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) -#define REQUIRE_THROWS_AS(expr, ...) \ - DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH(expr, ...) \ - DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS(expr, with, ...) \ - DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) - -#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) -#define WARN_FALSE_MESSAGE(cond, ...) \ - DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) -#define WARN_THROWS_MESSAGE(expr, ...) \ - DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) -#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) \ - DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define WARN_NOTHROW_MESSAGE(expr, ...) \ - DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) -#define CHECK_FALSE_MESSAGE(cond, ...) \ - DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) -#define CHECK_THROWS_MESSAGE(expr, ...) \ - DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) -#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) \ - DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define CHECK_NOTHROW_MESSAGE(expr, ...) \ - DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) -#define REQUIRE_FALSE_MESSAGE(cond, ...) \ - DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) -#define REQUIRE_THROWS_MESSAGE(expr, ...) \ - DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) \ - DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) \ - DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ - DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define REQUIRE_NOTHROW_MESSAGE(expr, ...) \ - DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) - -#define SCENARIO(name) DOCTEST_SCENARIO(name) -#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) -#define SCENARIO_TEMPLATE(name, T, ...) \ - DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) -#define SCENARIO_TEMPLATE_DEFINE(name, T, id) \ - DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) -#define GIVEN(name) DOCTEST_GIVEN(name) -#define WHEN(name) DOCTEST_WHEN(name) -#define AND_WHEN(name) DOCTEST_AND_WHEN(name) -#define THEN(name) DOCTEST_THEN(name) -#define AND_THEN(name) DOCTEST_AND_THEN(name) - -#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) -#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) -#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) -#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) -#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) -#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) -#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) -#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) -#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) -#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) -#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) -#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) -#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) -#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) -#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) -#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) -#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) -#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) -#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) -#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) -#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) -#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) -#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) -#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) - -// KEPT FOR BACKWARDS COMPATIBILITY -#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) -#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) -#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) -#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) -#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) -#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) -#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) -#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) -#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) -#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) -#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) -#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) -#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) -#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) -#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) -#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) -#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) -#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) - -#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) -#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) -#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) -#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) -#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) -#define FAST_REQUIRE_UNARY_FALSE(...) \ - DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) - -#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) - -#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES - -#ifndef DOCTEST_CONFIG_DISABLE - -// this is here to clear the 'current test suite' for the current translation -// unit - at the top -DOCTEST_TEST_SUITE_END(); - -#endif // DOCTEST_CONFIG_DISABLE - -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_POP - -#endif // DOCTEST_LIBRARY_INCLUDED - -#ifndef DOCTEST_SINGLE_HEADER -#define DOCTEST_SINGLE_HEADER -#endif // DOCTEST_SINGLE_HEADER - -#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER) - -#ifndef DOCTEST_SINGLE_HEADER -#include "doctest_fwd.h" -#endif // DOCTEST_SINGLE_HEADER - -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros") - -#ifndef DOCTEST_LIBRARY_IMPLEMENTATION -#define DOCTEST_LIBRARY_IMPLEMENTATION - -DOCTEST_CLANG_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH - -DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path") - -DOCTEST_GCC_SUPPRESS_WARNING_PUSH -DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") -DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces") -DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch") -DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum") -DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default") -DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations") -DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast") -DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance") -DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute") - -DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -DOCTEST_MSVC_SUPPRESS_WARNING( - 4267) // 'var' : conversion from 'x' to 'y', possible loss of data -DOCTEST_MSVC_SUPPRESS_WARNING( - 4530) // C++ exception handler used, but unwind semantics not enabled -DOCTEST_MSVC_SUPPRESS_WARNING( - 4577) // 'noexcept' used with no exception handling mode specified -DOCTEST_MSVC_SUPPRESS_WARNING( - 4774) // format string expected in argument is not a string literal -DOCTEST_MSVC_SUPPRESS_WARNING( - 4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch -DOCTEST_MSVC_SUPPRESS_WARNING( - 5039) // pointer to potentially throwing function passed to extern C -DOCTEST_MSVC_SUPPRESS_WARNING( - 4800) // forcing value to bool 'true' or 'false' (performance warning) -DOCTEST_MSVC_SUPPRESS_WARNING( - 5245) // unreferenced function with internal linkage has been removed - -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN - -// required includes - will go only in one translation unit! -#include -#include -#include -// borland (Embarcadero) compiler requires math.h and not cmath - -// https://github.com/doctest/doctest/pull/37 -#ifdef __BORLANDC__ -#include -#endif // __BORLANDC__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef DOCTEST_CONFIG_NO_MULTITHREADING -#include -#include -#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; -#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name) -#define DOCTEST_LOCK_MUTEX(name) \ - std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); -#else // DOCTEST_CONFIG_NO_MULTITHREADING -#define DOCTEST_DECLARE_MUTEX(name) -#define DOCTEST_DECLARE_STATIC_MUTEX(name) -#define DOCTEST_LOCK_MUTEX(name) -#endif // DOCTEST_CONFIG_NO_MULTITHREADING -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DOCTEST_PLATFORM_MAC -#include -#include -#include -#endif // DOCTEST_PLATFORM_MAC - -#ifdef DOCTEST_PLATFORM_WINDOWS - -// defines for a leaner windows.h -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif // WIN32_LEAN_AND_MEAN -#ifndef NOMINMAX -#define NOMINMAX -#endif // NOMINMAX - -// not sure what AfxWin.h is for - here I do what Catch does -#ifdef __AFXDLL -#include -#else -#include -#endif -#include - -#else // DOCTEST_PLATFORM_WINDOWS - -#include -#include - -#endif // DOCTEST_PLATFORM_WINDOWS - -// this is a fix for https://github.com/doctest/doctest/issues/348 -// https://mail.gnome.org/archives/xml/2012-January/msg00000.html -#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO) -#define STDOUT_FILENO fileno(stdout) -#endif // HAVE_UNISTD_H - -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END - -// counts the number of elements in a C array -#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0])) - -#ifdef DOCTEST_CONFIG_DISABLE -#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled -#else // DOCTEST_CONFIG_DISABLE -#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled -#endif // DOCTEST_CONFIG_DISABLE - -#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX -#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-" -#endif - -#ifndef DOCTEST_THREAD_LOCAL -#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || \ - DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_THREAD_LOCAL -#else // DOCTEST_MSVC -#define DOCTEST_THREAD_LOCAL thread_local -#endif // DOCTEST_MSVC -#endif // DOCTEST_THREAD_LOCAL - -#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES -#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32 -#endif - -#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE -#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64 -#endif - -#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS -#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX -#else -#define DOCTEST_OPTIONS_PREFIX_DISPLAY "" -#endif - -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS -#endif - -#ifndef DOCTEST_CDECL -#define DOCTEST_CDECL __cdecl -#endif - -namespace doctest { - -bool is_running_in_test = false; - -namespace { -using namespace detail; - -template -DOCTEST_NORETURN void -throw_exception(Ex const& e) -{ -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - throw e; -#else // DOCTEST_CONFIG_NO_EXCEPTIONS - std::cerr - << "doctest will terminate because it needed to throw an exception.\n" - << "The message was: " << e.what() << '\n'; - std::terminate(); -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -} - -#ifndef DOCTEST_INTERNAL_ERROR -#define DOCTEST_INTERNAL_ERROR(msg) \ - throw_exception(std::logic_error( \ - __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) -#endif // DOCTEST_INTERNAL_ERROR - -// case insensitive strcmp -int -stricmp(const char* a, const char* b) -{ - for (;; a++, b++) { - const int d = tolower(*a) - tolower(*b); - if (d != 0 || !*a) - return d; - } -} - -struct Endianness -{ - enum Arch - { - Big, - Little - }; - - static Arch which() - { - int x = 1; - // casting any data pointer to char* is allowed - auto ptr = reinterpret_cast(&x); - if (*ptr) - return Little; - return Big; - } -}; -} // namespace - -namespace detail { -DOCTEST_THREAD_LOCAL class -{ - std::vector stack; - std::stringstream ss; - -public: - std::ostream* push() - { - stack.push_back(ss.tellp()); - return &ss; - } - - String pop() - { - if (stack.empty()) - DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); - - std::streampos pos = stack.back(); - stack.pop_back(); - unsigned sz = static_cast(ss.tellp() - pos); - ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); - return String(ss, sz); - } -} g_oss; - -std::ostream* -tlssPush() -{ - return g_oss.push(); -} - -String -tlssPop() -{ - return g_oss.pop(); -} - -#ifndef DOCTEST_CONFIG_DISABLE - -namespace timer_large_integer { - -#if defined(DOCTEST_PLATFORM_WINDOWS) -using type = ULONGLONG; -#else // DOCTEST_PLATFORM_WINDOWS -using type = std::uint64_t; -#endif // DOCTEST_PLATFORM_WINDOWS -} - -using ticks_t = timer_large_integer::type; - -#ifdef DOCTEST_CONFIG_GETCURRENTTICKS -ticks_t -getCurrentTicks() -{ - return DOCTEST_CONFIG_GETCURRENTTICKS(); -} -#elif defined(DOCTEST_PLATFORM_WINDOWS) -ticks_t -getCurrentTicks() -{ - static LARGE_INTEGER hz = { { 0 } }, hzo = { { 0 } }; - if (!hz.QuadPart) { - QueryPerformanceFrequency(&hz); - QueryPerformanceCounter(&hzo); - } - LARGE_INTEGER t; - QueryPerformanceCounter(&t); - return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; -} -#else // DOCTEST_PLATFORM_WINDOWS -ticks_t -getCurrentTicks() -{ - timeval t; - gettimeofday(&t, nullptr); - return static_cast(t.tv_sec) * 1000000 + - static_cast(t.tv_usec); -} -#endif // DOCTEST_PLATFORM_WINDOWS - -struct Timer -{ - void start() { m_ticks = getCurrentTicks(); } - unsigned int getElapsedMicroseconds() const - { - return static_cast(getCurrentTicks() - m_ticks); - } - // unsigned int getElapsedMilliseconds() const { - // return static_cast(getElapsedMicroseconds() / 1000); - // } - double getElapsedSeconds() const - { - return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; - } - -private: - ticks_t m_ticks = 0; -}; - -#ifdef DOCTEST_CONFIG_NO_MULTITHREADING -template -using Atomic = T; -#else // DOCTEST_CONFIG_NO_MULTITHREADING -template -using Atomic = std::atomic; -#endif // DOCTEST_CONFIG_NO_MULTITHREADING - -#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || \ - defined(DOCTEST_CONFIG_NO_MULTITHREADING) -template -using MultiLaneAtomic = Atomic; -#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS -// Provides a multilane implementation of an atomic variable that supports add, -// sub, load, store. Instead of using a single atomic variable, this splits up -// into multiple ones, each sitting on a separate cache line. The goal is to -// provide a speedup when most operations are modifying. It achieves this with -// two properties: -// -// * Multiple atomics are used, so chance of congestion from the same atomic is -// reduced. -// * Each atomic sits on a separate cache line, so false sharing is reduced. -// -// The disadvantage is that there is a small overhead due to the use of TLS, and -// load/store is slower because all atomics have to be accessed. -template -class MultiLaneAtomic -{ - struct CacheLineAlignedAtomic - { - Atomic atomic{}; - char - padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; - }; - CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; - - static_assert(sizeof(CacheLineAlignedAtomic) == - DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, - "guarantee one atomic takes exactly one cache line"); - -public: - T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } - - T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } - - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) - DOCTEST_NOEXCEPT - { - return myAtomic().fetch_add(arg, order); - } - - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) - DOCTEST_NOEXCEPT - { - return myAtomic().fetch_sub(arg, order); - } - - operator T() const DOCTEST_NOEXCEPT { return load(); } - - T load(std::memory_order order = std::memory_order_seq_cst) const - DOCTEST_NOEXCEPT - { - auto result = T(); - for (auto const& c : m_atomics) { - result += c.atomic.load(order); - } - return result; - } - - T operator=(T desired) DOCTEST_NOEXCEPT - { // lgtm [cpp/assignment-does-not-return-this] - store(desired); - return desired; - } - - void store(T desired, std::memory_order order = std::memory_order_seq_cst) - DOCTEST_NOEXCEPT - { - // first value becomes desired", all others become 0. - for (auto& c : m_atomics) { - c.atomic.store(desired, order); - desired = {}; - } - } - -private: - // Each thread has a different atomic that it operates on. If more than - // NumLanes threads use this, some will use the same atomic. So performance - // will degrade a bit, but still everything will work. - // - // The logic here is a bit tricky. The call should be as fast as possible, so - // that there is minimal to no overhead in determining the correct atomic for - // the current thread. - // - // 1. A global static counter laneCounter counts continuously up. - // 2. Each successive thread will use modulo operation of that counter so it - // gets an atomic - // assigned in a round-robin fashion. - // 3. This tlsLaneIdx is stored in the thread local data, so it is directly - // available with - // little overhead. - Atomic& myAtomic() DOCTEST_NOEXCEPT - { - static Atomic laneCounter; - DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = - laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; - - return m_atomics[tlsLaneIdx].atomic; - } -}; -#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS - -// this holds both parameters from the command line and runtime data for tests -struct ContextState - : ContextOptions - , TestRunStats - , CurrentTestCaseStats -{ - MultiLaneAtomic numAssertsCurrentTest_atomic; - MultiLaneAtomic numAssertsFailedCurrentTest_atomic; - - std::vector> filters = - decltype(filters)(9); // 9 different filters - - std::vector reporters_currently_used; - - assert_handler ah = nullptr; - - Timer timer; - - std::vector - stringifiedContexts; // logging from INFO() due to an exception - - // stuff for subcases - bool reachedLeaf; - std::vector subcaseStack; - std::vector nextSubcaseStack; - std::unordered_set fullyTraversedSubcases; - size_t currentSubcaseDepth; - Atomic shouldLogCurrentException; - - void resetRunData() - { - numTestCases = 0; - numTestCasesPassingFilters = 0; - numTestSuitesPassingFilters = 0; - numTestCasesFailed = 0; - numAsserts = 0; - numAssertsFailed = 0; - numAssertsCurrentTest = 0; - numAssertsFailedCurrentTest = 0; - } - - void finalizeTestCaseData() - { - seconds = timer.getElapsedSeconds(); - - // update the non-atomic counters - numAsserts += numAssertsCurrentTest_atomic; - numAssertsFailed += numAssertsFailedCurrentTest_atomic; - numAssertsCurrentTest = numAssertsCurrentTest_atomic; - numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; - - if (numAssertsFailedCurrentTest) - failure_flags |= TestCaseFailureReason::AssertFailure; - - if (Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && - Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) - failure_flags |= TestCaseFailureReason::Timeout; - - if (currentTest->m_should_fail) { - if (failure_flags) { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; - } else { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; - } - } else if (failure_flags && currentTest->m_may_fail) { - failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; - } else if (currentTest->m_expected_failures > 0) { - if (numAssertsFailedCurrentTest == currentTest->m_expected_failures) { - failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; - } else { - failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; - } - } - - bool ok_to_fail = - (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); - - // if any subcase has failed - the whole test case has failed - testCaseSuccess = !(failure_flags && !ok_to_fail); - if (!testCaseSuccess) - numTestCasesFailed++; - } -}; - -ContextState* g_cs = nullptr; - -// used to avoid locks for the debug output -// TODO: figure out if this is indeed necessary/correct - seems like either -// there still could be a race or that there wouldn't be a race even if using -// the context directly -DOCTEST_THREAD_LOCAL bool g_no_colors; - -#endif // DOCTEST_CONFIG_DISABLE -} // namespace detail - -char* -String::allocate(size_type sz) -{ - if (sz <= last) { - buf[sz] = '\0'; - setLast(last - sz); - return buf; - } else { - setOnHeap(); - data.size = sz; - data.capacity = data.size + 1; - data.ptr = new char[data.capacity]; - data.ptr[sz] = '\0'; - return data.ptr; - } -} - -void -String::setOnHeap() noexcept -{ - *reinterpret_cast(&buf[last]) = 128; -} -void -String::setLast(size_type in) noexcept -{ - buf[last] = char(in); -} -void -String::setSize(size_type sz) noexcept -{ - if (isOnStack()) { - buf[sz] = '\0'; - setLast(last - sz); - } else { - data.ptr[sz] = '\0'; - data.size = sz; - } -} - -void -String::copy(const String& other) -{ - if (other.isOnStack()) { - memcpy(buf, other.buf, len); - } else { - memcpy(allocate(other.data.size), other.data.ptr, other.data.size); - } -} - -String::String() noexcept -{ - buf[0] = '\0'; - setLast(); -} - -String::~String() -{ - if (!isOnStack()) - delete[] data.ptr; -} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - -String::String(const char* in) - : String(in, strlen(in)) -{ -} - -String::String(const char* in, size_type in_size) -{ - memcpy(allocate(in_size), in, in_size); -} - -String::String(std::istream& in, size_type in_size) -{ - in.read(allocate(in_size), in_size); -} - -String::String(const String& other) -{ - copy(other); -} - -String& -String::operator=(const String& other) -{ - if (this != &other) { - if (!isOnStack()) - delete[] data.ptr; - - copy(other); - } - - return *this; -} - -String& -String::operator+=(const String& other) -{ - const size_type my_old_size = size(); - const size_type other_size = other.size(); - const size_type total_size = my_old_size + other_size; - if (isOnStack()) { - if (total_size < len) { - // append to the current stack space - memcpy(buf + my_old_size, other.c_str(), other_size + 1); - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - setLast(last - total_size); - } else { - // alloc new chunk - char* temp = new char[total_size + 1]; - // copy current data to new location before writing in the union - memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed - // update data in union - setOnHeap(); - data.size = total_size; - data.capacity = data.size + 1; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } - } else { - if (data.capacity > total_size) { - // append to the current heap block - data.size = total_size; - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } else { - // resize - data.capacity *= 2; - if (data.capacity <= total_size) - data.capacity = total_size + 1; - // alloc new chunk - char* temp = new char[data.capacity]; - // copy current data to new location before releasing it - memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed - // release old chunk - delete[] data.ptr; - // update the rest of the union members - data.size = total_size; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } - } - - return *this; -} - -String::String(String&& other) noexcept -{ - memcpy(buf, other.buf, len); - other.buf[0] = '\0'; - other.setLast(); -} - -String& -String::operator=(String&& other) noexcept -{ - if (this != &other) { - if (!isOnStack()) - delete[] data.ptr; - memcpy(buf, other.buf, len); - other.buf[0] = '\0'; - other.setLast(); - } - return *this; -} - -char -String::operator[](size_type i) const -{ - return const_cast(this)->operator[](i); -} - -char& -String::operator[](size_type i) -{ - if (isOnStack()) - return reinterpret_cast(buf)[i]; - return data.ptr[i]; -} - -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") -String::size_type -String::size() const -{ - if (isOnStack()) - return last - (size_type(buf[last]) & - 31); // using "last" would work only if "len" is 32 - return data.size; -} -DOCTEST_GCC_SUPPRESS_WARNING_POP - -String::size_type -String::capacity() const -{ - if (isOnStack()) - return len; - return data.capacity; -} - -String -String::substr(size_type pos, size_type cnt) && -{ - cnt = std::min(cnt, size() - 1 - pos); - char* cptr = c_str(); - memmove(cptr, cptr + pos, cnt); - setSize(cnt); - return std::move(*this); -} - -String -String::substr(size_type pos, size_type cnt) const& -{ - cnt = std::min(cnt, size() - 1 - pos); - return String{ c_str() + pos, cnt }; -} - -String::size_type -String::find(char ch, size_type pos) const -{ - const char* begin = c_str(); - const char* end = begin + size(); - const char* it = begin + pos; - for (; it < end && *it != ch; it++) - ; - if (it < end) { - return static_cast(it - begin); - } else { - return npos; - } -} - -String::size_type -String::rfind(char ch, size_type pos) const -{ - const char* begin = c_str(); - const char* it = begin + std::min(pos, size() - 1); - for (; it >= begin && *it != ch; it--) - ; - if (it >= begin) { - return static_cast(it - begin); - } else { - return npos; - } -} - -int -String::compare(const char* other, bool no_case) const -{ - if (no_case) - return doctest::stricmp(c_str(), other); - return std::strcmp(c_str(), other); -} - -int -String::compare(const String& other, bool no_case) const -{ - return compare(other.c_str(), no_case); -} - -String -operator+(const String& lhs, const String& rhs) -{ - return String(lhs) += rhs; -} - -bool -operator==(const String& lhs, const String& rhs) -{ - return lhs.compare(rhs) == 0; -} -bool -operator!=(const String& lhs, const String& rhs) -{ - return lhs.compare(rhs) != 0; -} -bool -operator<(const String& lhs, const String& rhs) -{ - return lhs.compare(rhs) < 0; -} -bool -operator>(const String& lhs, const String& rhs) -{ - return lhs.compare(rhs) > 0; -} -bool -operator<=(const String& lhs, const String& rhs) -{ - return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; -} -bool -operator>=(const String& lhs, const String& rhs) -{ - return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; -} - -std::ostream& -operator<<(std::ostream& s, const String& in) -{ - return s << in.c_str(); -} - -Contains::Contains(const String& str) - : string(str) -{ -} - -bool -Contains::checkWith(const String& other) const -{ - return strstr(other.c_str(), string.c_str()) != nullptr; -} - -String -toString(const Contains& in) -{ - return "Contains( " + in.string + " )"; -} - -bool -operator==(const String& lhs, const Contains& rhs) -{ - return rhs.checkWith(lhs); -} -bool -operator==(const Contains& lhs, const String& rhs) -{ - return lhs.checkWith(rhs); -} -bool -operator!=(const String& lhs, const Contains& rhs) -{ - return !rhs.checkWith(lhs); -} -bool -operator!=(const Contains& lhs, const String& rhs) -{ - return !lhs.checkWith(rhs); -} - -namespace { -void -color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) -} // namespace - -namespace Color { -std::ostream& -operator<<(std::ostream& s, Color::Enum code) -{ - color_to_stream(s, code); - return s; -} -} // namespace Color - -// clang-format off -const char* assertString(assertType::Enum at) { - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitely handled - #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type - #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \ - DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \ - DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \ - DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type) - switch(at) { - DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN); - DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK); - DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE); - - default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!"); - } - DOCTEST_MSVC_SUPPRESS_WARNING_POP -} -// clang-format on - -const char* -failureString(assertType::Enum at) -{ - if (at & assertType::is_warn) //! OCLINT bitwise operator in conditional - return "WARNING"; - if (at & assertType::is_check) //! OCLINT bitwise operator in conditional - return "ERROR"; - if (at & assertType::is_require) //! OCLINT bitwise operator in conditional - return "FATAL ERROR"; - return ""; -} - -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -// depending on the current options this will remove the path of filenames -const char* -skipPathFromFilename(const char* file) -{ -#ifndef DOCTEST_CONFIG_DISABLE - if (getContextOptions()->no_path_in_filenames) { - auto back = std::strrchr(file, '\\'); - auto forward = std::strrchr(file, '/'); - if (back || forward) { - if (back > forward) - forward = back; - return forward + 1; - } - } -#endif // DOCTEST_CONFIG_DISABLE - return file; -} -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -bool -SubcaseSignature::operator==(const SubcaseSignature& other) const -{ - return m_line == other.m_line && std::strcmp(m_file, other.m_file) == 0 && - m_name == other.m_name; -} - -bool -SubcaseSignature::operator<(const SubcaseSignature& other) const -{ - if (m_line != other.m_line) - return m_line < other.m_line; - if (std::strcmp(m_file, other.m_file) != 0) - return std::strcmp(m_file, other.m_file) < 0; - return m_name.compare(other.m_name) < 0; -} - -DOCTEST_DEFINE_INTERFACE(IContextScope) - -namespace detail { -void -filldata::fill(std::ostream* stream, const void* in) -{ - if (in) { - *stream << in; - } else { - *stream << "nullptr"; - } -} - -template -String -toStreamLit(T t) -{ - std::ostream* os = tlssPush(); - os->operator<<(t); - return tlssPop(); -} -} - -#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -String -toString(const char* in) -{ - return String("\"") + (in ? in : "{null string}") + "\""; -} -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - -#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: -// https://github.com/doctest/doctest/issues/183 -String -toString(const std::string& in) -{ - return in.c_str(); -} -#endif // VS 2019 - -String -toString(String in) -{ - return in; -} - -String -toString(std::nullptr_t) -{ - return "nullptr"; -} - -String -toString(bool in) -{ - return in ? "true" : "false"; -} - -String -toString(float in) -{ - return toStreamLit(in); -} -String -toString(double in) -{ - return toStreamLit(in); -} -String -toString(double long in) -{ - return toStreamLit(in); -} - -String -toString(char in) -{ - return toStreamLit(static_cast(in)); -} -String -toString(char signed in) -{ - return toStreamLit(static_cast(in)); -} -String -toString(char unsigned in) -{ - return toStreamLit(static_cast(in)); -} -String -toString(short in) -{ - return toStreamLit(in); -} -String -toString(short unsigned in) -{ - return toStreamLit(in); -} -String -toString(signed in) -{ - return toStreamLit(in); -} -String -toString(unsigned in) -{ - return toStreamLit(in); -} -String -toString(long in) -{ - return toStreamLit(in); -} -String -toString(long unsigned in) -{ - return toStreamLit(in); -} -String -toString(long long in) -{ - return toStreamLit(in); -} -String -toString(long long unsigned in) -{ - return toStreamLit(in); -} - -Approx::Approx(double value) - : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) - , m_scale(1.0) - , m_value(value) -{ -} - -Approx -Approx::operator()(double value) const -{ - Approx approx(value); - approx.epsilon(m_epsilon); - approx.scale(m_scale); - return approx; -} - -Approx& -Approx::epsilon(double newEpsilon) -{ - m_epsilon = newEpsilon; - return *this; -} -Approx& -Approx::scale(double newScale) -{ - m_scale = newScale; - return *this; -} - -bool -operator==(double lhs, const Approx& rhs) -{ - // Thanks to Richard Harris for his help refining this formula - return std::fabs(lhs - rhs.m_value) < - rhs.m_epsilon * - (rhs.m_scale + - std::max(std::fabs(lhs), std::fabs(rhs.m_value))); -} -bool -operator==(const Approx& lhs, double rhs) -{ - return operator==(rhs, lhs); -} -bool -operator!=(double lhs, const Approx& rhs) -{ - return !operator==(lhs, rhs); -} -bool -operator!=(const Approx& lhs, double rhs) -{ - return !operator==(rhs, lhs); -} -bool -operator<=(double lhs, const Approx& rhs) -{ - return lhs < rhs.m_value || lhs == rhs; -} -bool -operator<=(const Approx& lhs, double rhs) -{ - return lhs.m_value < rhs || lhs == rhs; -} -bool -operator>=(double lhs, const Approx& rhs) -{ - return lhs > rhs.m_value || lhs == rhs; -} -bool -operator>=(const Approx& lhs, double rhs) -{ - return lhs.m_value > rhs || lhs == rhs; -} -bool -operator<(double lhs, const Approx& rhs) -{ - return lhs < rhs.m_value && lhs != rhs; -} -bool -operator<(const Approx& lhs, double rhs) -{ - return lhs.m_value < rhs && lhs != rhs; -} -bool -operator>(double lhs, const Approx& rhs) -{ - return lhs > rhs.m_value && lhs != rhs; -} -bool -operator>(const Approx& lhs, double rhs) -{ - return lhs.m_value > rhs && lhs != rhs; -} - -String -toString(const Approx& in) -{ - return "Approx( " + doctest::toString(in.m_value) + " )"; -} -const ContextOptions* -getContextOptions() -{ - return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); -} - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) -template -IsNaN:: -operator bool() const -{ - return std::isnan(value) ^ flipped; -} -DOCTEST_MSVC_SUPPRESS_WARNING_POP -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template -String -toString(IsNaN in) -{ - return String(in.flipped ? "! " : "") + "IsNaN( " + - doctest::toString(in.value) + " )"; -} -String -toString(IsNaN in) -{ - return toString(in); -} -String -toString(IsNaN in) -{ - return toString(in); -} -String -toString(IsNaN in) -{ - return toString(in); -} - -} // namespace doctest - -#ifdef DOCTEST_CONFIG_DISABLE -namespace doctest { -Context::Context(int, const char* const*) {} -Context::~Context() = default; -void -Context::applyCommandLine(int, const char* const*) -{ -} -void -Context::addFilter(const char*, const char*) -{ -} -void -Context::clearFilters() -{ -} -void -Context::setOption(const char*, bool) -{ -} -void -Context::setOption(const char*, int) -{ -} -void -Context::setOption(const char*, const char*) -{ -} -bool -Context::shouldExit() -{ - return false; -} -void -Context::setAsDefaultForAssertsOutOfTestCases() -{ -} -void -Context::setAssertHandler(detail::assert_handler) -{ -} -void -Context::setCout(std::ostream*) -{ -} -int -Context::run() -{ - return 0; -} - -int -IReporter::get_num_active_contexts() -{ - return 0; -} -const IContextScope* const* -IReporter::get_active_contexts() -{ - return nullptr; -} -int -IReporter::get_num_stringified_contexts() -{ - return 0; -} -const String* -IReporter::get_stringified_contexts() -{ - return nullptr; -} - -int -registerReporter(const char*, int, IReporter*) -{ - return 0; -} - -} // namespace doctest -#else // DOCTEST_CONFIG_DISABLE - -#if !defined(DOCTEST_CONFIG_COLORS_NONE) -#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && \ - !defined(DOCTEST_CONFIG_COLORS_ANSI) -#ifdef DOCTEST_PLATFORM_WINDOWS -#define DOCTEST_CONFIG_COLORS_WINDOWS -#else // linux -#define DOCTEST_CONFIG_COLORS_ANSI -#endif // platform -#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI -#endif // DOCTEST_CONFIG_COLORS_NONE - -namespace doctest_detail_test_suite_ns { -// holds the current test suite -doctest::detail::TestSuite& -getCurrentTestSuite() -{ - static doctest::detail::TestSuite data{}; - return data; -} -} // namespace doctest_detail_test_suite_ns - -namespace doctest { -namespace { -// the int (priority) is part of the key for automatic sorting - sadly one can -// register a reporter with a duplicate name and a different priority but -// hopefully that won't happen often :| -using reporterMap = std::map, reporterCreatorFunc>; - -reporterMap& -getReporters() -{ - static reporterMap data; - return data; -} -reporterMap& -getListeners() -{ - static reporterMap data; - return data; -} -} // namespace -namespace detail { -#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ - for (auto& curr_rep : g_cs->reporters_currently_used) \ - curr_rep->function(__VA_ARGS__) - -bool -checkIfShouldThrow(assertType::Enum at) -{ - if (at & assertType::is_require) //! OCLINT bitwise operator in conditional - return true; - - if ((at & assertType::is_check) //! OCLINT bitwise operator in conditional - && getContextOptions()->abort_after > 0 && - (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= - getContextOptions()->abort_after) - return true; - - return false; -} - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -DOCTEST_NORETURN void -throwException() -{ - g_cs->shouldLogCurrentException = false; - throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) -} -#else // DOCTEST_CONFIG_NO_EXCEPTIONS -void -throwException() -{ -} -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -} // namespace detail - -namespace { -using namespace detail; -// matching of a string against a wildcard mask (case sensitivity configurable) -// taken from -// https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing -int -wildcmp(const char* str, const char* wild, bool caseSensitive) -{ - const char* cp = str; - const char* mp = wild; - - while ((*str) && (*wild != '*')) { - if ((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && - (*wild != '?')) { - return 0; - } - wild++; - str++; - } - - while (*str) { - if (*wild == '*') { - if (!*++wild) { - return 1; - } - mp = wild; - cp = str + 1; - } else if ((caseSensitive ? (*wild == *str) - : (tolower(*wild) == tolower(*str))) || - (*wild == '?')) { - wild++; - str++; - } else { - wild = mp; //! OCLINT parameter reassignment - str = cp++; //! OCLINT parameter reassignment - } - } - - while (*wild == '*') { - wild++; - } - return !*wild; -} - -// checks if the name matches any of the filters (and can be configured what to -// do when empty) -bool -matchesAny(const char* name, - const std::vector& filters, - bool matchEmpty, - bool caseSensitive) -{ - if (filters.empty() && matchEmpty) - return true; - for (auto& curr : filters) - if (wildcmp(name, curr.c_str(), caseSensitive)) - return true; - return false; -} - -unsigned long long -hash(unsigned long long a, unsigned long long b) -{ - return (a << 5) + b; -} - -// C string hash function (djb2) - taken from -// http://www.cse.yorku.ca/~oz/hash.html -unsigned long long -hash(const char* str) -{ - unsigned long long hash = 5381; - char c; - while ((c = *str++)) - hash = ((hash << 5) + hash) + c; // hash * 33 + c - return hash; -} - -unsigned long long -hash(const SubcaseSignature& sig) -{ - return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); -} - -unsigned long long -hash(const std::vector& sigs, size_t count) -{ - unsigned long long running = 0; - auto end = sigs.begin() + count; - for (auto it = sigs.begin(); it != end; it++) { - running = hash(running, hash(*it)); - } - return running; -} - -unsigned long long -hash(const std::vector& sigs) -{ - unsigned long long running = 0; - for (const SubcaseSignature& sig : sigs) { - running = hash(running, hash(sig)); - } - return running; -} -} // namespace -namespace detail { -bool -Subcase::checkFilters() -{ - if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { - if (!matchesAny(m_signature.m_name.c_str(), - g_cs->filters[6], - true, - g_cs->case_sensitive)) - return true; - if (matchesAny(m_signature.m_name.c_str(), - g_cs->filters[7], - false, - g_cs->case_sensitive)) - return true; - } - return false; -} - -Subcase::Subcase(const String& name, const char* file, int line) - : m_signature({ name, file, line }) -{ - if (!g_cs->reachedLeaf) { - if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() || - g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { - // Going down. - if (checkFilters()) { - return; - } - - g_cs->subcaseStack.push_back(m_signature); - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } - } else { - if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { - // This subcase is reentered via control flow. - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth && - g_cs->fullyTraversedSubcases.find(hash( - hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), - hash(m_signature))) == g_cs->fullyTraversedSubcases.end()) { - if (checkFilters()) { - return; - } - // This subcase is part of the one to be executed next. - g_cs->nextSubcaseStack.clear(); - g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), - g_cs->subcaseStack.begin(), - g_cs->subcaseStack.begin() + - g_cs->currentSubcaseDepth); - g_cs->nextSubcaseStack.push_back(m_signature); - } - } -} - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH( - 4996) // std::uncaught_exception is deprecated in C++17 -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - -Subcase::~Subcase() -{ - if (m_entered) { - g_cs->currentSubcaseDepth--; - - if (!g_cs->reachedLeaf) { - // Leaf. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - g_cs->nextSubcaseStack.clear(); - g_cs->reachedLeaf = true; - } else if (g_cs->nextSubcaseStack.empty()) { - // All children are finished. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - } - -#if defined(__cpp_lib_uncaught_exceptions) && \ - __cpp_lib_uncaught_exceptions >= 201411L && \ - (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || \ - __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if (std::uncaught_exceptions() > 0 -#else - if (std::uncaught_exception() -#endif - && g_cs->shouldLogCurrentException) { - DOCTEST_ITERATE_THROUGH_REPORTERS( - test_case_exception, - { "exception thrown in subcase - will translate later " - "when the whole test case has been exited (cannot " - "translate while there is an active exception)", - false }); - g_cs->shouldLogCurrentException = false; - } - - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); - } -} - -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP -DOCTEST_MSVC_SUPPRESS_WARNING_POP - -Subcase:: -operator bool() const -{ - return m_entered; -} - -Result::Result(bool passed, const String& decomposition) - : m_passed(passed) - , m_decomp(decomposition) -{ -} - -ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) - : m_at(at) -{ -} - -TestSuite& -TestSuite::operator*(const char* in) -{ - m_test_suite = in; - return *this; -} - -TestCase::TestCase(funcType test, - const char* file, - unsigned line, - const TestSuite& test_suite, - const String& type, - int template_id) -{ - m_file = file; - m_line = line; - m_name = nullptr; // will be later overridden in operator* - m_test_suite = test_suite.m_test_suite; - m_description = test_suite.m_description; - m_skip = test_suite.m_skip; - m_no_breaks = test_suite.m_no_breaks; - m_no_output = test_suite.m_no_output; - m_may_fail = test_suite.m_may_fail; - m_should_fail = test_suite.m_should_fail; - m_expected_failures = test_suite.m_expected_failures; - m_timeout = test_suite.m_timeout; - - m_test = test; - m_type = type; - m_template_id = template_id; -} - -TestCase::TestCase(const TestCase& other) - : TestCaseData() -{ - *this = other; -} - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function -TestCase& -TestCase::operator=(const TestCase& other) -{ - TestCaseData::operator=(other); - m_test = other.m_test; - m_type = other.m_type; - m_template_id = other.m_template_id; - m_full_name = other.m_full_name; - - if (m_template_id != -1) - m_name = m_full_name.c_str(); - return *this; -} -DOCTEST_MSVC_SUPPRESS_WARNING_POP - -TestCase& -TestCase::operator*(const char* in) -{ - m_name = in; - // make a new name with an appended type for templated test case - if (m_template_id != -1) { - m_full_name = String(m_name) + "<" + m_type + ">"; - // redirect the name to point to the newly constructed full name - m_name = m_full_name.c_str(); - } - return *this; -} - -bool -TestCase::operator<(const TestCase& other) const -{ - // this will be used only to differentiate between test cases - not relevant - // for sorting - if (m_line != other.m_line) - return m_line < other.m_line; - const int name_cmp = strcmp(m_name, other.m_name); - if (name_cmp != 0) - return name_cmp < 0; - const int file_cmp = m_file.compare(other.m_file); - if (file_cmp != 0) - return file_cmp < 0; - return m_template_id < other.m_template_id; -} - -// all the registered tests -std::set& -getRegisteredTests() -{ - static std::set data; - return data; -} -} // namespace detail -namespace { -using namespace detail; -// for sorting tests by file/line -bool -fileOrderComparator(const TestCase* lhs, const TestCase* rhs) -{ - // this is needed because MSVC gives different case for drive letters - // for __FILE__ when evaluated in a header and a source file - const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); - if (res != 0) - return res < 0; - if (lhs->m_line != rhs->m_line) - return lhs->m_line < rhs->m_line; - return lhs->m_template_id < rhs->m_template_id; -} - -// for sorting tests by suite/file/line -bool -suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) -{ - const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); - if (res != 0) - return res < 0; - return fileOrderComparator(lhs, rhs); -} - -// for sorting tests by name/suite/file/line -bool -nameOrderComparator(const TestCase* lhs, const TestCase* rhs) -{ - const int res = std::strcmp(lhs->m_name, rhs->m_name); - if (res != 0) - return res < 0; - return suiteOrderComparator(lhs, rhs); -} - -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") -void -color_to_stream(std::ostream& s, Color::Enum code) -{ - static_cast( - s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS - static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE -#ifdef DOCTEST_CONFIG_COLORS_ANSI - if (g_no_colors || (isatty(STDOUT_FILENO) == false && - getContextOptions()->force_colors == false)) - return; - - auto col = ""; - // clang-format off - switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement - case Color::Red: col = "[0;31m"; break; - case Color::Green: col = "[0;32m"; break; - case Color::Blue: col = "[0;34m"; break; - case Color::Cyan: col = "[0;36m"; break; - case Color::Yellow: col = "[0;33m"; break; - case Color::Grey: col = "[1;30m"; break; - case Color::LightGrey: col = "[0;37m"; break; - case Color::BrightRed: col = "[1;31m"; break; - case Color::BrightGreen: col = "[1;32m"; break; - case Color::BrightWhite: col = "[1;37m"; break; - case Color::Bright: // invalid - case Color::None: - case Color::White: - default: col = "[0m"; - } - // clang-format on - s << "\033" << col; -#endif // DOCTEST_CONFIG_COLORS_ANSI - -#ifdef DOCTEST_CONFIG_COLORS_WINDOWS - if (g_no_colors || (_isatty(_fileno(stdout)) == false && - getContextOptions()->force_colors == false)) - return; - - static struct ConsoleHelper - { - HANDLE stdoutHandle; - WORD origFgAttrs; - WORD origBgAttrs; - - ConsoleHelper() - { - stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); - origFgAttrs = - csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | - BACKGROUND_BLUE | BACKGROUND_INTENSITY); - origBgAttrs = - csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | - FOREGROUND_BLUE | FOREGROUND_INTENSITY); - } - } ch; - -#define DOCTEST_SET_ATTR(x) \ - SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) - - // clang-format off - switch (code) { - case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; - case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; - case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break; - case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break; - case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break; - case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break; - case Color::Grey: DOCTEST_SET_ATTR(0); break; - case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break; - case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break; - case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break; - case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; - case Color::None: - case Color::Bright: // invalid - default: DOCTEST_SET_ATTR(ch.origFgAttrs); - } - // clang-format on -#endif // DOCTEST_CONFIG_COLORS_WINDOWS -} -DOCTEST_CLANG_SUPPRESS_WARNING_POP - -std::vector& -getExceptionTranslators() -{ - static std::vector data; - return data; -} - -String -translateActiveException() -{ -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - String res; - auto& translators = getExceptionTranslators(); - for (auto& curr : translators) - if (curr->translate(res)) - return res; - // clang-format off - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value") - try { - throw; - } catch(std::exception& ex) { - return ex.what(); - } catch(std::string& msg) { - return msg.c_str(); - } catch(const char* msg) { - return msg; - } catch(...) { - return "unknown exception"; - } - DOCTEST_GCC_SUPPRESS_WARNING_POP -// clang-format on -#else // DOCTEST_CONFIG_NO_EXCEPTIONS - return ""; -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -} -} // namespace - -namespace detail { -// used by the macros for registering tests -int -regTest(const TestCase& tc) -{ - getRegisteredTests().insert(tc); - return 0; -} - -// sets the current test suite -int -setTestSuite(const TestSuite& ts) -{ - doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; - return 0; -} - -#ifdef DOCTEST_IS_DEBUGGER_ACTIVE -bool -isDebuggerActive() -{ - return DOCTEST_IS_DEBUGGER_ACTIVE(); -} -#else // DOCTEST_IS_DEBUGGER_ACTIVE -#ifdef DOCTEST_PLATFORM_LINUX -class ErrnoGuard -{ -public: - ErrnoGuard() - : m_oldErrno(errno) - { - } - ~ErrnoGuard() { errno = m_oldErrno; } - -private: - int m_oldErrno; -}; -// See the comments in Catch2 for the reasoning behind this implementation: -// https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 -bool -isDebuggerActive() -{ - ErrnoGuard guard; - std::ifstream in("/proc/self/status"); - for (std::string line; std::getline(in, line);) { - static const int PREFIX_LEN = 11; - if (line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - return false; -} -#elif defined(DOCTEST_PLATFORM_MAC) -// The following function is taken directly from the following technical note: -// https://developer.apple.com/library/archive/qa/qa1361/_index.html -// Returns true if the current process is being debugged (either -// running under the debugger or has a debugger attached post facto). -bool -isDebuggerActive() -{ - int mib[4]; - kinfo_proc info; - size_t size; - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - info.kp_proc.p_flag = 0; - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - // Call sysctl. - size = sizeof(info); - if (sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { - std::cerr << "\nCall to sysctl failed - unable to determine if debugger is " - "active **\n"; - return false; - } - // We're being debugged if the P_TRACED flag is set. - return ((info.kp_proc.p_flag & P_TRACED) != 0); -} -#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) -bool -isDebuggerActive() -{ - return ::IsDebuggerPresent() != 0; -} -#else -bool -isDebuggerActive() -{ - return false; -} -#endif // Platform -#endif // DOCTEST_IS_DEBUGGER_ACTIVE - -void -registerExceptionTranslatorImpl(const IExceptionTranslator* et) -{ - if (std::find(getExceptionTranslators().begin(), - getExceptionTranslators().end(), - et) == getExceptionTranslators().end()) - getExceptionTranslators().push_back(et); -} - -DOCTEST_THREAD_LOCAL std::vector - g_infoContexts; // for logging with INFO() - -ContextScopeBase::ContextScopeBase() -{ - g_infoContexts.push_back(this); -} - -ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept -{ - if (other.need_to_destroy) { - other.destroy(); - } - other.need_to_destroy = false; - g_infoContexts.push_back(this); -} - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH( - 4996) // std::uncaught_exception is deprecated in C++17 -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - -// destroy cannot be inlined into the destructor because that would mean calling -// stringify after ContextScope has been destroyed (base class destructors run -// after derived class destructors). Instead, ContextScope calls this method -// directly from its destructor. -void -ContextScopeBase::destroy() -{ -#if defined(__cpp_lib_uncaught_exceptions) && \ - __cpp_lib_uncaught_exceptions >= 201411L && \ - (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || \ - __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if (std::uncaught_exceptions() > 0) { -#else - if (std::uncaught_exception()) { -#endif - std::ostringstream s; - this->stringify(&s); - g_cs->stringifiedContexts.push_back(s.str().c_str()); - } - g_infoContexts.pop_back(); -} - -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP -DOCTEST_MSVC_SUPPRESS_WARNING_POP -} // namespace detail -namespace { -using namespace detail; - -#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ - !defined(DOCTEST_CONFIG_WINDOWS_SEH) -struct FatalConditionHandler -{ - static void reset() {} - static void allocateAltStackMem() {} - static void freeAltStackMem() {} -}; -#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH - -void -reportFatal(const std::string&); - -#ifdef DOCTEST_PLATFORM_WINDOWS - -struct SignalDefs -{ - DWORD id; - const char* name; -}; -// There is no 1-1 mapping between signals and windows exceptions. -// Windows can easily distinguish between SO and SigSegV, -// but SigInt, SigTerm, etc are handled differently. -SignalDefs signalDefs[] = { - { static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), - "SIGILL - Illegal instruction signal" }, - { static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" }, - { static_cast(EXCEPTION_ACCESS_VIOLATION), - "SIGSEGV - Segmentation violation signal" }, - { static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, -}; - -struct FatalConditionHandler -{ - static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) - { - // Multiple threads may enter this filter/handler at once. We want the error - // message to be printed on the console just once no matter how many threads - // have crashed. - DOCTEST_DECLARE_STATIC_MUTEX(mutex) - static bool execute = true; - { - DOCTEST_LOCK_MUTEX(mutex) - if (execute) { - bool reported = false; - for (size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == - signalDefs[i].id) { - reportFatal(signalDefs[i].name); - reported = true; - break; - } - } - if (reported == false) - reportFatal("Unhandled SEH exception caught"); - if (isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - } - execute = false; - } - std::exit(EXIT_FAILURE); - } - - static void allocateAltStackMem() {} - static void freeAltStackMem() {} - - FatalConditionHandler() - { - isSet = true; - // 32k seems enough for doctest to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - // Register an unhandled exception filter - previousTop = SetUnhandledExceptionFilter(handleException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - - // On Windows uncaught exceptions from another thread, exceptions from - // destructors, or calls to std::terminate are not a SEH exception - - // The terminal handler gets called when: - // - std::terminate is called FROM THE TEST RUNNER THREAD - // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD - original_terminate_handler = std::get_terminate(); - std::set_terminate([]() DOCTEST_NOEXCEPT { - reportFatal("Terminate handler called"); - if (isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT - // handler may be called as well - }); - - // SIGABRT is raised when: - // - std::terminate is called FROM A DIFFERENT THREAD - // - an exception is thrown from a destructor FROM A DIFFERENT THREAD - // - an uncaught exception is thrown FROM A DIFFERENT THREAD - prev_sigabrt_handler = - std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { - if (signal == SIGABRT) { - reportFatal("SIGABRT - Abort (abnormal termination) signal"); - if (isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); - } - }); - - // The following settings are taken from google test, and more - // specifically from UnitTest::Run() inside of gtest.cc - - // the user does not want to see pop-up dialogs about crashes - prev_error_mode_1 = - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | - SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); - // This forces the abort message to go to stderr in all circumstances. - prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); - // In the debug version, Visual Studio pops up a separate dialog - // offering a choice to debug the aborted program - we want to disable that. - prev_abort_behavior = - _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - // In debug mode, the Windows CRT can crash with an assertion over invalid - // input (e.g. passing an invalid file descriptor). The default handling - // for these assertions is to pop up a dialog and wait for user input. - // Instead ask the CRT to dump such assertions to stderr non-interactively. - prev_report_mode = - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); - } - - static void reset() - { - if (isSet) { - // Unregister handler and restore the old guarantee - SetUnhandledExceptionFilter(previousTop); - SetThreadStackGuarantee(&guaranteeSize); - std::set_terminate(original_terminate_handler); - std::signal(SIGABRT, prev_sigabrt_handler); - SetErrorMode(prev_error_mode_1); - _set_error_mode(prev_error_mode_2); - _set_abort_behavior(prev_abort_behavior, - _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); - static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); - isSet = false; - } - } - - ~FatalConditionHandler() { reset(); } - -private: - static UINT prev_error_mode_1; - static int prev_error_mode_2; - static unsigned int prev_abort_behavior; - static int prev_report_mode; - static _HFILE prev_report_file; - static void(DOCTEST_CDECL* prev_sigabrt_handler)(int); - static std::terminate_handler original_terminate_handler; - static bool isSet; - static ULONG guaranteeSize; - static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; -}; - -UINT FatalConditionHandler::prev_error_mode_1; -int FatalConditionHandler::prev_error_mode_2; -unsigned int FatalConditionHandler::prev_abort_behavior; -int FatalConditionHandler::prev_report_mode; -_HFILE FatalConditionHandler::prev_report_file; -void(DOCTEST_CDECL* FatalConditionHandler::prev_sigabrt_handler)(int); -std::terminate_handler FatalConditionHandler::original_terminate_handler; -bool FatalConditionHandler::isSet = false; -ULONG FatalConditionHandler::guaranteeSize = 0; -LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; - -#else // DOCTEST_PLATFORM_WINDOWS - -struct SignalDefs -{ - int id; - const char* name; -}; -SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } -}; - -struct FatalConditionHandler -{ - static bool isSet; - static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; - static stack_t oldSigStack; - static size_t altStackSize; - static char* altStackMem; - - static void handleSignal(int sig) - { - const char* name = ""; - for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - SignalDefs& def = signalDefs[i]; - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise(sig); - } - - static void allocateAltStackMem() { altStackMem = new char[altStackSize]; } - - static void freeAltStackMem() { delete[] altStackMem; } - - FatalConditionHandler() - { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = altStackSize; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = {}; - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - ~FatalConditionHandler() { reset(); } - static void reset() - { - if (isSet) { - // Set signals back to previous values -- hopefully nobody overwrote them - // in the meantime - for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } -}; - -bool FatalConditionHandler::isSet = false; -struct sigaction - FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; -stack_t FatalConditionHandler::oldSigStack = {}; -size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; -char* FatalConditionHandler::altStackMem = nullptr; - -#endif // DOCTEST_PLATFORM_WINDOWS -#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH - -} // namespace - -namespace { -using namespace detail; - -#ifdef DOCTEST_PLATFORM_WINDOWS -#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text) -#else -// TODO: integration with XCode and other IDEs -#define DOCTEST_OUTPUT_DEBUG_STRING(text) -#endif // Platform - -void -addAssert(assertType::Enum at) -{ - if ((at & assertType::is_warn) == 0) //! OCLINT bitwise operator in - //! conditional - g_cs->numAssertsCurrentTest_atomic++; -} - -void -addFailedAssert(assertType::Enum at) -{ - if ((at & assertType::is_warn) == 0) //! OCLINT bitwise operator in - //! conditional - g_cs->numAssertsFailedCurrentTest_atomic++; -} - -#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH) -void -reportFatal(const std::string& message) -{ - g_cs->failure_flags |= TestCaseFailureReason::Crash; - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, - { message.c_str(), true }); - - while (g_cs->subcaseStack.size()) { - g_cs->subcaseStack.pop_back(); - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); - } - - g_cs->finalizeTestCaseData(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); -} -#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH -} // namespace - -AssertData::AssertData(assertType::Enum at, - const char* file, - int line, - const char* expr, - const char* exception_type, - const StringContains& exception_string) - : m_test_case(g_cs->currentTest) - , m_at(at) - , m_file(file) - , m_line(line) - , m_expr(expr) - , m_failed(true) - , m_threw(false) - , m_threw_as(false) - , m_exception_type(exception_type) - , m_exception_string(exception_string) -{ -#if DOCTEST_MSVC - if (m_expr[0] == - ' ') // this happens when variadic macros are disabled under MSVC - ++m_expr; -#endif // MSVC -} - -namespace detail { -ResultBuilder::ResultBuilder(assertType::Enum at, - const char* file, - int line, - const char* expr, - const char* exception_type, - const String& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) -{ -} - -ResultBuilder::ResultBuilder(assertType::Enum at, - const char* file, - int line, - const char* expr, - const char* exception_type, - const Contains& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) -{ -} - -void -ResultBuilder::setResult(const Result& res) -{ - m_decomp = res.m_decomp; - m_failed = !res.m_passed; -} - -void -ResultBuilder::translateException() -{ - m_threw = true; - m_exception = translateActiveException(); -} - -bool -ResultBuilder::log() -{ - if (m_at & assertType::is_throws) { //! OCLINT bitwise operator in conditional - m_failed = !m_threw; - } else if ((m_at & assertType::is_throws_as) && - (m_at & assertType::is_throws_with)) { //! OCLINT - m_failed = !m_threw_as || !m_exception_string.check(m_exception); - } else if (m_at & assertType::is_throws_as) { //! OCLINT bitwise operator in - //! conditional - m_failed = !m_threw_as; - } else if (m_at & assertType::is_throws_with) { //! OCLINT bitwise operator in - //! conditional - m_failed = !m_exception_string.check(m_exception); - } else if (m_at & assertType::is_nothrow) { //! OCLINT bitwise operator in - //! conditional - m_failed = m_threw; - } - - if (m_exception.size()) - m_exception = "\"" + m_exception + "\""; - - if (is_running_in_test) { - addAssert(m_at); - DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); - - if (m_failed) - addFailedAssert(m_at); - } else if (m_failed) { - failed_out_of_a_testing_context(*this); - } - - return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && - (g_cs->currentTest == nullptr || - !g_cs->currentTest->m_no_breaks); // break into debugger -} - -void -ResultBuilder::react() const -{ - if (m_failed && checkIfShouldThrow(m_at)) - throwException(); -} - -void -failed_out_of_a_testing_context(const AssertData& ad) -{ - if (g_cs->ah) - g_cs->ah(ad); - else - std::abort(); -} - -bool -decomp_assert(assertType::Enum at, - const char* file, - int line, - const char* expr, - const Result& result) -{ - bool failed = !result.m_passed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE - // FAILING ASSERT THIS IS THE EFFECT OF HAVING - // 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); - DOCTEST_ASSERT_IN_TESTS(result.m_decomp); - return !failed; -} - -MessageBuilder::MessageBuilder(const char* file, - int line, - assertType::Enum severity) -{ - m_stream = tlssPush(); - m_file = file; - m_line = line; - m_severity = severity; -} - -MessageBuilder::~MessageBuilder() -{ - if (!logged) - tlssPop(); -} - -DOCTEST_DEFINE_INTERFACE(IExceptionTranslator) - -bool -MessageBuilder::log() -{ - if (!logged) { - m_string = tlssPop(); - logged = true; - } - - DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); - - const bool isWarn = m_severity & assertType::is_warn; - - // warn is just a message in this context so we don't treat it as an assert - if (!isWarn) { - addAssert(m_severity); - addFailedAssert(m_severity); - } - - return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && - (g_cs->currentTest == nullptr || - !g_cs->currentTest->m_no_breaks); // break into debugger -} - -void -MessageBuilder::react() -{ - if (m_severity & - assertType::is_require) //! OCLINT bitwise operator in conditional - throwException(); -} -} // namespace detail -namespace { -using namespace detail; - -// clang-format off - -// ================================================================================================= -// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp -// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. -// ================================================================================================= - - class XmlEncode { - public: - enum ForWhat { ForTextNodes, ForAttributes }; - - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); - - void encodeTo( std::ostream& os ) const; - - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); - - private: - std::string m_str; - ForWhat m_forWhat; - }; - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ); - - ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT; - ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT; - - ~ScopedElement(); - - ScopedElement& writeText( std::string const& text, bool indent = true ); - - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer = nullptr; - }; - - XmlWriter( std::ostream& os = std::cout ); - ~XmlWriter(); - - XmlWriter( XmlWriter const& ) = delete; - XmlWriter& operator=( XmlWriter const& ) = delete; - - XmlWriter& startElement( std::string const& name ); - - ScopedElement scopedElement( std::string const& name ); - - XmlWriter& endElement(); - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); - - XmlWriter& writeAttribute( std::string const& name, const char* attribute ); - - XmlWriter& writeAttribute( std::string const& name, bool attribute ); - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::stringstream rss; - rss << attribute; - return writeAttribute( name, rss.str() ); - } - - XmlWriter& writeText( std::string const& text, bool indent = true ); - - //XmlWriter& writeComment( std::string const& text ); - - //void writeStylesheetRef( std::string const& url ); - - //XmlWriter& writeBlankLine(); - - void ensureTagClosed(); - - void writeDeclaration(); - - private: - - void newlineIfNecessary(); - - bool m_tagIsOpen = false; - bool m_needsNewline = false; - std::vector m_tags; - std::string m_indent; - std::ostream& m_os; - }; - -// ================================================================================================= -// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp -// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. -// ================================================================================================= - -using uchar = unsigned char; - -namespace { - - size_t trailingBytes(unsigned char c) { - if ((c & 0xE0) == 0xC0) { - return 2; - } - if ((c & 0xF0) == 0xE0) { - return 3; - } - if ((c & 0xF8) == 0xF0) { - return 4; - } - DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); - } - - uint32_t headerValue(unsigned char c) { - if ((c & 0xE0) == 0xC0) { - return c & 0x1F; - } - if ((c & 0xF0) == 0xE0) { - return c & 0x0F; - } - if ((c & 0xF8) == 0xF0) { - return c & 0x07; - } - DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); - } - - void hexEscapeChar(std::ostream& os, unsigned char c) { - std::ios_base::fmtflags f(os.flags()); - os << "\\x" - << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast(c); - os.flags(f); - } - -} // anonymous namespace - - XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) - : m_str( str ), - m_forWhat( forWhat ) - {} - - void XmlEncode::encodeTo( std::ostream& os ) const { - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: https://www.w3.org/TR/xml/#syntax) - - for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { - uchar c = m_str[idx]; - switch (c) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: https://www.w3.org/TR/xml/#syntax - if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') - os << ">"; - else - os << c; - break; - - case '\"': - if (m_forWhat == ForAttributes) - os << """; - else - os << c; - break; - - default: - // Check for control characters and invalid utf-8 - - // Escape control characters in standard ascii - // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { - hexEscapeChar(os, c); - break; - } - - // Plain ASCII: Write it to stream - if (c < 0x7F) { - os << c; - break; - } - - // UTF-8 territory - // Check if the encoding is valid and if it is not, hex escape bytes. - // Important: We do not check the exact decoded values for validity, only the encoding format - // First check that this bytes is a valid lead byte: - // This means that it is not encoded as 1111 1XXX - // Or as 10XX XXXX - if (c < 0xC0 || - c >= 0xF8) { - hexEscapeChar(os, c); - break; - } - - auto encBytes = trailingBytes(c); - // Are there enough bytes left to avoid accessing out-of-bounds memory? - if (idx + encBytes - 1 >= m_str.size()) { - hexEscapeChar(os, c); - break; - } - // The header is valid, check data - // The next encBytes bytes must together be a valid utf-8 - // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) - bool valid = true; - uint32_t value = headerValue(c); - for (std::size_t n = 1; n < encBytes; ++n) { - uchar nc = m_str[idx + n]; - valid &= ((nc & 0xC0) == 0x80); - value = (value << 6) | (nc & 0x3F); - } - - if ( - // Wrong bit pattern of following bytes - (!valid) || - // Overlong encodings - (value < 0x80) || - ( value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant - (0x800 < value && value < 0x10000 && encBytes > 3) || - // Encoded value out of range - (value >= 0x110000) - ) { - hexEscapeChar(os, c); - break; - } - - // If we got here, this is in fact a valid(ish) utf-8 sequence - for (std::size_t n = 0; n < encBytes; ++n) { - os << m_str[idx + n]; - } - idx += encBytes - 1; - break; - } - } - } - - std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } - - XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT - : m_writer( other.m_writer ){ - other.m_writer = nullptr; - } - XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT { - if ( m_writer ) { - m_writer->endElement(); - } - m_writer = other.m_writer; - other.m_writer = nullptr; - return *this; - } - - - XmlWriter::ScopedElement::~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { - m_writer->writeText( text, indent ); - return *this; - } - - XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) - { - // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627 - } - - XmlWriter::~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& XmlWriter::startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& XmlWriter::endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) { - if( !name.empty() && attribute && attribute[0] != '\0' ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - //XmlWriter& XmlWriter::writeComment( std::string const& text ) { - // ensureTagClosed(); - // m_os << m_indent << ""; - // m_needsNewline = true; - // return *this; - //} - - //void XmlWriter::writeStylesheetRef( std::string const& url ) { - // m_os << "\n"; - //} - - //XmlWriter& XmlWriter::writeBlankLine() { - // ensureTagClosed(); - // m_os << '\n'; - // return *this; - //} - - void XmlWriter::ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } - - void XmlWriter::writeDeclaration() { - m_os << "\n"; - } - - void XmlWriter::newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } - -// ================================================================================================= -// End of copy-pasted code from Catch -// ================================================================================================= - -// clang-format on - -struct XmlReporter : public IReporter -{ - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - XmlReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) - { - } - - void log_contexts() - { - int num_contexts = get_num_active_contexts(); - if (num_contexts) { - auto contexts = get_active_contexts(); - std::stringstream ss; - for (int i = 0; i < num_contexts; ++i) { - contexts[i]->stringify(&ss); - xml.scopedElement("Info").writeText(ss.str()); - ss.str(""); - } - } - } - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - void test_case_start_impl(const TestCaseData& in) - { - bool open_ts_tag = false; - if (tc != nullptr) { // we have already opened a test suite - if (std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { - xml.endElement(); - open_ts_tag = true; - } - } else { - open_ts_tag = true; // first test case ==> first test suite - } - - if (open_ts_tag) { - xml.startElement("TestSuite"); - xml.writeAttribute("name", in.m_test_suite); - } - - tc = ∈ - xml.startElement("TestCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) - .writeAttribute("line", line(in.m_line)) - .writeAttribute("description", in.m_description); - - if (Approx(in.m_timeout) != 0) - xml.writeAttribute("timeout", in.m_timeout); - if (in.m_may_fail) - xml.writeAttribute("may_fail", true); - if (in.m_should_fail) - xml.writeAttribute("should_fail", true); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override - { - test_run_start(); - if (opt.list_reporters) { - for (auto& curr : getListeners()) - xml.scopedElement("Listener") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - for (auto& curr : getReporters()) - xml.scopedElement("Reporter") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - } else if (opt.count || opt.list_test_cases) { - for (unsigned i = 0; i < in.num_data; ++i) { - xml.scopedElement("TestCase") - .writeAttribute("name", in.data[i]->m_name) - .writeAttribute("testsuite", in.data[i]->m_test_suite) - .writeAttribute("filename", - skipPathFromFilename(in.data[i]->m_file.c_str())) - .writeAttribute("line", line(in.data[i]->m_line)) - .writeAttribute("skipped", in.data[i]->m_skip); - } - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - } else if (opt.list_test_suites) { - for (unsigned i = 0; i < in.num_data; ++i) - xml.scopedElement("TestSuite") - .writeAttribute("name", in.data[i]->m_test_suite); - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - xml.scopedElement("OverallResultsTestSuites") - .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); - } - xml.endElement(); - } - - void test_run_start() override - { - xml.writeDeclaration(); - - // remove .exe extension - mainly to have the same output on UNIX and - // Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); -#ifdef DOCTEST_PLATFORM_WINDOWS - if (binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); -#endif // DOCTEST_PLATFORM_WINDOWS - - xml.startElement("doctest").writeAttribute("binary", binary_name); - if (opt.no_version == false) - xml.writeAttribute("version", DOCTEST_VERSION_STR); - - // only the consequential ones (TODO: filters) - xml.scopedElement("Options") - .writeAttribute("order_by", opt.order_by.c_str()) - .writeAttribute("rand_seed", opt.rand_seed) - .writeAttribute("first", opt.first) - .writeAttribute("last", opt.last) - .writeAttribute("abort_after", opt.abort_after) - .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) - .writeAttribute("case_sensitive", opt.case_sensitive) - .writeAttribute("no_throw", opt.no_throw) - .writeAttribute("no_skip", opt.no_skip); - } - - void test_run_end(const TestRunStats& p) override - { - if (tc) // the TestSuite tag - only if there has been at least 1 test case - xml.endElement(); - - xml.scopedElement("OverallResultsAsserts") - .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) - .writeAttribute("failures", p.numAssertsFailed); - - xml.startElement("OverallResultsTestCases") - .writeAttribute("successes", - p.numTestCasesPassingFilters - p.numTestCasesFailed) - .writeAttribute("failures", p.numTestCasesFailed); - if (opt.no_skipped_summary == false) - xml.writeAttribute("skipped", - p.numTestCases - p.numTestCasesPassingFilters); - xml.endElement(); - - xml.endElement(); - } - - void test_case_start(const TestCaseData& in) override - { - test_case_start_impl(in); - xml.ensureTagClosed(); - } - - void test_case_reenter(const TestCaseData&) override {} - - void test_case_end(const CurrentTestCaseStats& st) override - { - xml.startElement("OverallResultsAsserts") - .writeAttribute("successes", - st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) - .writeAttribute("failures", st.numAssertsFailedCurrentTest) - .writeAttribute("test_case_success", st.testCaseSuccess); - if (opt.duration) - xml.writeAttribute("duration", st.seconds); - if (tc->m_expected_failures) - xml.writeAttribute("expected_failures", tc->m_expected_failures); - xml.endElement(); - - xml.endElement(); - } - - void test_case_exception(const TestCaseException& e) override - { - DOCTEST_LOCK_MUTEX(mutex) - - xml.scopedElement("Exception") - .writeAttribute("crash", e.is_crash) - .writeText(e.error_string.c_str()); - } - - void subcase_start(const SubcaseSignature& in) override - { - xml.startElement("SubCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file)) - .writeAttribute("line", line(in.m_line)); - xml.ensureTagClosed(); - } - - void subcase_end() override { xml.endElement(); } - - void log_assert(const AssertData& rb) override - { - if (!rb.m_failed && !opt.success) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Expression") - .writeAttribute("success", !rb.m_failed) - .writeAttribute("type", assertString(rb.m_at)) - .writeAttribute("filename", skipPathFromFilename(rb.m_file)) - .writeAttribute("line", line(rb.m_line)); - - xml.scopedElement("Original").writeText(rb.m_expr); - - if (rb.m_threw) - xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); - - if (rb.m_at & assertType::is_throws_as) - xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); - if (rb.m_at & assertType::is_throws_with) - xml.scopedElement("ExpectedExceptionString") - .writeText(rb.m_exception_string.c_str()); - if ((rb.m_at & assertType::is_normal) && !rb.m_threw) - xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void log_message(const MessageData& mb) override - { - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Message") - .writeAttribute("type", failureString(mb.m_severity)) - .writeAttribute("filename", skipPathFromFilename(mb.m_file)) - .writeAttribute("line", line(mb.m_line)); - - xml.scopedElement("Text").writeText(mb.m_string.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void test_case_skipped(const TestCaseData& in) override - { - if (opt.no_skipped_summary == false) { - test_case_start_impl(in); - xml.writeAttribute("skipped", "true"); - xml.endElement(); - } - } -}; - -DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); - -void -fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) -{ - if ((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == - 0) //! OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " - << Color::None; - - if (rb.m_at & - assertType::is_throws) { //! OCLINT bitwise operator in conditional - s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; - } else if ((rb.m_at & assertType::is_throws_as) && - (rb.m_at & assertType::is_throws_with)) { //! OCLINT - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() << "\", " << rb.m_exception_type << " ) " - << Color::None; - if (rb.m_threw) { - if (!rb.m_failed) { - s << "threw as expected!\n"; - } else { - s << "threw a DIFFERENT exception! (contents: " << rb.m_exception - << ")\n"; - } - } else { - s << "did NOT throw at all!\n"; - } - } else if (rb.m_at & assertType::is_throws_as) { //! OCLINT bitwise operator - //! in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " - << rb.m_exception_type << " ) " << Color::None - << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" - : "threw a DIFFERENT exception: ") - : "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if (rb.m_at & assertType::is_throws_with) { //! OCLINT bitwise operator - //! in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() << "\" ) " << Color::None - << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" - : "threw a DIFFERENT exception: ") - : "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if (rb.m_at & assertType::is_nothrow) { //! OCLINT bitwise operator in - //! conditional - s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan - << rb.m_exception << "\n"; - } else { - s << (rb.m_threw ? "THREW exception: " - : (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); - if (rb.m_threw) - s << rb.m_exception << "\n"; - else - s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp - << " )\n"; - } -} - -// TODO: -// - log_message() -// - respond to queries -// - honor remaining options -// - more attributes in tags -struct JUnitReporter : public IReporter -{ - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - Timer timer; - std::vector deepestSubcaseStackNames; - - struct JUnitTestCaseData - { - static std::string getCurrentTimestamp() - { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - - std::tm timeInfo; -#ifdef DOCTEST_PLATFORM_WINDOWS - gmtime_s(&timeInfo, &rawtime); -#else // DOCTEST_PLATFORM_WINDOWS - gmtime_r(&rawtime, &timeInfo); -#endif // DOCTEST_PLATFORM_WINDOWS - - char timeStamp[timeStampSize]; - const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; - - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); - return std::string(timeStamp); - } - - struct JUnitTestMessage - { - JUnitTestMessage(const std::string& _message, - const std::string& _type, - const std::string& _details) - : message(_message) - , type(_type) - , details(_details) - { - } - - JUnitTestMessage(const std::string& _message, const std::string& _details) - : message(_message) - , type() - , details(_details) - { - } - - std::string message, type, details; - }; - - struct JUnitTestCase - { - JUnitTestCase(const std::string& _classname, const std::string& _name) - : classname(_classname) - , name(_name) - , time(0) - , failures() - { - } - - std::string classname, name; - double time; - std::vector failures, errors; - }; - - void add(const std::string& classname, const std::string& name) - { - testcases.emplace_back(classname, name); - } - - void appendSubcaseNamesToLastTestcase(std::vector nameStack) - { - for (auto& curr : nameStack) - if (curr.size()) - testcases.back().name += std::string("/") + curr.c_str(); - } - - void addTime(double time) - { - if (time < 1e-4) - time = 0; - testcases.back().time = time; - totalSeconds += time; - } - - void addFailure(const std::string& message, - const std::string& type, - const std::string& details) - { - testcases.back().failures.emplace_back(message, type, details); - ++totalFailures; - } - - void addError(const std::string& message, const std::string& details) - { - testcases.back().errors.emplace_back(message, details); - ++totalErrors; - } - - std::vector testcases; - double totalSeconds = 0; - int totalErrors = 0, totalFailures = 0; - }; - - JUnitTestCaseData testCaseData; - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - JUnitReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) - { - } - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData&) override { xml.writeDeclaration(); } - - void test_run_start() override { xml.writeDeclaration(); } - - void test_run_end(const TestRunStats& p) override - { - // remove .exe extension - mainly to have the same output on UNIX and - // Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); -#ifdef DOCTEST_PLATFORM_WINDOWS - if (binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); -#endif // DOCTEST_PLATFORM_WINDOWS - xml.startElement("testsuites"); - xml.startElement("testsuite") - .writeAttribute("name", binary_name) - .writeAttribute("errors", testCaseData.totalErrors) - .writeAttribute("failures", testCaseData.totalFailures) - .writeAttribute("tests", p.numAsserts); - if (opt.no_time_in_output == false) { - xml.writeAttribute("time", testCaseData.totalSeconds); - xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); - } - if (opt.no_version == false) - xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); - - for (const auto& testCase : testCaseData.testcases) { - xml.startElement("testcase") - .writeAttribute("classname", testCase.classname) - .writeAttribute("name", testCase.name); - if (opt.no_time_in_output == false) - xml.writeAttribute("time", testCase.time); - // This is not ideal, but it should be enough to mimic gtest's junit - // output. - xml.writeAttribute("status", "run"); - - for (const auto& failure : testCase.failures) { - xml.scopedElement("failure") - .writeAttribute("message", failure.message) - .writeAttribute("type", failure.type) - .writeText(failure.details, false); - } - - for (const auto& error : testCase.errors) { - xml.scopedElement("error") - .writeAttribute("message", error.message) - .writeText(error.details); - } - - xml.endElement(); - } - xml.endElement(); - xml.endElement(); - } - - void test_case_start(const TestCaseData& in) override - { - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); - timer.start(); - } - - void test_case_reenter(const TestCaseData& in) override - { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); - - timer.start(); - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); - } - - void test_case_end(const CurrentTestCaseStats&) override - { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); - } - - void test_case_exception(const TestCaseException& e) override - { - DOCTEST_LOCK_MUTEX(mutex) - testCaseData.addError("exception", e.error_string.c_str()); - } - - void subcase_start(const SubcaseSignature& in) override - { - deepestSubcaseStackNames.push_back(in.m_name); - } - - void subcase_end() override {} - - void log_assert(const AssertData& rb) override - { - if (!rb.m_failed) // report only failures & ignore the `success` option - return; - - DOCTEST_LOCK_MUTEX(mutex) - - std::ostringstream os; - os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") - << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; - - fulltext_log_assert_to_stream(os, rb); - log_contexts(os); - testCaseData.addFailure( - rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); - } - - void log_message(const MessageData&) override {} - - void test_case_skipped(const TestCaseData&) override {} - - void log_contexts(std::ostringstream& s) - { - int num_contexts = get_num_active_contexts(); - if (num_contexts) { - auto contexts = get_active_contexts(); - - s << " logged: "; - for (int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << std::endl; - } - } - } -}; - -DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); - -struct Whitespace -{ - int nrSpaces; - explicit Whitespace(int nr) - : nrSpaces(nr) - { - } -}; - -std::ostream& -operator<<(std::ostream& out, const Whitespace& ws) -{ - if (ws.nrSpaces != 0) - out << std::setw(ws.nrSpaces) << ' '; - return out; -} - -struct ConsoleReporter : public IReporter -{ - std::ostream& s; - bool hasLoggedCurrentTestStart; - std::vector subcasesStack; - size_t currentSubcaseLevel; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc; - - ConsoleReporter(const ContextOptions& co) - : s(*co.cout) - , opt(co) - { - } - - ConsoleReporter(const ContextOptions& co, std::ostream& ostr) - : s(ostr) - , opt(co) - { - } - - // ========================================================================================= - // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF - // THE INTERFACE - // ========================================================================================= - - void separator_to_stream() - { - s << Color::Yellow - << "=====================================================================" - "==========" - "\n"; - } - - const char* getSuccessOrFailString(bool success, - assertType::Enum at, - const char* success_str) - { - if (success) - return success_str; - return failureString(at); - } - - Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) - { - return success ? Color::BrightGreen - : (at & assertType::is_warn) ? Color::Yellow - : Color::Red; - } - - void successOrFailColoredStringToStream(bool success, - assertType::Enum at, - const char* success_str = "SUCCESS") - { - s << getSuccessOrFailColor(success, at) - << getSuccessOrFailString(success, at, success_str) << ": "; - } - - void log_contexts() - { - int num_contexts = get_num_active_contexts(); - if (num_contexts) { - auto contexts = get_active_contexts(); - - s << Color::None << " logged: "; - for (int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << "\n"; - } - } - - s << "\n"; - } - - // this was requested to be made virtual so users could override it - virtual void file_line_to_stream(const char* file, - int line, - const char* tail = "") - { - s << Color::LightGrey << skipPathFromFilename(file) - << (opt.gnu_file_line ? ":" : "(") - << (opt.no_line_numbers - ? 0 - : line) // 0 or the real num depending on the option - << (opt.gnu_file_line ? ":" : "):") << tail; - } - - void logTestStart() - { - if (hasLoggedCurrentTestStart) - return; - - separator_to_stream(); - file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); - if (tc->m_description) - s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description - << "\n"; - if (tc->m_test_suite && tc->m_test_suite[0] != '\0') - s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite - << "\n"; - if (strncmp(tc->m_name, " Scenario:", 11) != 0) - s << Color::Yellow << "TEST CASE: "; - s << Color::None << tc->m_name << "\n"; - - for (size_t i = 0; i < currentSubcaseLevel; ++i) { - if (subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - - if (currentSubcaseLevel != subcasesStack.size()) { - s << Color::Yellow - << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" - << Color::None; - for (size_t i = 0; i < subcasesStack.size(); ++i) { - if (subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - } - - s << "\n"; - - hasLoggedCurrentTestStart = true; - } - - void printVersion() - { - if (opt.no_version == false) - s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" - << DOCTEST_VERSION_STR << "\"\n"; - } - - void printIntro() - { - if (opt.no_intro == false) { - printVersion(); - s << Color::Cyan << "[doctest] " << Color::None - << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY - "help\" for options\n"; - } - } - - void printHelp() - { - int sizePrefixDisplay = - static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); - printVersion(); - // clang-format off - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"; - s << Color::Cyan << "[doctest] " << Color::None; - s << "filter values: \"str1,str2,str3\" (comma separated strings)\n"; - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "filters use wildcards for matching strings\n"; - s << Color::Cyan << "[doctest] " << Color::None; - s << "something passes a filter if any of the strings in a filter matches\n"; -#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n"; -#endif - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "Query flags - the program quits after them. Available:\n\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h " - << Whitespace(sizePrefixDisplay*0) << "prints this message\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version " - << Whitespace(sizePrefixDisplay*1) << "prints the version\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count " - << Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases " - << Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites " - << Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters " - << Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n"; - // ================================================================================== << 79 - s << Color::Cyan << "[doctest] " << Color::None; - s << "The available / options/filters are:\n\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case= " - << Whitespace(sizePrefixDisplay*1) << "filters tests by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file= " - << Whitespace(sizePrefixDisplay*1) << "filters tests by their file\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite= " - << Whitespace(sizePrefixDisplay*1) << "filters tests by their test suite\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase= " - << Whitespace(sizePrefixDisplay*1) << "filters subcases by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters= " - << Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out= " - << Whitespace(sizePrefixDisplay*1) << "output filename\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by= " - << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n"; - s << Whitespace(sizePrefixDisplay*3) << " - [file/suite/name/rand/none]\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed= " - << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first= " - << Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n"; - s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last= " - << Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n"; - s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after= " - << Whitespace(sizePrefixDisplay*1) << "stop after failed assertions\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels= " - << Whitespace(sizePrefixDisplay*1) << "apply filters for the first levels\n"; - s << Color::Cyan << "\n[doctest] " << Color::None; - s << "Bool options - can be used like flags and true is assumed. Available:\n\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success= " - << Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive= " - << Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit= " - << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration= " - << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal= " - << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet= " - << Whitespace(sizePrefixDisplay*1) << "no console output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw= " - << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode= " - << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run= " - << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro= " - << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version= " - << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors= " - << Whitespace(sizePrefixDisplay*1) << "disables colors in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors= " - << Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks= " - << Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip= " - << Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line= " - << Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames= " - << Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers= " - << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n"; - // ================================================================================== << 79 - // clang-format on - - s << Color::Cyan << "\n[doctest] " << Color::None; - s << "for more information visit the project documentation\n\n"; - } - - void printRegisteredReporters() - { - printVersion(); - auto printReporters = [this](const reporterMap& reporters, - const char* type) { - if (reporters.size()) { - s << Color::Cyan << "[doctest] " << Color::None - << "listing all registered " << type << "\n"; - for (auto& curr : reporters) - s << "priority: " << std::setw(5) << curr.first.first - << " name: " << curr.first.second << "\n"; - } - }; - printReporters(getListeners(), "listeners"); - printReporters(getReporters(), "reporters"); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override - { - if (opt.version) { - printVersion(); - } else if (opt.help) { - printHelp(); - } else if (opt.list_reporters) { - printRegisteredReporters(); - } else if (opt.count || opt.list_test_cases) { - if (opt.list_test_cases) { - s << Color::Cyan << "[doctest] " << Color::None - << "listing all test case names\n"; - separator_to_stream(); - } - - for (unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_name << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - - } else if (opt.list_test_suites) { - s << Color::Cyan << "[doctest] " << Color::None - << "listing all test suites\n"; - separator_to_stream(); - - for (unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_test_suite << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "test suites with unskipped test cases passing the current filters: " - << g_cs->numTestSuitesPassingFilters << "\n"; - } - } - - void test_run_start() override - { - if (!opt.minimal) - printIntro(); - } - - void test_run_end(const TestRunStats& p) override - { - if (opt.minimal && p.numTestCasesFailed == 0) - return; - - separator_to_stream(); - s << std::dec; - - auto totwidth = - int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, - static_cast(p.numAsserts))) + - 1))); - auto passwidth = int(std::ceil(log10( - (std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, - static_cast(p.numAsserts - p.numAssertsFailed))) + - 1))); - auto failwidth = int( - std::ceil(log10((std::max(p.numTestCasesFailed, - static_cast(p.numAssertsFailed))) + - 1))); - const bool anythingFailed = - p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; - s << Color::Cyan << "[doctest] " << Color::None - << "test cases: " << std::setw(totwidth) << p.numTestCasesPassingFilters - << " | " - << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None - : Color::Green) - << std::setw(passwidth) - << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" - << Color::None << " | " - << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) - << std::setw(failwidth) << p.numTestCasesFailed << " failed" - << Color::None << " |"; - if (opt.no_skipped_summary == false) { - const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; - s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped - << " skipped" << Color::None; - } - s << "\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "assertions: " << std::setw(totwidth) << p.numAsserts << " | " - << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) - << " passed" << Color::None << " | " - << (p.numAssertsFailed > 0 ? Color::Red : Color::None) - << std::setw(failwidth) << p.numAssertsFailed << " failed" << Color::None - << " |\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) - << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None - << std::endl; - } - - void test_case_start(const TestCaseData& in) override - { - hasLoggedCurrentTestStart = false; - tc = ∈ - subcasesStack.clear(); - currentSubcaseLevel = 0; - } - - void test_case_reenter(const TestCaseData&) override - { - subcasesStack.clear(); - } - - void test_case_end(const CurrentTestCaseStats& st) override - { - if (tc->m_no_output) - return; - - // log the preamble of the test case only if there is something - // else to print - something other than that an assert has failed - if (opt.duration || - (st.failure_flags && - st.failure_flags != - static_cast(TestCaseFailureReason::AssertFailure))) - logTestStart(); - - if (opt.duration) - s << Color::None << std::setprecision(6) << std::fixed << st.seconds - << " s: " << tc->m_name << "\n"; - - if (st.failure_flags & TestCaseFailureReason::Timeout) - s << Color::Red << "Test case exceeded time limit of " - << std::setprecision(6) << std::fixed << tc->m_timeout << "!\n"; - - if (st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { - s << Color::Red - << "Should have failed but didn't! Marking it as failed!\n"; - } else if (st.failure_flags & - TestCaseFailureReason::ShouldHaveFailedAndDid) { - s << Color::Yellow << "Failed as expected so marking it as not failed\n"; - } else if (st.failure_flags & - TestCaseFailureReason::CouldHaveFailedAndDid) { - s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; - } else if (st.failure_flags & - TestCaseFailureReason::DidntFailExactlyNumTimes) { - s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures - << " times so marking it as failed!\n"; - } else if (st.failure_flags & - TestCaseFailureReason::FailedExactlyNumTimes) { - s << Color::Yellow << "Failed exactly " << tc->m_expected_failures - << " times as expected so marking it as not failed!\n"; - } - if (st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { - s << Color::Red << "Aborting - too many failed asserts!\n"; - } - s << Color::None; // lgtm [cpp/useless-expression] - } - - void test_case_exception(const TestCaseException& e) override - { - DOCTEST_LOCK_MUTEX(mutex) - if (tc->m_no_output) - return; - - logTestStart(); - - file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); - successOrFailColoredStringToStream( - false, e.is_crash ? assertType::is_require : assertType::is_check); - s << Color::Red - << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") - << Color::Cyan << e.error_string << "\n"; - - int num_stringified_contexts = get_num_stringified_contexts(); - if (num_stringified_contexts) { - auto stringified_contexts = get_stringified_contexts(); - s << Color::None << " logged: "; - for (int i = num_stringified_contexts; i > 0; --i) { - s << (i == num_stringified_contexts ? "" : " ") - << stringified_contexts[i - 1] << "\n"; - } - } - s << "\n" << Color::None; - } - - void subcase_start(const SubcaseSignature& subc) override - { - subcasesStack.push_back(subc); - ++currentSubcaseLevel; - hasLoggedCurrentTestStart = false; - } - - void subcase_end() override - { - --currentSubcaseLevel; - hasLoggedCurrentTestStart = false; - } - - void log_assert(const AssertData& rb) override - { - if ((!rb.m_failed && !opt.success) || tc->m_no_output) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - logTestStart(); - - file_line_to_stream(rb.m_file, rb.m_line, " "); - successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); - - fulltext_log_assert_to_stream(s, rb); - - log_contexts(); - } - - void log_message(const MessageData& mb) override - { - if (tc->m_no_output) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - logTestStart(); - - file_line_to_stream(mb.m_file, mb.m_line, " "); - s << getSuccessOrFailColor(false, mb.m_severity) - << getSuccessOrFailString( - mb.m_severity & assertType::is_warn, mb.m_severity, "MESSAGE") - << ": "; - s << Color::None << mb.m_string << "\n"; - log_contexts(); - } - - void test_case_skipped(const TestCaseData&) override {} -}; - -DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); - -#ifdef DOCTEST_PLATFORM_WINDOWS -struct DebugOutputWindowReporter : public ConsoleReporter -{ - DOCTEST_THREAD_LOCAL static std::ostringstream oss; - - DebugOutputWindowReporter(const ContextOptions& co) - : ConsoleReporter(co, oss) - { - } - -#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ - void func(type arg) override \ - { \ - bool with_col = g_no_colors; \ - g_no_colors = false; \ - ConsoleReporter::func(arg); \ - if (oss.tellp() != std::streampos{}) { \ - DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ - oss.str(""); \ - } \ - g_no_colors = with_col; \ - } - - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, - DOCTEST_EMPTY, - DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, - const TestCaseData&, - in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, - const TestCaseData&, - in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, - const CurrentTestCaseStats&, - in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, - const TestCaseException&, - in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, - const SubcaseSignature&, - in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, - DOCTEST_EMPTY, - DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, - const TestCaseData&, - in) -}; - -DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; -#endif // DOCTEST_PLATFORM_WINDOWS - -// the implementation of parseOption() -bool -parseOptionImpl(int argc, - const char* const* argv, - const char* pattern, - String* value) -{ - // going from the end to the beginning and stopping on the first occurrence - // from the end - for (int i = argc; i > 0; --i) { - auto index = i - 1; - auto temp = std::strstr(argv[index], pattern); - if (temp && - (value || - strlen(temp) == - strlen(pattern))) { //! OCLINT prefer early exits and continue - // eliminate matches in which the chars before the option are not '-' - bool noBadCharsFound = true; - auto curr = argv[index]; - while (curr != temp) { - if (*curr++ != '-') { - noBadCharsFound = false; - break; - } - } - if (noBadCharsFound && argv[index][0] == '-') { - if (value) { - // parsing the value of an option - temp += strlen(pattern); - const unsigned len = strlen(temp); - if (len) { - *value = temp; - return true; - } - } else { - // just a flag - no value - return true; - } - } - } - } - return false; -} - -// parses an option and returns the string after the '=' character -bool -parseOption(int argc, - const char* const* argv, - const char* pattern, - String* value = nullptr, - const String& defaultVal = String()) -{ - if (value) - *value = defaultVal; -#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - // offset (normally 3 for "dt-") to skip prefix - if (parseOptionImpl( - argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) - return true; -#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - return parseOptionImpl(argc, argv, pattern, value); -} - -// locates a flag on the command line -bool -parseFlag(int argc, const char* const* argv, const char* pattern) -{ - return parseOption(argc, argv, pattern); -} - -// parses a comma separated list of words after a pattern in one of the -// arguments in argv -bool -parseCommaSepArgs(int argc, - const char* const* argv, - const char* pattern, - std::vector& res) -{ - String filtersString; - if (parseOption(argc, argv, pattern, &filtersString)) { - // tokenize with "," as a separator, unless escaped with backslash - std::ostringstream s; - auto flush = [&s, &res]() { - auto string = s.str(); - if (string.size() > 0) { - res.push_back(string.c_str()); - } - s.str(""); - }; - - bool seenBackslash = false; - const char* current = filtersString.c_str(); - const char* end = current + strlen(current); - while (current != end) { - char character = *current++; - if (seenBackslash) { - seenBackslash = false; - if (character == ',' || character == '\\') { - s.put(character); - continue; - } - s.put('\\'); - } - if (character == '\\') { - seenBackslash = true; - } else if (character == ',') { - flush(); - } else { - s.put(character); - } - } - - if (seenBackslash) { - s.put('\\'); - } - flush(); - return true; - } - return false; -} - -enum optionType -{ - option_bool, - option_int -}; - -// parses an int/bool option from the command line -bool -parseIntOption(int argc, - const char* const* argv, - const char* pattern, - optionType type, - int& res) -{ - String parsedValue; - if (!parseOption(argc, argv, pattern, &parsedValue)) - return false; - - if (type) { - // integer - // TODO: change this to use std::stoi or something else! currently it uses - // undefined behavior - assumes '0' on failed parse... - int theInt = std::atoi(parsedValue.c_str()); - if (theInt != 0) { - res = theInt; //! OCLINT parameter reassignment - return true; - } - } else { - // boolean - const char positive[][5] = { - "1", "true", "on", "yes" - }; // 5 - strlen("true") + 1 - const char negative[][6] = { - "0", "false", "off", "no" - }; // 6 - strlen("false") + 1 - - // if the value matches any of the positive/negative possibilities - for (unsigned i = 0; i < 4; i++) { - if (parsedValue.compare(positive[i], true) == 0) { - res = 1; //! OCLINT parameter reassignment - return true; - } - if (parsedValue.compare(negative[i], true) == 0) { - res = 0; //! OCLINT parameter reassignment - return true; - } - } - } - return false; -} -} // namespace - -Context::Context(int argc, const char* const* argv) - : p(new detail::ContextState) -{ - parseArgs(argc, argv, true); - if (argc) - p->binary_name = argv[0]; -} - -Context::~Context() -{ - if (g_cs == p) - g_cs = nullptr; - delete p; -} - -void -Context::applyCommandLine(int argc, const char* const* argv) -{ - parseArgs(argc, argv); - if (argc) - p->binary_name = argv[0]; -} - -// parses args -void -Context::parseArgs(int argc, const char* const* argv, bool withDefaults) -{ - using namespace detail; - - // clang-format off - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]); - // clang-format on - - int intRes = 0; - String strRes; - -#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ - if (parseIntOption(argc, \ - argv, \ - DOCTEST_CONFIG_OPTIONS_PREFIX name "=", \ - option_bool, \ - intRes) || \ - parseIntOption(argc, \ - argv, \ - DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", \ - option_bool, \ - intRes)) \ - p->var = static_cast(intRes); \ - else if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ - p->var = true; \ - else if (withDefaults) \ - p->var = default - -#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ - if (parseIntOption(argc, \ - argv, \ - DOCTEST_CONFIG_OPTIONS_PREFIX name "=", \ - option_int, \ - intRes) || \ - parseIntOption(argc, \ - argv, \ - DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", \ - option_int, \ - intRes)) \ - p->var = intRes; \ - else if (withDefaults) \ - p->var = default - -#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ - if (parseOption(argc, \ - argv, \ - DOCTEST_CONFIG_OPTIONS_PREFIX name "=", \ - &strRes, \ - default) || \ - parseOption(argc, \ - argv, \ - DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", \ - &strRes, \ - default) || \ - withDefaults) \ - p->var = strRes - - // clang-format off - DOCTEST_PARSE_STR_OPTION("out", "o", out, ""); - DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file"); - DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0); - - DOCTEST_PARSE_INT_OPTION("first", "f", first, 0); - DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX); - - DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0); - DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX); - - DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC)); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); - // clang-format on - - if (withDefaults) { - p->help = false; - p->version = false; - p->count = false; - p->list_test_cases = false; - p->list_test_suites = false; - p->list_reporters = false; - } - if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { - p->help = true; - p->exit = true; - } - if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { - p->version = true; - p->exit = true; - } - if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { - p->count = true; - p->exit = true; - } - if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { - p->list_test_cases = true; - p->exit = true; - } - if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { - p->list_test_suites = true; - p->exit = true; - } - if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { - p->list_reporters = true; - p->exit = true; - } -} - -// allows the user to add procedurally to the filters from the command line -void -Context::addFilter(const char* filter, const char* value) -{ - setOption(filter, value); -} - -// allows the user to clear all filters from the command line -void -Context::clearFilters() -{ - for (auto& curr : p->filters) - curr.clear(); -} - -// allows the user to override procedurally the bool options from the command -// line -void -Context::setOption(const char* option, bool value) -{ - setOption(option, value ? "true" : "false"); -} - -// allows the user to override procedurally the int options from the command -// line -void -Context::setOption(const char* option, int value) -{ - setOption(option, toString(value).c_str()); -} - -// allows the user to override procedurally the string options from the command -// line -void -Context::setOption(const char* option, const char* value) -{ - auto argv = String("-") + option + "=" + value; - auto lvalue = argv.c_str(); - parseArgs(1, &lvalue); -} - -// users should query this in their main() and exit the program if true -bool -Context::shouldExit() -{ - return p->exit; -} - -void -Context::setAsDefaultForAssertsOutOfTestCases() -{ - g_cs = p; -} - -void -Context::setAssertHandler(detail::assert_handler ah) -{ - p->ah = ah; -} - -void -Context::setCout(std::ostream* out) -{ - p->cout = out; -} - -static class DiscardOStream : public std::ostream -{ -private: - class : public std::streambuf - { - private: - // allowing some buffering decreases the amount of calls to overflow - char buf[1024]; - - protected: - std::streamsize xsputn(const char_type*, std::streamsize count) override - { - return count; - } - - int_type overflow(int_type ch) override - { - setp(std::begin(buf), std::end(buf)); - return traits_type::not_eof(ch); - } - } discardBuf; - -public: - DiscardOStream() - : std::ostream(&discardBuf) - { - } -} discardOut; - -// the main function that does all the filtering and test running -int -Context::run() -{ - using namespace detail; - - // save the old context state in case such was setup - for using asserts out - // of a testing context - auto old_cs = g_cs; - // this is the current contest - g_cs = p; - is_running_in_test = true; - - g_no_colors = p->no_colors; - p->resetRunData(); - - std::fstream fstr; - if (p->cout == nullptr) { - if (p->quiet) { - p->cout = &discardOut; - } else if (p->out.size()) { - // to a file if specified - fstr.open(p->out.c_str(), std::fstream::out); - p->cout = &fstr; - } else { - // stdout by default - p->cout = &std::cout; - } - } - - FatalConditionHandler::allocateAltStackMem(); - - auto cleanup_and_return = [&]() { - FatalConditionHandler::freeAltStackMem(); - - if (fstr.is_open()) - fstr.close(); - - // restore context - g_cs = old_cs; - is_running_in_test = false; - - // we have to free the reporters which were allocated when the run started - for (auto& curr : p->reporters_currently_used) - delete curr; - p->reporters_currently_used.clear(); - - if (p->numTestCasesFailed && !p->no_exitcode) - return EXIT_FAILURE; - return EXIT_SUCCESS; - }; - - // setup default reporter if none is given through the command line - if (p->filters[8].empty()) - p->filters[8].push_back("console"); - - // check to see if any of the registered reporters has been selected - for (auto& curr : getReporters()) { - if (matchesAny( - curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) - p->reporters_currently_used.push_back(curr.second(*g_cs)); - } - - // TODO: check if there is nothing in reporters_currently_used - - // prepend all listeners - for (auto& curr : getListeners()) - p->reporters_currently_used.insert(p->reporters_currently_used.begin(), - curr.second(*g_cs)); - -#ifdef DOCTEST_PLATFORM_WINDOWS - if (isDebuggerActive() && p->no_debug_output == false) - p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); -#endif // DOCTEST_PLATFORM_WINDOWS - - // handle version, help and no_run - if (p->no_run || p->version || p->help || p->list_reporters) { - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); - - return cleanup_and_return(); - } - - std::vector testArray; - for (auto& curr : getRegisteredTests()) - testArray.push_back(&curr); - p->numTestCases = testArray.size(); - - // sort the collected records - if (!testArray.empty()) { - if (p->order_by.compare("file", true) == 0) { - std::sort(testArray.begin(), testArray.end(), fileOrderComparator); - } else if (p->order_by.compare("suite", true) == 0) { - std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); - } else if (p->order_by.compare("name", true) == 0) { - std::sort(testArray.begin(), testArray.end(), nameOrderComparator); - } else if (p->order_by.compare("rand", true) == 0) { - std::srand(p->rand_seed); - - // random_shuffle implementation - const auto first = &testArray[0]; - for (size_t i = testArray.size() - 1; i > 0; --i) { - int idxToSwap = std::rand() % (i + 1); - - const auto temp = first[i]; - - first[i] = first[idxToSwap]; - first[idxToSwap] = temp; - } - } else if (p->order_by.compare("none", true) == 0) { - // means no sorting - beneficial for death tests which call into the - // executable with a specific test case in mind - we don't want to slow - // down the startup times - } - } - - std::set testSuitesPassingFilt; - - bool query_mode = p->count || p->list_test_cases || p->list_test_suites; - std::vector queryResults; - - if (!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); - - // invoke the registered functions if they match the filter criteria (or just - // count them) - for (auto& curr : testArray) { - const auto& tc = *curr; - - bool skip_me = false; - if (tc.m_skip && !p->no_skip) - skip_me = true; - - if (!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) - skip_me = true; - if (matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) - skip_me = true; - if (!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) - skip_me = true; - if (matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) - skip_me = true; - if (!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) - skip_me = true; - if (matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) - skip_me = true; - - if (!skip_me) - p->numTestCasesPassingFilters++; - - // skip the test if it is not in the execution range - if ((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || - (p->first > p->numTestCasesPassingFilters)) - skip_me = true; - - if (skip_me) { - if (!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); - continue; - } - - // do not execute the test if we are to only count the number of filter - // passing tests - if (p->count) - continue; - - // print the name of the test and don't execute it - if (p->list_test_cases) { - queryResults.push_back(&tc); - continue; - } - - // print the name of the test suite if not done already and don't execute it - if (p->list_test_suites) { - if ((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && - tc.m_test_suite[0] != '\0') { - queryResults.push_back(&tc); - testSuitesPassingFilt.insert(tc.m_test_suite); - p->numTestSuitesPassingFilters++; - } - continue; - } - - // execute the test if it passes all the filtering - { - p->currentTest = &tc; - - p->failure_flags = TestCaseFailureReason::None; - p->seconds = 0; - - // reset atomic counters - p->numAssertsFailedCurrentTest_atomic = 0; - p->numAssertsCurrentTest_atomic = 0; - - p->fullyTraversedSubcases.clear(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); - - p->timer.start(); - - bool run_test = true; - - do { - // reset some of the fields for subcases (except for the set of fully - // passed ones) - p->reachedLeaf = false; - // May not be empty if previous subcase exited via exception. - p->subcaseStack.clear(); - p->currentSubcaseDepth = 0; - - p->shouldLogCurrentException = true; - - // reset stuff for logging with INFO() - p->stringifiedContexts.clear(); - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - // MSVC 2015 diagnoses fatalConditionHandler as unused (because - // reset() is a static method) - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH( - 4101) // unreferenced local variable - FatalConditionHandler fatalConditionHandler; // Handle signals - // execute the test - tc.m_test(); - fatalConditionHandler.reset(); - DOCTEST_MSVC_SUPPRESS_WARNING_POP -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - } catch (const TestFailureException&) { - p->failure_flags |= TestCaseFailureReason::AssertFailure; - } catch (...) { - DOCTEST_ITERATE_THROUGH_REPORTERS( - test_case_exception, { translateActiveException(), false }); - p->failure_flags |= TestCaseFailureReason::Exception; - } -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - - // exit this loop if enough assertions have failed - even if there are - // more subcases - if (p->abort_after > 0 && - p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= - p->abort_after) { - run_test = false; - p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; - } - - if (!p->nextSubcaseStack.empty() && run_test) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); - if (p->nextSubcaseStack.empty()) - run_test = false; - } while (run_test); - - p->finalizeTestCaseData(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - - p->currentTest = nullptr; - - // stop executing tests if enough assertions have failed - if (p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) - break; - } - } - - if (!query_mode) { - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); - } else { - QueryData qdata; - qdata.run_stats = g_cs; - qdata.data = queryResults.data(); - qdata.num_data = unsigned(queryResults.size()); - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); - } - - return cleanup_and_return(); -} - -DOCTEST_DEFINE_INTERFACE(IReporter) - -int -IReporter::get_num_active_contexts() -{ - return detail::g_infoContexts.size(); -} -const IContextScope* const* -IReporter::get_active_contexts() -{ - return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr; -} - -int -IReporter::get_num_stringified_contexts() -{ - return detail::g_cs->stringifiedContexts.size(); -} -const String* -IReporter::get_stringified_contexts() -{ - return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] - : nullptr; -} - -namespace detail { -void -registerReporterImpl(const char* name, - int priority, - reporterCreatorFunc c, - bool isReporter) -{ - if (isReporter) - getReporters().insert( - reporterMap::value_type(reporterMap::key_type(priority, name), c)); - else - getListeners().insert( - reporterMap::value_type(reporterMap::key_type(priority, name), c)); -} -} // namespace detail - -} // namespace doctest - -#endif // DOCTEST_CONFIG_DISABLE - -#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH( - 4007) // 'function' : must be 'attribute' - see issue #182 -int -main(int argc, char** argv) -{ - return doctest::Context(argc, argv).run(); -} -DOCTEST_MSVC_SUPPRESS_WARNING_POP -#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN - -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_POP - -#endif // DOCTEST_LIBRARY_IMPLEMENTATION -#endif // DOCTEST_CONFIG_IMPLEMENT diff --git a/test/include/cnpy.hpp b/test/include/cnpy.hpp deleted file mode 100644 index 80cc0096f..000000000 --- a/test/include/cnpy.hpp +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (C) 2011 Carl Rogers -// Released under MIT License -// license available in LICENSE file, or at -// http://www.opensource.org/licenses/mit-license.php - -#ifndef PROXSUITE_TEST_CNPY_HPP -#define PROXSUITE_TEST_CNPY_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CNPY_FWD(x) static_cast(x) -#define CNPY_ASSERT(Cond) \ - ((Cond) \ - ? (void)0 \ - : ::cnpy::detail::terminate_with_message( \ - "assertion failed: " #Cond, sizeof("assertion failed: " #Cond) - 1)) - -#define CNPY_LITERAL(X) X, sizeof(X) - 1 - -namespace cnpy { -using usize = decltype(sizeof(0)); -namespace detail { - -enum struct LoadVecResult : int -{ - success = 0, - failed_file = 1, - failed_dtype = 2, - failed_ndim = 3, -}; - -enum struct LoadMatResult : int -{ - success = 0, - success_transpose = -1, - - failed_file = 1, - failed_dtype = 2, - failed_ndim = 3, -}; - -void -terminate_with_message(char const* msg, usize len); - -template -struct TypeCode; -template<> -struct TypeCode -{ - static constexpr char value = 'f'; -}; -template<> -struct TypeCode -{ - static constexpr char value = 'f'; -}; - -struct FromByteRepr -{}; -struct FromLiteral -{}; -struct FromRawParts -{}; -struct FromRange -{}; - -struct StrView -{ - char const* data; - usize size; - - StrView(FromRawParts /*tag*/, char const* data_, usize size_) noexcept - : data{ data_ } - , size{ size_ } - { - } - - template - StrView(FromRange /*tag*/, T const& str) noexcept - : data{ str.data() } - , size{ str.size() } - { - } - - template - StrView(FromByteRepr /*tag*/, T const& val) noexcept - : data{ &reinterpret_cast(val) } - , size{ sizeof(T) } - { - } - - template - constexpr StrView(FromLiteral /*tag*/, char const (&literal)[N]) noexcept - : data{ literal } - , size{ N - 1 } - { - } -}; - -} // namespace detail - -namespace detail { -inline auto -BigEndianTest() -> char -{ - int x = 1; - char buf[sizeof(x)]; - std::memcpy(&buf, &x, sizeof(x)); - return buf[0] != 0 ? '<' : '>'; -} -template -auto -create_npy_header(std::vector const& shape) -> std::vector; - -auto -create_npy_header(std::vector const& shape, - usize sizeof_T, - char type_code) -> std::vector; -void -parse_npy_header(FILE* fp, - usize& word_size, - std::vector& shape, - bool& fortran_order); -void -parse_npy_header(unsigned char* buffer, - usize& word_size, - std::vector& shape, - bool& fortran_order); - -void -npy_vsave(char const* fname, - void const* vdata, - usize sizeof_T, - char type_code, - usize const* shape, - usize ndim, - char const* mode); - -auto -npy_vload_vec(std::string const& fname, - usize sizeof_T, - void* vec, - void* (*ptr)(void*), - void (*resize)(void*, usize rows)) -> LoadVecResult; -auto -npy_vload_mat(std::string const& fname, - usize sizeof_T, - void* vec, - void* (*ptr)(void*), - void (*resize)(void*, usize rows, usize cols)) -> LoadMatResult; -} // namespace detail - -template -void -npy_save_mat(std::string const& fname, - Eigen::MatrixBase const& mat, - std::string const& mode = "w") -{ - - auto const& eval = mat.eval(); - usize rowcol[] = { usize(eval.rows()), usize(eval.cols()) }; - - using T = typename D::Scalar; - - detail::npy_vsave( // - fname.c_str(), - eval.data(), - sizeof(T), - detail::TypeCode::value, - &rowcol[0], - 2, - mode.c_str()); -} - -template -void -npy_save_vec(std::string const& fname, - Eigen::MatrixBase const& vec, - const std::string& mode = "w") -{ - - auto const& eval = vec.eval(); - using T = typename D::Scalar; - CNPY_ASSERT(vec.cols() == 1); - usize size = vec.rows(); - - detail::npy_vsave( // - fname.c_str(), - vec.data(), - sizeof(T), - detail::TypeCode::value, - &size, - 1, - mode.c_str()); -} - -template -auto -npy_load_vec(std::string const& fname) -> Eigen::Matrix -{ - using Vec = Eigen::Matrix; - Vec out; - - using Res = detail::LoadVecResult; - using detail::terminate_with_message; - - Res res = detail::npy_vload_vec( // - fname.c_str(), - sizeof(T), - std::addressof(out), - +[](void* vec) -> void* { return static_cast(vec)->data(); }, - +[](void* vec, usize rows) -> void { - static_cast(vec)->resize(Eigen::Index(rows), 1); - }); - - if (res == Res::failed_file) { - terminate_with_message(CNPY_LITERAL("libnpy: could not load file")); - } - if (res == Res::failed_dtype) { - terminate_with_message(CNPY_LITERAL("libnpy: mismatching scalar type")); - } - if (res == Res::failed_ndim) { - char buf[4096]; - usize len = usize( - std::snprintf(&buf[0], - 4096, - "libnpy: wrong number of dimensions. expected %zu, got %zu", - usize{ 2 }, - usize(res) - usize(Res::failed_ndim))); - CNPY_ASSERT(len + 1 < 4096); - terminate_with_message(&buf[0], len); - } - return out; -} - -template -auto -npy_load_mat(std::string const& fname) - -> Eigen::Matrix -{ - using Mat = Eigen::Matrix; - Mat out; - - using Res = detail::LoadMatResult; - using detail::terminate_with_message; - - Res res = detail::npy_vload_mat( // - fname.c_str(), - sizeof(T), - std::addressof(out), - +[](void* mat) -> void* { return static_cast(mat)->data(); }, - +[](void* mat, usize rows, usize cols) -> void { - static_cast(mat)->resize(Eigen::Index(rows), Eigen::Index(cols)); - }); - - if (res == Res::failed_file) { - terminate_with_message(CNPY_LITERAL("libnpy: could not load file")); - } - if (res == Res::failed_dtype) { - terminate_with_message(CNPY_LITERAL("libnpy: mismatching scalar type")); - } - if (res == Res::failed_ndim) { - char buf[4096]; - usize len = usize( - std::snprintf(&buf[0], - 4096, - "libnpy: wrong number of dimensions. expected %zu, got %zu", - usize{ 2 }, - usize(res) - usize(Res::failed_ndim))); - CNPY_ASSERT(len + 1 < 4096); - terminate_with_message(&buf[0], len); - } - if (res == Res::success_transpose) { - auto rowmajor = Eigen::Map< // - Eigen::Matrix< // - T, // - Eigen::Dynamic, // - Eigen::Dynamic, // - Eigen::RowMajor // - > // - >{ - out.data(), - out.rows(), - out.cols(), - }; - Mat tmp = rowmajor; - out = tmp; - } - return out; -} - -extern template auto -npy_load_mat(std::string const&) - -> Eigen::Matrix; -extern template auto -npy_load_mat(std::string const&) - -> Eigen::Matrix; - -extern template auto -npy_load_vec(std::string const&) - -> Eigen::Matrix; -extern template auto -npy_load_vec(std::string const&) - -> Eigen::Matrix; - -} // namespace cnpy - -#endif /* end of include guard PROXSUITE_TEST_CNPY_HPP */ diff --git a/test/include/utils.hpp b/test/include/utils.hpp deleted file mode 100644 index 490d0622a..000000000 --- a/test/include/utils.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "util_f32.hpp" -#include "util_f64.hpp" diff --git a/test/packaging/cmake-components/CMakeLists.txt b/test/packaging/cmake-components/CMakeLists.txt new file mode 100644 index 000000000..507670720 --- /dev/null +++ b/test/packaging/cmake-components/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.22) + +project(myproject) +find_package(proxsuite CONFIG REQUIRED COMPONENTS proxsuite vectorized) + +add_executable(run-proxqp ${CMAKE_CURRENT_LIST_DIR}/../src/run-proxqp.cpp) +target_link_libraries(run-proxqp PUBLIC proxsuite::proxsuite-vectorized) diff --git a/test/packaging/cmake/CMakeLists.txt b/test/packaging/cmake/CMakeLists.txt index 4699225ca..cc3dcc513 100644 --- a/test/packaging/cmake/CMakeLists.txt +++ b/test/packaging/cmake/CMakeLists.txt @@ -1,8 +1,7 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.22) -project(ExternalLib CXX) +project(myproject) find_package(proxsuite REQUIRED) -set(CMAKE_CXX_STANDARD 17) add_executable(run-proxqp ${CMAKE_CURRENT_LIST_DIR}/../src/run-proxqp.cpp) target_link_libraries(run-proxqp PUBLIC proxsuite::proxsuite) diff --git a/test/packaging/external/CMakeLists.txt b/test/packaging/external/CMakeLists.txt deleted file mode 100644 index ed21543ee..000000000 --- a/test/packaging/external/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 3.22) -project(ExtraLib CXX) - -message(STATUS "PROXSUITE_GIT_REPOSITORY: $ENV{PROXSUITE_GIT_REPOSITORY}") -message(STATUS "PROXSUITE_GIT_TAG: $ENV{PROXSUITE_GIT_TAG}") - -include(FetchContent) -FetchContent_Declare( - proxsuite-c++ - GIT_REPOSITORY $ENV{PROXSUITE_GIT_REPOSITORY} - GIT_TAG $ENV{PROXSUITE_GIT_TAG} - GIT_SHALLOW ON -) -FetchContent_MakeAvailable(proxsuite-c++) - -add_executable(run-proxqp ${CMAKE_CURRENT_LIST_DIR}/../src/run-proxqp.cpp) -target_link_libraries(run-proxqp PUBLIC proxsuite) diff --git a/test/packaging/fetchcontent/CMakeLists.txt b/test/packaging/fetchcontent/CMakeLists.txt new file mode 100644 index 000000000..bc779d521 --- /dev/null +++ b/test/packaging/fetchcontent/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.22) +project(myproject) + +cmake_path( + CONVERT "${PROXSUITE_FETCHCONTENT_SOURCE_DIR}" + TO_CMAKE_PATH_LIST PROXSUITE_FETCHCONTENT_SOURCE_DIR + NORMALIZE +) +message(STATUS "PROXSUITE_FETCHCONTENT_SOURCE_DIR: ${PROXSUITE_FETCHCONTENT_SOURCE_DIR}") + +include(FetchContent) +FetchContent_Declare(proxsuite SOURCE_DIR ${PROXSUITE_FETCHCONTENT_SOURCE_DIR}) +FetchContent_MakeAvailable(proxsuite) + +add_executable(run-proxqp ${CMAKE_CURRENT_LIST_DIR}/../src/run-proxqp.cpp) +target_link_libraries(run-proxqp PUBLIC proxsuite::proxsuite) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt new file mode 100644 index 000000000..e3f7dc886 --- /dev/null +++ b/test/python/CMakeLists.txt @@ -0,0 +1,27 @@ +function(proxsuite_python_add_test name) + add_test( + NAME proxsuite-test-python.${name} + COMMAND $ ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py + ) + set_tests_properties( + proxsuite-test-python.${name} + PROPERTIES + ENVIRONMENT_MODIFICATION "PYTHONPATH=path_list_prepend:$/.." + LABELS python + ) +endfunction() + +proxsuite_python_add_test(test_cvxpy) +proxsuite_python_add_test(test_dense_qp_solve) +proxsuite_python_add_test(test_dense_qp_wrapper) + +if(BUILD_WITH_OPENMP_SUPPORT) + proxsuite_python_add_test(test_parallel_qp_solve) +endif() + +if(PROXSUITE_BUILD_WITH_SERIALIZATION) + proxsuite_python_add_test(test_serialization) +endif() + +proxsuite_python_add_test(test_sparse_qp_solve) +proxsuite_python_add_test(test_sparse_qp_wrapper) diff --git a/test/src/cvxpy.py b/test/python/test_cvxpy.py similarity index 100% rename from test/src/cvxpy.py rename to test/python/test_cvxpy.py diff --git a/test/src/dense_qp_solve.py b/test/python/test_dense_qp_solve.py similarity index 100% rename from test/src/dense_qp_solve.py rename to test/python/test_dense_qp_solve.py diff --git a/test/src/dense_qp_wrapper.py b/test/python/test_dense_qp_wrapper.py similarity index 99% rename from test/src/dense_qp_wrapper.py rename to test/python/test_dense_qp_wrapper.py index 844224009..65250c3d2 100644 --- a/test/src/dense_qp_wrapper.py +++ b/test/python/test_dense_qp_wrapper.py @@ -4,6 +4,7 @@ import proxsuite import numpy as np import scipy.sparse as spa +import scipy.sparse.linalg as spla import unittest np.printoptions(precision=16) @@ -4844,7 +4845,7 @@ def test_minimal_eigenvalue_estimation_nonconvex_eigen_option( 10000, ) ) - vals, _ = spa.linalg.eigs(H, which="SR") + vals, _ = spla.eigs(H, which="SR") min_eigenvalue = float(np.min(vals)) qp.init( H, @@ -4876,7 +4877,7 @@ def test_minimal_eigenvalue_estimation_nonconvex_manual_option( qp = proxsuite.proxqp.dense.QP(n, n_eq, n_in) qp.settings.verbose = False qp.settings.initial_guess = proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS - vals, _ = spa.linalg.eigs(H, which="SR") + vals, _ = spla.eigs(H, which="SR") min_eigenvalue = float(np.min(vals)) qp.init( H, @@ -4917,7 +4918,7 @@ def test_minimal_eigenvalue_estimation_nonconvex_power_iter_option( 10000, ) ) - vals, _ = spa.linalg.eigs(H, which="SR") + vals, _ = spla.eigs(H, which="SR") min_eigenvalue = float(np.min(vals)) qp.init( H, diff --git a/test/src/parallel_qp_solve.py b/test/python/test_parallel_qp_solve.py similarity index 100% rename from test/src/parallel_qp_solve.py rename to test/python/test_parallel_qp_solve.py diff --git a/test/src/serialization.py b/test/python/test_serialization.py similarity index 100% rename from test/src/serialization.py rename to test/python/test_serialization.py diff --git a/test/src/sparse_qp_solve.py b/test/python/test_sparse_qp_solve.py similarity index 100% rename from test/src/sparse_qp_solve.py rename to test/python/test_sparse_qp_solve.py diff --git a/test/src/sparse_qp_wrapper.py b/test/python/test_sparse_qp_wrapper.py similarity index 99% rename from test/src/sparse_qp_wrapper.py rename to test/python/test_sparse_qp_wrapper.py index bd79834db..36734f5a4 100644 --- a/test/src/sparse_qp_wrapper.py +++ b/test/python/test_sparse_qp_wrapper.py @@ -4,6 +4,7 @@ import proxsuite import numpy as np import scipy.sparse as spa +import scipy.sparse.linalg as spla import unittest @@ -4642,7 +4643,7 @@ def test_sparse_infeasibility_solving( # qp.settings.estimate_method_option = ( # proxsuite.proxqp.EigenValueEstimateMethodOption.EigenRegularization # ) - # vals, _ = spa.linalg.eigs(H, which="SR") + # vals, _ = spla.eigs(H, which="SR") # min_eigenvalue = float(np.min(vals)) # qp.init( # H, @@ -4676,7 +4677,7 @@ def test_minimal_eigenvalue_estimation_nonconvex_manual_option( qp = proxsuite.proxqp.sparse.QP(n, n_eq, n_in) qp.settings.verbose = False qp.settings.initial_guess = proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS - vals, _ = spa.linalg.eigs(H, which="SR") + vals, _ = spla.eigs(H, which="SR") min_eigenvalue = float(np.min(vals)) qp.init( H, @@ -4711,7 +4712,7 @@ def test_minimal_eigenvalue_estimation_nonconvex_power_iter_option( estimate_minimal_eigen_value = proxsuite.proxqp.sparse.estimate_minimal_eigen_value_of_symmetric_matrix( H, 1.0e-10, 100000 ) - vals, _ = spa.linalg.eigs(H, which="SR") + vals, _ = spla.eigs(H, which="SR") min_eigenvalue = float(np.min(vals)) qp.init( H, @@ -4723,7 +4724,7 @@ def test_minimal_eigenvalue_estimation_nonconvex_power_iter_option( np.asfortranarray(u), manual_minimal_H_eigenvalue=estimate_minimal_eigen_value, ) - # vals_bis, _ = spa.linalg.eigs(H, which="LM") + # vals_bis, _ = spla.eigs(H, which="LM") # print(f"{vals_bis}=") # print(f"{vals}=") # print(f"{min_eigenvalue=}") diff --git a/test/src/backward.cpp b/test/src/backward.cpp deleted file mode 100644 index 34dcf2b72..000000000 --- a/test/src/backward.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include - -namespace backward { -SignalHandling const sh; -} // namespace backward diff --git a/test/src/cnpy.cpp b/test/src/cnpy.cpp deleted file mode 100644 index 0f0ac2562..000000000 --- a/test/src/cnpy.cpp +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright (C) 2011 Carl Rogers -// Released under MIT License -// license available in LICENSE file, or at -// http://www.opensource.org/licenses/mit-license.php - -#include "cnpy.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace cnpy { -namespace detail { - -struct File -{ - File(File&& rhs) noexcept - : ptr(rhs.ptr) - { - rhs.ptr = nullptr; - } - File(File const&) = delete; - auto operator=(File&& rhs) noexcept -> File& - { - - // put rhs in temporary to handle aliasing - File tmp = CNPY_FWD(rhs); - - // clear current File - { - File tmp2 = static_cast(*this); - } - - ptr = tmp.ptr; - tmp.ptr = nullptr; - - return *this; - } - auto operator=(File const&) -> File& = delete; - - std::FILE* ptr; - File(char const* fname, char const* mode) - : ptr{ std::fopen(fname, mode) } - { - } - ~File() noexcept - { - if (ptr != nullptr) { - std::fclose(ptr); - } - } -}; - -void -terminate_with_message(char const* msg, usize len) -{ - std::fwrite(msg, 1, len, stderr); - std::fputc('\n', stderr); - std::terminate(); -} - -void -append_bytes(std::vector& lhs, StrView rhs) -{ - usize old_size = lhs.size(); - lhs.resize(old_size + rhs.size); - std::memcpy(lhs.data() + old_size, rhs.data, rhs.size); -} -void -npy_vsave(char const* fname, - void const* vdata, - usize sizeof_T, - char type_code, - usize const* shape, - usize ndim, - char const* mode) -{ - - std::FILE* fp{}; - std::vector - true_data_shape; // if appending, the shape of existing + new data - - if (std::strcmp(mode, "a") == 0) { - fp = std::fopen(fname, "r+b"); // NOLINT - } - - if (fp != nullptr) { - // file exists. we need to append to it. read the header, modify the array - // size - usize word_size = 0; - bool fortran_order = false; - detail::parse_npy_header(fp, word_size, true_data_shape, fortran_order); - CNPY_ASSERT(!fortran_order); - - if (word_size != sizeof_T) { - std::fprintf( // NOLINT - stderr, - "libnpy error: %s has word size %zu but npy_save is appending data " - "sized %zu\n", - fname, - word_size, - sizeof_T); - - CNPY_ASSERT(word_size == sizeof_T); - } - if (true_data_shape.size() != ndim) { - std::fprintf( // NOLINT - stderr, - "libnpy error: npy_save attempting to append misdimensioned data to " - "%s\n", - fname); - - CNPY_ASSERT(true_data_shape.size() != ndim); - } - - for (usize i = 1; i < ndim; i++) { - if (shape[i] != true_data_shape[i]) { - std::fprintf( // NOLINT - stderr, - "libnpy error: npy_save attempting to append misshaped data to " - "%s\n", - fname); - - CNPY_ASSERT(shape[i] == true_data_shape[i]); - } - } - true_data_shape[0] += shape[0]; - } else { - fp = std::fopen(fname, "wb"); // NOLINT - true_data_shape = {}; - true_data_shape.insert(true_data_shape.end(), shape, shape + ndim); - } - - std::vector header = - detail::create_npy_header(true_data_shape, sizeof_T, type_code); - usize nels = - usize(std::accumulate(shape, shape + ndim, 1, std::multiplies())); - - std::fseek(fp, 0, SEEK_SET); - std::fwrite(&header[0], sizeof(char), header.size(), fp); - std::fseek(fp, 0, SEEK_END); - std::fwrite(vdata, sizeof_T, nels, fp); - std::fclose(fp); -} -auto -create_npy_header(std::vector const& shape, - usize sizeof_T, - char type_code) -> std::vector -{ - - std::vector dict; - detail::append_bytes(dict, { FromLiteral{}, "{'descr': '" }); - detail::append_bytes(dict, { FromByteRepr{}, detail::BigEndianTest() }); - detail::append_bytes(dict, { FromByteRepr{}, type_code }); - { - auto str = std::to_string(sizeof_T); - detail::append_bytes(dict, { FromRange{}, std::to_string(sizeof_T) }); - } - detail::append_bytes( - dict, { FromLiteral{}, "', 'fortran_order': False, 'shape': (" }); - detail::append_bytes(dict, { FromRange{}, std::to_string(shape[0]) }); - for (usize i = 1; i < shape.size(); i++) { - detail::append_bytes(dict, { FromLiteral{}, ", " }); - detail::append_bytes(dict, { FromRange{}, std::to_string(shape[i]) }); - } - if (shape.size() == 1) { - detail::append_bytes(dict, { FromLiteral{}, ", " }); - } - detail::append_bytes(dict, { FromLiteral{}, "), }" }); - - // pad with spaces so that preamble+dict is modulo 16 bytes. preamble is 10 - // bytes. dict needs to end with \n - usize remainder = 16 - (10 + dict.size()) % 16; - dict.insert(dict.end(), remainder, ' '); - dict.back() = '\n'; - - std::vector header; - detail::append_bytes(header, { FromLiteral{}, "\x93NUMPY\x01\x00" }); - detail::append_bytes(header, { FromByteRepr{}, uint16_t(dict.size()) }); - detail::append_bytes(header, { FromRange{}, dict }); - - return header; -} - -void -parse_npy_header(std::FILE* fp, - usize& word_size, - std::vector& shape, - bool& fortran_order) -{ - char buffer[256]; - CNPY_ASSERT(std::fread(&buffer[0], sizeof(char), 11, fp) == 11); - std::string header = std::fgets(&buffer[0], 256, fp); - CNPY_ASSERT(header[header.size() - 1] == '\n'); - - usize loc1 = 0; - usize loc2 = 0; - - // fortran order - loc1 = header.find("fortran_order"); - CNPY_ASSERT( - !(loc1 == std::string::npos) && - "parse_npy_header: failed to find header keyword: 'fortran_order'"); - loc1 += 16; - fortran_order = (header.substr(loc1, 4) == "True"); - - // shape - loc1 = header.find('('); - loc2 = header.find(')'); - CNPY_ASSERT(!(loc1 == std::string::npos || loc2 == std::string::npos) && - "parse_npy_header: failed to find header keyword: '(' or ')'"); - - std::regex num_regex("[0-9][0-9]*"); - std::smatch sm; - shape.clear(); - - std::string str_shape = header.substr(loc1 + 1, loc2 - loc1 - 1); - while (std::regex_search(str_shape, sm, num_regex)) { - shape.push_back(std::stoul(sm[0].str())); - str_shape = sm.suffix().str(); - } - - // endian, word size, data type - // byte order code | stands for not applicable. - // not sure when this applies except for byte array - loc1 = header.find("descr"); - CNPY_ASSERT(!(loc1 == std::string::npos) && - "parse_npy_header: failed to find header keyword: 'descr'"); - loc1 += 9; - bool littleEndian = (header[loc1] == '<' || header[loc1] == '|'); - CNPY_ASSERT(littleEndian); - - char type = header[loc1 + 1]; - CNPY_ASSERT(type == 'f'); - - std::string str_ws = header.substr(loc1 + 2); - loc2 = str_ws.find('\''); - word_size = std::stoul(str_ws.substr(0, loc2)); -} - -auto -load_npy_vec(std::FILE* fp, - usize sizeof_T, - void* vec, - void* (*ptr)(void*), - void (*resize)(void*, usize rows)) -> LoadVecResult -{ - std::vector shape; - - usize word_size{}; - bool fortran_order{}; - - cnpy::detail::parse_npy_header(fp, word_size, shape, fortran_order); - if (word_size != sizeof_T) { - return LoadVecResult::failed_dtype; - } - if (shape.size() != 1) { - return LoadVecResult(int(LoadVecResult::failed_ndim) + shape.size()); - } - - usize nbytes = word_size * shape[0]; - resize(vec, shape[0]); - - CNPY_ASSERT(std::fread(ptr(vec), 1, nbytes, fp) == nbytes && - "load_the_npy_file: failed fread"); - return LoadVecResult::success; -} - -auto -load_npy_mat(std::FILE* fp, - usize sizeof_T, - void* vec, - void* (*ptr)(void*), - void (*resize)(void*, usize rows, usize cols)) -> LoadMatResult -{ - std::vector shape; - - usize word_size{}; - bool fortran_order{}; - - cnpy::detail::parse_npy_header(fp, word_size, shape, fortran_order); - if (word_size != sizeof_T) { - return LoadMatResult::failed_dtype; - } - if (shape.size() != 2) { - return LoadMatResult(int(LoadMatResult::failed_ndim) + shape.size()); - } - usize nbytes = word_size * shape[0] * shape[1]; - resize(vec, shape[0], shape[1]); - - CNPY_ASSERT(std::fread(ptr(vec), 1, nbytes, fp) == nbytes && - "load_the_npy_file: failed fread"); - - if (fortran_order) { - return LoadMatResult::success; - } else { - return LoadMatResult::success_transpose; - } -} - -auto -npy_vload_vec(std::string const& fname, - usize sizeof_T, - void* vec, - void* (*ptr)(void*), - void (*resize)(void*, usize rows)) -> LoadVecResult -{ - File fp{ fname.c_str(), "rb" }; // NOLINT - - CNPY_ASSERT(fp.ptr != nullptr); - return detail::load_npy_vec(fp.ptr, sizeof_T, vec, ptr, resize); -} - -auto -npy_vload_mat(std::string const& fname, - usize sizeof_T, - void* vec, - void* (*ptr)(void*), - void (*resize)(void*, usize rows, usize cols)) -> LoadMatResult -{ - File fp{ fname.c_str(), "rb" }; // NOLINT - - CNPY_ASSERT(fp.ptr != nullptr); - return detail::load_npy_mat(fp.ptr, sizeof_T, vec, ptr, resize); -} -} // namespace detail - -template auto -npy_load_mat(std::string const&) - -> Eigen::Matrix; -template auto -npy_load_mat(std::string const&) - -> Eigen::Matrix; - -template auto -npy_load_vec(std::string const&) - -> Eigen::Matrix; -template auto -npy_load_vec(std::string const&) - -> Eigen::Matrix; -} // namespace cnpy From 38fe4438b2e38558d5e2d5bf28366cea4801c2af Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Wed, 7 Oct 2026 13:13:23 +0200 Subject: [PATCH 2/3] changelog: Fix entry --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba0019485..9f4ebb05a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Removed - CMake: remove unconditional `DOXYGEN_USE_MATHJAX`. You can turn it on if necessary with `cmake -DDOXYGEN_USE_MATHJAX=ON`. ([#467](https://github.com/Simple-Robotics/proxsuite/pull/467)) +### Changed +- Switch to [JRL CMake modules v2](https://github.com/jrl-umi3218/jrl-cmakemodules/) ([#437](https://github.com/Simple-Robotics/proxsuite/pull/437)) + ## [0.7.3] - 2026-05-11 ### Added @@ -28,7 +31,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Upgraded nanobind dependency version (submodule) to v2.9.2 ([#418](https://github.com/Simple-Robotics/proxsuite/pull/418)) - Better dynamic module handling ([#419](https://github.com/Simple-Robotics/proxsuite/pull/419)) - Fix `SyntaxError` on importing `proxsuite.torch.qplayer` caused by invalid escape sequences in the `QPFunction` docstring ([#458](https://github.com/Simple-Robotics/proxsuite/pull/461)) -- Switch to [JRL CMake modules v2](https://github.com/jrl-umi3218/jrl-cmakemodules/pull/798) ([#28](https://github.com/Simple-Robotics/nanoeigenpy/pull/28)) ### Fixed - Correction of the status update for `PROXQP_SOLVED_CLOSEST_PRIMAL_FEASIBLE` ([#432](https://github.com/Simple-Robotics/proxsuite/pull/432)) From 97b52f3984f6f58e29bc6e705d82928c7c7c351b Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Thu, 8 Oct 2026 10:21:58 +0200 Subject: [PATCH 3/3] ci: Downgrade to Windows 2022 to check regression --- .github/workflows/ci-pixi.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-pixi.yml b/.github/workflows/ci-pixi.yml index bce3a21ac..91f24a250 100644 --- a/.github/workflows/ci-pixi.yml +++ b/.github/workflows/ci-pixi.yml @@ -32,7 +32,7 @@ jobs: build_type: [Release, Debug] cxx_std: [17, 20] pixi_environment: [default] - os: [ubuntu-24.04, macos-15-intel, macos-26, windows-2025] + os: [ubuntu-24.04, macos-15-intel, macos-26, windows-2022] steps: - uses: actions/checkout@v6 @@ -54,7 +54,7 @@ jobs: run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps build --verbose --parallel 1 - name: Run C++ tests - if: ${{ !(startsWith(matrix.os, 'windows-') && matrix.build_type == 'Debug') }} + # if: ${{ !(startsWith(matrix.os, 'windows-') && matrix.build_type == 'Debug') }} run: pixi run -e ${{ matrix.pixi_environment }} --skip-deps test - name: Install @@ -74,7 +74,7 @@ jobs: # strategy: # fail-fast: false # matrix: - # os: [ubuntu-24.04, macos-15-intel, macos-26, windows-2025] + # os: [ubuntu-24.04, macos-15-intel, macos-26, windows-2022] # runs-on: ${{ matrix.os }} # steps: # - uses: actions/checkout@v6