diff --git a/.github/workflows/dockercentos.yml b/.github/workflows/dockercentos.yml index e1f1a799..770f2b30 100644 --- a/.github/workflows/dockercentos.yml +++ b/.github/workflows/dockercentos.yml @@ -2,8 +2,9 @@ on: push: branches: - - codac2 - - codac2_codac4matlab + - codac1 + - codac2 + - codac2_codac4matlab tags: '' # Restrict to blank tags pull_request: @@ -32,8 +33,10 @@ jobs: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes if: (matrix.cfg.arch!='x86_64')&&(matrix.cfg.arch!='i386') - run: | - chmod a+x scripts/docker/build_pybinding.sh - docker run ${{ matrix.cfg.docker_flags }} --rm -v `pwd`:/io ${{ matrix.cfg.img }} /io/scripts/docker/build_pybinding.sh + chmod a+x scripts/docker/*.sh + if [ ${{ github.ref_name }} = 'codac2_codac4matlab' ] || [ ${{ github.event.pull_request.base.ref }} = 'codac2_codac4matlab' ]; then docker run ${{ matrix.cfg.docker_flags }} --rm -v `pwd`:/io ${{ matrix.cfg.img }} /io/scripts/docker/build_pybinding_codac4matlab.sh + else docker run ${{ matrix.cfg.docker_flags }} --rm -v `pwd`:/io ${{ matrix.cfg.img }} /io/scripts/docker/build_pybinding.sh + fi ls wheelhouse - uses: xresloader/upload-to-github-release@v1 env: @@ -42,4 +45,4 @@ jobs: file: "wheelhouse/*.whl" overwrite: true tag_name: autotagname-${{ github.sha }} - if: (github.event_name!='pull_request')&&((github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) + if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) diff --git a/.github/workflows/dockermatrix.yml b/.github/workflows/dockermatrix.yml index fcb20b5d..c91d623e 100644 --- a/.github/workflows/dockermatrix.yml +++ b/.github/workflows/dockermatrix.yml @@ -1,10 +1,16 @@ # This file checks that the lib runs on ARM on: push: - branches: 'codac2' + branches: + - codac1 + - codac2 + # The following is implied by above selection... + #branches-ignore: + #- codac2_codac4matlab tags: '' # Restrict to blank tags pull_request: - branches: 'codac2' + branches-ignore: + - codac2_codac4matlab jobs: dockermatrix: @@ -63,12 +69,13 @@ jobs: git config --global --add safe.directory ${PWD} && \ if [ ${{ matrix.cfg.deb }} = true ]; then \ sudo sh -c 'echo \"deb [trusted=yes] https://packages.ensta-bretagne.fr/\$(if [ -z \"\$(. /etc/os-release && echo \$UBUNTU_CODENAME)\" ]; then echo debian/\$(. /etc/os-release && echo \$VERSION_CODENAME); else echo ubuntu/\$(. /etc/os-release && echo \$UBUNTU_CODENAME); fi) ./\" > /etc/apt/sources.list.d/ensta-bretagne.list' && \ - sudo apt-get -q update ; sudo apt-get -y install libeigen3-dev dpkg-dev || true && \ - wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/libibex-dev-2.8.9.20240417-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb --no-check-certificate -nv && \ - sudo dpkg -i libibex-dev-2.8.9.20240417-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb && \ - rm -Rf libibex-dev-2.8.9.20240417-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb ; \ + #sudo apt-get -q update ; sudo apt-get -y install libeigen3-dev dpkg-dev || true && \\ + sudo apt-get -q update ; sudo apt-get -y install dpkg-dev || true && \ + wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/libibex-dev-2.8.9.20241117-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb --no-check-certificate -nv && \ + sudo dpkg -i libibex-dev-2.8.9.20241117-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb && \ + rm -Rf libibex-dev-2.8.9.20241117-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb ; \ else \ - wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip --no-check-certificate -nv && \ + wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip --no-check-certificate -nv && \ unzip -q ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip && \ rm -Rf ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip && \ sudo cp -Rf ibex/* /usr/ ; \ @@ -112,4 +119,4 @@ jobs: file: "*.zip;*.deb" overwrite: true tag_name: autotagname-${{ github.sha }} - if: (github.event_name != 'pull_request') + if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) diff --git a/.github/workflows/macosmatrix.yml b/.github/workflows/macosmatrix.yml index edc85f60..057d5408 100644 --- a/.github/workflows/macosmatrix.yml +++ b/.github/workflows/macosmatrix.yml @@ -2,8 +2,9 @@ on: push: branches: - - codac2 - - codac2_codac4matlab + - codac1 + - codac2 + - codac2_codac4matlab tags: '' # Restrict to blank tags pull_request: @@ -20,20 +21,22 @@ jobs: fail-fast: false matrix: cfg: + - { os: macos-14, shell: bash, arch: arm64, runtime: sonoma, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 13, desc: 'macOS Sonoma Python 3.13 arm64' } - { os: macos-14, shell: bash, arch: arm64, runtime: sonoma, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 12, desc: 'macOS Sonoma Python 3.12 arm64' } - { os: macos-14, shell: bash, arch: arm64, runtime: sonoma, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 11, desc: 'macOS Sonoma Python 3.11 arm64' } - - { os: macos-12, shell: bash, arch: arm64, runtime: monterey, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 10, cross: true, desc: 'macOS Monterey Python 3.10 arm64 (cross)' } - - { os: macos-12, shell: bash, arch: arm64, runtime: monterey, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 9, cross: true, desc: 'macOS Monterey Python 3.9 arm64 (cross)' } - - { os: macos-12, shell: bash, arch: arm64, runtime: monterey, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 8, cross: true, desc: 'macOS Monterey Python 3.8 arm64 (cross)' } - - { os: macos-12, shell: bash, arch: arm64, runtime: monterey, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: 'm-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 7, cross: true, desc: 'macOS Monterey Python 3.7 arm64 (cross)' } - - { os: macos-12, shell: bash, arch: arm64, runtime: monterey, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: 'm-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 6, cross: true, desc: 'macOS Monterey Python 3.6 arm64 (cross)' } - - { os: macos-12, shell: bash, arch: x86_64, runtime: monterey, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 12, desc: 'macOS Monterey Python 3.12 x86_64' } - - { os: macos-12, shell: bash, arch: x86_64, runtime: monterey, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 11, desc: 'macOS Monterey Python 3.11 x86_64' } - - { os: macos-12, shell: bash, arch: x86_64, runtime: monterey, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 10, desc: 'macOS Monterey Python 3.10 x86_64' } - - { os: macos-12, shell: bash, arch: x86_64, runtime: monterey, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 9, desc: 'macOS Monterey Python 3.9 x86_64' } - - { os: macos-12, shell: bash, arch: x86_64, runtime: monterey, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 8, desc: 'macOS Monterey Python 3.8 x86_64' } - - { os: macos-12, shell: bash, arch: x86_64, runtime: monterey, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: 'm-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 7, desc: 'macOS Monterey Python 3.7 x86_64' } - - { os: macos-12, shell: bash, arch: x86_64, runtime: monterey, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: 'm-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 6, desc: 'macOS Monterey Python 3.6 x86_64' } # Was 10.14 because of error $MACOSX_DEPLOYMENT_TARGET mismatch: now "10.9" but "10.14" during configure. Now 10.16 due to C++20 problems... + - { os: macos-13, shell: bash, arch: arm64, runtime: ventura, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 10, cross: true, desc: 'macOS Ventura Python 3.10 arm64 (cross)' } + - { os: macos-13, shell: bash, arch: arm64, runtime: ventura, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 9, cross: true, desc: 'macOS Ventura Python 3.9 arm64 (cross)' } + - { os: macos-13, shell: bash, arch: arm64, runtime: ventura, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: '-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 8, cross: true, desc: 'macOS Ventura Python 3.8 arm64 (cross)' } + - { os: macos-13, shell: bash, arch: arm64, runtime: ventura, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: 'm-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 7, cross: true, desc: 'macOS Ventura Python 3.7 arm64 (cross)' } + - { os: macos-13, shell: bash, arch: arm64, runtime: ventura, cmake_flags: '-fPIC', trgt: '11.0', cpcfg: 'm-macosx_11_0_arm64', py_v_maj: 3, py_v_min: 6, cross: true, desc: 'macOS Ventura Python 3.6 arm64 (cross)' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 13, desc: 'macOS Ventura Python 3.13 x86_64' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 12, desc: 'macOS Ventura Python 3.12 x86_64' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 11, desc: 'macOS Ventura Python 3.11 x86_64' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 10, desc: 'macOS Ventura Python 3.10 x86_64' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 9, desc: 'macOS Ventura Python 3.9 x86_64' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: '-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 8, desc: 'macOS Ventura Python 3.8 x86_64' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: 'm-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 7, desc: 'macOS Ventura Python 3.7 x86_64' } + - { os: macos-13, shell: bash, arch: x86_64, runtime: ventura, cmake_flags: '-fPIC', trgt: '10.16', cpcfg: 'm-macosx_10_16_x86_64', py_v_maj: 3, py_v_min: 6, desc: 'macOS Ventura Python 3.6 x86_64' } # Was 10.14 because of error $MACOSX_DEPLOYMENT_TARGET mismatch: now "10.9" but "10.14" during configure. Now 10.16 due to C++20 problems... name: ${{ matrix.cfg.desc }} steps: - uses: actions/checkout@v4 @@ -52,12 +55,12 @@ jobs: if: matrix.cfg.py_v_maj!='' - run: echo "VERBOSE=1" >> $GITHUB_ENV shell: bash - - run: brew install eigen - if: runner.os=='macOS' + #- run: brew install eigen + # if: runner.os=='macOS' - run: brew install graphviz ; brew install --formula doxygen ; python -m pip install --upgrade pip ; pip install --upgrade wheel setuptools sphinx breathe sphinx_rtd_theme sphinx-tabs sphinx-issues sphinx-reredirects if: runner.os=='macOS' - run: | - wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip --no-check-certificate -nv + wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip --no-check-certificate -nv unzip -q ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip rm -Rf ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip sudo cp -Rf ibex/* /usr/local/ @@ -76,7 +79,7 @@ jobs: file: "*.whl" overwrite: true tag_name: autotagname-${{ github.sha }} - if: (github.event_name!='pull_request')&&((github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) + if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) - run: | pip install --no-deps --no-index *.whl python -c "import sys; print(sys.version)" ; python examples/02_centered_form/main.py @@ -85,4 +88,4 @@ jobs: cd build && ctest -C Release -V --output-on-failure cd .. shell: bash - if: (matrix.cfg.cross!=true) && (github.ref_name!='codac2_codac4matlab') && (github.event_name!='pull_request') \ No newline at end of file + if: (matrix.cfg.cross!=true)&&(github.ref_name!='codac2_codac4matlab')&&(github.event.pull_request.base.ref!='codac2_codac4matlab') diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f9b03791..0efbe9c8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,11 @@ on: push: branches-ignore: - - codac2_codac4matlab + - codac2_codac4matlab tags: '' # Restrict to blank tags pull_request: + branches-ignore: + - codac2_codac4matlab jobs: tests: @@ -41,7 +43,7 @@ jobs: sudo sh -c 'echo "deb [trusted=yes] https://packages.ensta-bretagne.fr/$(if [ -z "$(. /etc/os-release && echo $UBUNTU_CODENAME)" ]; then echo debian/$(. /etc/os-release && echo $VERSION_CODENAME); else echo ubuntu/$(. /etc/os-release && echo $UBUNTU_CODENAME); fi) ./" > /etc/apt/sources.list.d/ensta-bretagne.list' sudo apt update - sudo apt-get -y install flex bison libeigen3-dev + sudo apt-get -y install flex bison # libeigen3-dev # For documentation pip install sphinx breathe sphinx-issues sphinx-tabs sphinx_rtd_theme @@ -78,7 +80,7 @@ jobs: cd $ORIGIN_DIR pwd ls - git submodule init ; git submodule update # for pybind11 submodule + git submodule init ; git submodule update # for pybind11/eigen submodules mkdir build -p cd build diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index 2319e099..e5367d6c 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -6,9 +6,9 @@ on: pull_request: jobs: - # This job may be commented if a new release should not be created... deploy: runs-on: ubuntu-latest + if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) steps: - uses: softprops/action-gh-release@v2 id: create_release @@ -17,10 +17,10 @@ jobs: with: draft: true tag_name: autotagname-${{ github.sha }} - if: (github.event_name != 'pull_request')&&(github.ref_name == 'codac2') unixmatrix: runs-on: ${{ matrix.cfg.os }} + if: (github.ref_name!='codac2_codac4matlab')&&(github.event.pull_request.base.ref!='codac2_codac4matlab') defaults: run: shell: ${{ matrix.cfg.shell }} @@ -30,9 +30,9 @@ jobs: cfg: - { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2022 x64' } - { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2022 x86' } - - { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2019 x64' } - - { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2019 x86' } # Problems related to C++20? + #- { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2019 x64' } + #- { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2019 x86' } #- { os: windows-2019, shell: cmd, arch: x64, bitness: 64, runtime: vc15, cmake_params: '-G "Visual Studio 16" -T v141 -A x64', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2017 x64' } #- { os: windows-2019, shell: cmd, arch: x86, bitness: 32, runtime: vc15, cmake_params: '-G "Visual Studio 16" -T v141 -A Win32', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2017 x86' } - { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: mingw13, cmake_params: '-G "MinGW Makefiles"', cmake_flags: '-fPIC', desc: 'Windows MinGW 13.2.0 x64' } @@ -50,12 +50,12 @@ jobs: - { os: ubuntu-22.04, shell: bash, arch: amd64, bitness: 64, runtime: jammy, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 22.04 amd64' } # Problems related to C++20? #- { os: ubuntu-20.04, shell: bash, arch: amd64, bitness: 64, runtime: focal, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 20.04 amd64' } + - { os: macos-15, shell: bash, arch: arm64, bitness: 64, runtime: sequoia, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=arm64', cmake_flags: '-fPIC', desc: 'macOS Sequoia arm64' } + - { os: macos-15, shell: bash, arch: x86_64, bitness: 64, runtime: sequoia, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=x86_64', cmake_flags: '-fPIC', cross: true, desc: 'macOS Sequoia x86_64 (cross)' } - { os: macos-14, shell: bash, arch: arm64, bitness: 64, runtime: sonoma, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=arm64', cmake_flags: '-fPIC', desc: 'macOS Sonoma arm64' } - { os: macos-14, shell: bash, arch: x86_64, bitness: 64, runtime: sonoma, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=x86_64', cmake_flags: '-fPIC', cross: true, desc: 'macOS Sonoma x86_64 (cross)' } - { os: macos-13, shell: bash, arch: arm64, bitness: 64, runtime: ventura, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=arm64', cmake_flags: '-fPIC', cross: true, desc: 'macOS Ventura arm64 (cross)' } - { os: macos-13, shell: bash, arch: x86_64, bitness: 64, runtime: ventura, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=x86_64', cmake_flags: '-fPIC', desc: 'macOS Ventura x86_64' } - - { os: macos-12, shell: bash, arch: arm64, bitness: 64, runtime: monterey, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=arm64', cmake_flags: '-fPIC', cross: true, desc: 'macOS Monterey arm64 (cross)' } - - { os: macos-12, shell: bash, arch: x86_64, bitness: 64, runtime: monterey, cmake_params: '-D CMAKE_SYSTEM_NAME=Darwin -D CMAKE_OSX_ARCHITECTURES=x86_64', cmake_flags: '-fPIC', desc: 'macOS Monterey x86_64' } name: ${{ matrix.cfg.desc }} steps: - uses: actions/checkout@v4 @@ -119,31 +119,24 @@ jobs: echo export BASHMINGWPATH=/c/ProgramData/mingw64/mingw${{ matrix.cfg.bitness }}/bin>>%USERPROFILE%\.bashrc if: (matrix.cfg.runtime=='mingw13') - run: | - choco install -y -r --no-progress eigen --version=3.4.0.20240224 ${{ matrix.cfg.choco_flags }} - wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex.2.8.9.20240417.nupkg --no-check-certificate -nv - choco install -y -r --no-progress --ignore-dependencies -s . ibex --version=2.8.9.20240417 ${{ matrix.cfg.choco_flags }} --params "'/url:https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip'" - del /f /q ibex.2.8.9.20240417.nupkg + #choco install -y -r --no-progress eigen --version=3.4.0.20240224 ${{ matrix.cfg.choco_flags }} + wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex.2.8.9.20241117.nupkg --no-check-certificate -nv + choco install -y -r --no-progress --ignore-dependencies -s . ibex --version=2.8.9.20241117 ${{ matrix.cfg.choco_flags }} --params "'/url:https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip'" + del /f /q ibex.2.8.9.20241117.nupkg if: runner.os=='Windows' - run: | sudo sh -c 'echo "deb [trusted=yes] https://packages.ensta-bretagne.fr/$(if [ -z "$(. /etc/os-release && echo $UBUNTU_CODENAME)" ]; then echo debian/$(. /etc/os-release && echo $VERSION_CODENAME); else echo ubuntu/$(. /etc/os-release && echo $UBUNTU_CODENAME); fi) ./" > /etc/apt/sources.list.d/ensta-bretagne.list' # Replace this line by the next ones to test a specific binary package of IBEX. - #sudo apt-get -q update ; sudo apt-get -y install libibex-dev libeigen3-dev dpkg-dev || true - sudo apt-get -q update ; sudo apt-get -y install libeigen3-dev dpkg-dev || true - wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/libibex-dev-2.8.9.20240417-0${{ matrix.cfg.runtime }}0_$(dpkg --print-architecture).deb --no-check-certificate -nv - sudo dpkg -i libibex-dev-2.8.9.20240417-0${{ matrix.cfg.runtime }}0_$(dpkg --print-architecture).deb - rm -Rf libibex-dev-2.8.9.20240417-0${{ matrix.cfg.runtime }}0_$(dpkg --print-architecture).deb + #sudo apt-get -q update ; sudo apt-get -y install libibex-dev dpkg-dev || true + sudo apt-get -q update ; sudo apt-get -y install dpkg-dev || true + wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/libibex-dev-2.8.9.20241117-0${{ matrix.cfg.runtime }}0_$(dpkg --print-architecture).deb --no-check-certificate -nv + sudo dpkg -i libibex-dev-2.8.9.20241117-0${{ matrix.cfg.runtime }}0_$(dpkg --print-architecture).deb + rm -Rf libibex-dev-2.8.9.20241117-0${{ matrix.cfg.runtime }}0_$(dpkg --print-architecture).deb shell: bash if: matrix.cfg.deb==true - run: | -# git clone https://github.com/catchorg/Catch2 -# cd Catch2 -# git checkout v2.x -# mkdir build ; cd build ; cmake .. ; make ; sudo make install - shell: bash - if: runner.os=='Linux' - - run: | - brew install eigen - wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip --no-check-certificate -nv + #brew install eigen + wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip --no-check-certificate -nv unzip -q ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip rm -Rf ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip sudo cp -Rf ibex/* /usr/local/ @@ -154,7 +147,7 @@ jobs: if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi mkdir build ; cd build cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" .. - cmake --build . -j 4 --config Debug --target install + cmake --build . --config Debug --target install cd .. sed_param=s/PATH_SUFFIXES\ /PATHS\ \$\{CMAKE_CURRENT_LIST_FILE\}\\/..\\/..\\/..\\/..\\/\ PATH_SUFFIXES\ / if [ ${{ runner.os }} = Windows ]; then sed -i "$sed_param" codac/share/codac/cmake/*.cmake ; fi @@ -163,7 +156,7 @@ jobs: - run: | if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi mkdir -p codac_standalone/example ; cd codac_standalone - wget https://community.chocolatey.org/api/v2/package/eigen/3.4.0.20240224 --no-check-certificate -nv ; unzip -q 3.4.0.20240224 -d eigen ; rm -Rf 3.4.0.20240224 eigen/*.xml eigen/*.nuspec eigen/_* eigen/package eigen/tools + #wget https://community.chocolatey.org/api/v2/package/eigen/3.4.0.20240224 --no-check-certificate -nv ; unzip -q 3.4.0.20240224 -d eigen ; rm -Rf 3.4.0.20240224 eigen/*.xml eigen/*.nuspec eigen/_* eigen/package eigen/tools if [ ${{ runner.os }} = Windows ]; then cp -Rf /C/ProgramData/chocolatey/lib/ibex . ; rm -Rf ibex/tools ibex/ibex.* elif [ ${{ matrix.cfg.deb }} = true ]; then mkdir -p ibex/include ; mkdir -p ibex/lib ; mkdir -p ibex/share ; mkdir -p ibex/bin ; cp -Rf /usr/include/ibex* ibex/include/ ; cp -Rf /usr/lib/*ibex* ibex/lib/ ; cp -Rf /usr/share/*ibex* ibex/share/ ; cp -Rf /usr/share/pkgconfig ibex/share/ ; cp -Rf /usr/bin/ibex* ibex/bin/ else cp -Rf ../ibex . @@ -179,7 +172,7 @@ jobs: ./${{ matrix.cfg.test_config }}my_project cd ../.. shell: bash - if: (matrix.cfg.cross!=true) && (github.ref_name!='codac2_codac4matlab') && (github.event_name!='pull_request') + if: (matrix.cfg.cross!=true) - run: | source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH cd packages/choco @@ -220,7 +213,7 @@ jobs: file: "*.zip;*.nupkg;*.deb" overwrite: true tag_name: autotagname-${{ github.sha }} - if: (github.event_name != 'pull_request')&&(github.ref_name == 'codac2') + if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) - run: | if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi rm -Rf codac @@ -231,4 +224,4 @@ jobs: ./${{ matrix.cfg.test_config }}my_project cd ../.. shell: bash - if: (matrix.cfg.cross!=true) && (github.ref_name!='codac2_codac4matlab') && (github.event_name!='pull_request') + if: (matrix.cfg.cross!=true) diff --git a/.github/workflows/vcmatrix.yml b/.github/workflows/vcmatrix.yml index 34b163a4..f2269977 100644 --- a/.github/workflows/vcmatrix.yml +++ b/.github/workflows/vcmatrix.yml @@ -2,8 +2,9 @@ on: push: branches: - - codac2 - - codac2_codac4matlab + - codac1 + - codac2 + - codac2_codac4matlab tags: '' # Restrict to blank tags pull_request: @@ -17,21 +18,23 @@ jobs: fail-fast: false matrix: cfg: + # Should be Visual Studio 2015 for Python 3.5-3.7, Visual Studio 2019 for Python 3.8-3.10, but need Visual Studio 2022 for C++20 compatibility...? + - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 13, desc: 'Windows Visual Studio 2022 x86 Python 3.13' } - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 12, desc: 'Windows Visual Studio 2022 x86 Python 3.12' } - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 11, desc: 'Windows Visual Studio 2022 x86 Python 3.11' } - - { os: windows-2022, shell: cmd, arch: x86, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 10, desc: 'Windows Visual Studio 2019 x86 Python 3.10' } - - { os: windows-2022, shell: cmd, arch: x86, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 9, desc: 'Windows Visual Studio 2019 x86 Python 3.9' } - - { os: windows-2022, shell: cmd, arch: x86, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 8, desc: 'Windows Visual Studio 2019 x86 Python 3.8' } + - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 10, desc: 'Windows Visual Studio 2022 x86 Python 3.10' } + - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 9, desc: 'Windows Visual Studio 2022 x86 Python 3.9' } + - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: '-win32', py_v_maj: 3, py_v_min: 8, desc: 'Windows Visual Studio 2022 x86 Python 3.8' } + - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: 'm-win32', py_v_maj: 3, py_v_min: 7, desc: 'Windows Visual Studio 2022 x86 Python 3.7' } + - { os: windows-2022, shell: cmd, arch: x86, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', choco_flags: '--x86', cpcfg: 'm-win32', py_v_maj: 3, py_v_min: 6, desc: 'Windows Visual Studio 2022 x86 Python 3.6' } + - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 13, desc: 'Windows Visual Studio 2022 x64 Python 3.13' } - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 12, desc: 'Windows Visual Studio 2022 x64 Python 3.12' } - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 11, desc: 'Windows Visual Studio 2022 x64 Python 3.11' } - - { os: windows-2022, shell: cmd, arch: x64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 10, desc: 'Windows Visual Studio 2019 x64 Python 3.10' } - - { os: windows-2022, shell: cmd, arch: x64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 9, desc: 'Windows Visual Studio 2019 x64 Python 3.9' } - - { os: windows-2022, shell: cmd, arch: x64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 8, desc: 'Windows Visual Studio 2019 x64 Python 3.8' } - # Should be Visual Studio 2015 for Python 3.5-3.7, but need Visual Studio 2019 for C++20 compatibility...? - - { os: windows-2022, shell: cmd, arch: x86, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', choco_flags: '--x86', cpcfg: 'm-win32', py_v_maj: 3, py_v_min: 7, desc: 'Windows Visual Studio 2019 x86 Python 3.7' } - - { os: windows-2022, shell: cmd, arch: x86, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', choco_flags: '--x86', cpcfg: 'm-win32', py_v_maj: 3, py_v_min: 6, desc: 'Windows Visual Studio 2019 x86 Python 3.6' } - - { os: windows-2022, shell: cmd, arch: x64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cpcfg: 'm-win_amd64', py_v_maj: 3, py_v_min: 7, desc: 'Windows Visual Studio 2019 x64 Python 3.7' } - - { os: windows-2022, shell: cmd, arch: x64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cpcfg: 'm-win_amd64', py_v_maj: 3, py_v_min: 6, desc: 'Windows Visual Studio 2019 x64 Python 3.6' } + - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 10, desc: 'Windows Visual Studio 2022 x64 Python 3.10' } + - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 9, desc: 'Windows Visual Studio 2022 x64 Python 3.9' } + - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: '-win_amd64', py_v_maj: 3, py_v_min: 8, desc: 'Windows Visual Studio 2022 x64 Python 3.8' } + - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: 'm-win_amd64', py_v_maj: 3, py_v_min: 7, desc: 'Windows Visual Studio 2022 x64 Python 3.7' } + - { os: windows-2022, shell: cmd, arch: x64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cpcfg: 'm-win_amd64', py_v_maj: 3, py_v_min: 6, desc: 'Windows Visual Studio 2022 x64 Python 3.6' } name: ${{ matrix.cfg.desc }} steps: - uses: actions/checkout@v4 @@ -55,14 +58,14 @@ jobs: 7z x C:\Windows\Temp\windows_extra_tools.zip -o"C:\Windows" -y shell: pwsh if: runner.os=='Windows' - - run: choco install -y -r --no-progress eigen --version=3.4.0.20240224 ${{ matrix.cfg.choco_flags }} - if: runner.os=='Windows' - - run: choco install -y -r --no-progress graphviz doxygen.install & pip install --upgrade wheel setuptools sphinx breathe sphinx-issues sphinx-tabs sphinx_rtd_theme sphinx-reredirects + #- run: choco install -y -r --no-progress eigen --version=3.4.0.20240224 ${{ matrix.cfg.choco_flags }} + # if: runner.os=='Windows' + - run: choco install -y -r --no-progress graphviz doxygen.install & python -m pip install --upgrade pip & pip install --upgrade wheel setuptools sphinx breathe sphinx-issues sphinx-tabs sphinx_rtd_theme sphinx-reredirects if: runner.os=='Windows' - run: | - wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex.2.8.9.20240417.nupkg --no-check-certificate -nv - choco install -y -r --no-progress --ignore-dependencies -s . ibex --version=2.8.9.20240417 ${{ matrix.cfg.choco_flags }} --params "'/url:https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip'" - del /f /q ibex.2.8.9.20240417.nupkg + wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex.2.8.9.20241117.nupkg --no-check-certificate -nv + choco install -y -r --no-progress --ignore-dependencies -s . ibex --version=2.8.9.20241117 ${{ matrix.cfg.choco_flags }} --params "'/url:https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip'" + del /f /q ibex.2.8.9.20241117.nupkg - run: | mkdir build ; cd build cmake -E env CXXFLAGS=" /wd4267 /wd4244 /wd4305 /wd4996" CFLAGS=" /wd4267 /wd4244 /wd4305 /wd4996" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" -D BUILD_TESTS=ON -D WITH_CAPD=OFF -D WITH_PYTHON=ON .. @@ -77,7 +80,7 @@ jobs: file: "*.whl" overwrite: true tag_name: autotagname-${{ github.sha }} - if: (github.event_name!='pull_request')&&((github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) + if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) - run: | pip install --no-deps --no-index *.whl python -c "import sys; print(sys.version)" ; python examples/02_centered_form/main.py @@ -86,4 +89,4 @@ jobs: cd build && ctest -C Release -V --output-on-failure cd .. shell: bash - if: (github.ref_name!='codac2_codac4matlab') && (github.event_name!='pull_request') + if: (github.ref_name!='codac2_codac4matlab')&&(github.event.pull_request.base.ref!='codac2_codac4matlab') diff --git a/.gitignore b/.gitignore index aa002231..f1986dcd 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,7 @@ wheelhouse/ # VSCode files *.vscode -.idea/ \ No newline at end of file +.idea/ + +# Graphics files +examples/**/*.xml \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 4dbf077b..6bb00244 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "python/pybind11"] path = python/pybind11 url = https://github.com/pybind/pybind11 +[submodule "3rd/eigen"] + path = 3rd/eigen + url = https://github.com/codac-team/eigen diff --git a/3rd/Catch2-3.6.0.zip b/3rd/Catch2-3.6.0.zip new file mode 100644 index 00000000..d966c07d Binary files /dev/null and b/3rd/Catch2-3.6.0.zip differ diff --git a/3rd/eigen b/3rd/eigen new file mode 160000 index 00000000..23547192 --- /dev/null +++ b/3rd/eigen @@ -0,0 +1 @@ +Subproject commit 2354719271ab49cc92a4f6a8ec3e491d58125273 diff --git a/CMakeLists.txt b/CMakeLists.txt index f25b75d8..2a39db1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Codac - cmake configuration file # ================================================================== - cmake_minimum_required(VERSION 3.0.2) + cmake_minimum_required(VERSION 3.14...3.25) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/scripts/CMakeModules/) include(version_from_git) @@ -28,15 +28,6 @@ set(PROJECT_HOMEPAGE_URL "http://codac.io") message(STATUS "Configuring build for ${PROJECT_NAME} ${PROJECT_VERSION}") - if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug) - message(STATUS "Configuring ${PROJECT_NAME} in DEBUG mode as none was specified.") - if(MSVC) - add_compile_options(/MD) # Temporary fix to avoid debug vs release inconsistencies... - else() - add_compile_options(-O3) - endif() - endif() ################################################################################ # Options for directories @@ -54,6 +45,22 @@ # Compilation configuration ################################################################################ + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) + message(STATUS "Configuring ${PROJECT_NAME} in DEBUG mode as none was specified.") + if(MSVC) + add_compile_options(/MD) # Temporary fix to avoid debug vs release inconsistencies... + else() + add_compile_options(-O3) + endif() + endif() + + if(MSVC) + add_compile_options(/W4) + else() + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + # # Check that the compiler supports c++20 # include(CheckCXXCompilerFlag) # check_cxx_compiler_flag("-std=c++2a" COMPILER_SUPPORTS_CXX20) @@ -62,11 +69,6 @@ # add_compile_options(-std=c++2a) # else() # message(FATAL_ERROR "Codac needs a compiler with C++20 support") -# endif() - -# if(WIN32) -# # We need this for strdup under Windows (see issue #287 of ibex-lib repo) -# add_definitions(-U__STRICT_ANSI__) # endif() #if(NOT CMAKE_CXX_STANDARD) @@ -88,7 +90,7 @@ # Looking for Eigen3 ################################################################################ - find_package(Eigen3 3.4 REQUIRED NO_MODULE) + add_subdirectory(3rd/eigen) message(STATUS "Found Eigen3 version ${Eigen3_VERSION}") add_definitions(${EIGEN3_DEFINITIONS}) @@ -114,7 +116,8 @@ ################################################################################ if(FAST_RELEASE) - add_compile_definitions(FAST_RELEASE=1) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") endif() add_subdirectory(src) # C++ sources diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index a305e855..ee4626e4 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -52,4 +52,53 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mathjax_stmaryrd.js endif() + endif() + +# User manual (Sphinx) + + find_package(Sphinx) + + if(NOT SPHINX_FOUND) + + message(STATUS "Sphinx not found, will not be able to generate the manual.") + + else() + + # Includes CMake commands in config file: + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/manual/conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/manual/conf.py) + + set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/manual) + set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/manual) + + # Copying _static files of Sphinx to build directories + foreach(static_file ${CMAKE_CURRENT_SOURCE_DIR}/manual/_static/) + file(COPY ${static_file} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/manual/_static/) + endforeach() + + # Copying tmp files + foreach(static_file ${CMAKE_CURRENT_SOURCE_DIR}/manual/tmp/) + file(COPY ${static_file} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/manual/tmp/) + endforeach() + + # todo: the SPHINX_EXECUTABLE is already set by FindSphinx.cmake: + # check that it works without the following overload for Win and Linux: + if(WIN32) + set(SPHINX_EXECUTABLE "sphinx-build") + else() + set(SPHINX_EXECUTABLE "python3" "-msphinx") + endif() + + add_custom_target(manual + COMMAND + ${SPHINX_EXECUTABLE} -b html + # Specifying path to conf.py generated by CMake: + -c ${CMAKE_CURRENT_BINARY_DIR}/manual/ + ${SPHINX_SOURCE} ${SPHINX_BUILD} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating the manual website using Sphinx") + + install(DIRECTORY ${SPHINX_BUILD}/ + DESTINATION share/manual/${CMAKE_PROJECT_NAME} + OPTIONAL) + endif() \ No newline at end of file diff --git a/doc/api/Doxyfile.in b/doc/api/Doxyfile.in index 31a0e71c..98532a04 100644 --- a/doc/api/Doxyfile.in +++ b/doc/api/Doxyfile.in @@ -1005,7 +1005,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../src/core/graphics/vibes/ +EXCLUDE = ../src/graphics/3rd/vibes/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/doc/manual/_static/css/custom.css b/doc/manual/_static/css/custom.css new file mode 100644 index 00000000..bf36547f --- /dev/null +++ b/doc/manual/_static/css/custom.css @@ -0,0 +1,10 @@ +div.rst-content a:visited +{ + color: #2980b9; + text-decoration: none; +} + +div.rst-content li.toctree-l1 > a +{ + font-weight: bold; +} \ No newline at end of file diff --git a/doc/manual/_static/empty.txt b/doc/manual/_static/empty.txt new file mode 100644 index 00000000..e69de29b diff --git a/doc/manual/_templates/empty.txt b/doc/manual/_templates/empty.txt new file mode 100644 index 00000000..e69de29b diff --git a/doc/manual/conf.py.in b/doc/manual/conf.py.in new file mode 100644 index 00000000..e7d94dab --- /dev/null +++ b/doc/manual/conf.py.in @@ -0,0 +1,40 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'Codac' +copyright = 'Codac Team' +author = 'Codac Team' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx_rtd_theme', +] + +templates_path = ['_templates'] +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_static_path = ['_static'] +html_theme = "sphinx_rtd_theme" +html_logo = "_static/logos/logo_codac.svg" + +# These paths are either relative to html_static_path +# or fully qualified paths (eg. https://...) +html_css_files = [ + 'css/custom.css', +] + +html_theme_options = { + 'logo_only': True, + 'display_version': True, +} \ No newline at end of file diff --git a/doc/manual/index.rst b/doc/manual/index.rst new file mode 100644 index 00000000..460fb89b --- /dev/null +++ b/doc/manual/index.rst @@ -0,0 +1,51 @@ +Codac manual +============ + + +.. toctree:: + :caption: Overview of Codac + :maxdepth: 3 + + Constraint programming and IA + The Codac framework + Target audience + + +.. toctree:: + :caption: User manual + :maxdepth: 3 + + installation/index.rst + intervals/index.rst + linear/index.rst + functions/index.rst + tubes/index.rst + contractors/index.rst + separators/index.rst + pavers/index.rst + cn/index.rst + geometry/index.rst + ellipsoids/index.rst + topology/index.rst + visualization/index.rst + extensions/index.rst + seealso/index.rst + references/index.rst + + +.. toctree:: + :caption: How-to guides + :maxdepth: 3 + + howto/robotics/index.rst + howto/geometry/index.rst + howto/dynamical/index.rst + + +.. toctree:: + :caption: Development + :maxdepth: 3 + + Changelog + C++ API + Information for developers \ No newline at end of file diff --git a/doc/manual/tmp/empty.txt b/doc/manual/tmp/empty.txt new file mode 100644 index 00000000..e69de29b diff --git a/examples/00_graphics/graphic_examples.py b/examples/00_graphics/graphic_examples.py index c333a826..b4089801 100644 --- a/examples/00_graphics/graphic_examples.py +++ b/examples/00_graphics/graphic_examples.py @@ -23,7 +23,7 @@ fig1.set_window_properties([50,50],[500,500]) # position, window size fig1.set_axes(axis(0,[-10,10]), axis(1,[-10,10])) # (axis_id,[range_of_values_on_this_axis]) fig1.draw_box([[-1,1],[-1,1]],[Color.green(),Color.red(0.2)]) # drawing a green box with red opacity values inside -fig1.draw_circle([1,1],0.5,Color(255,155,5)) # drawing a circle at (1,1) of radius 0.5 with a custom RGB color +fig1.draw_circle([1,1],0.5,Color([255,155,5])) # drawing a circle at (1,1) of radius 0.5 with a custom RGB color fig1.draw_ring([1,1],[4,6],Color.red()) # drawing a ring at (1,1) of radius [4,6] with a predefined red color fig2 = Figure2D("My figure 2", GraphicOutput.VIBES | GraphicOutput.IPE) @@ -37,11 +37,38 @@ DefaultView.set(fig1) DefaultView.draw_box([[2.2,2.5],[2.2,2.5]],[Color.blue(),Color.cyan(0.8)]) -fig2.draw_AUV([1,1,3.14/2],1.,[Color.black(),Color.yellow()]) +fig2.draw_AUV([1,1,3.14/2],2.,[Color.black(),Color.yellow()]) fig2.draw_tank([2,1,3.14/2],1.,[Color.black(),Color.yellow()]) fig2.draw_pie([2,2],[1.5,2.5],[(3*3.14/4)-0.5,(3*3.14/4)+0.5],[Color.blue(),Color.cyan()]) fig2.draw_polyline([[2,-0.5],[4,0.5],[3,1.5],[4,2.5],[3,3]], Color.red()) fig2.draw_polygone([[2,4.5],[4,4.5],[4.2,3.5],[3.5,3]], [Color.none(),Color.green(0.5)]) fig2.draw_polyline([[-0.8,0],[0,1.5]], 0.2, [Color.red(),Color.black(0.3)]) fig2.draw_ellipse([1,1],[0.5,2], 0.2, [Color.blue(),Color.blue(0.3)]) -fig2.draw_point([2,2], [Color.red(),Color.yellow(0.5)]) \ No newline at end of file + +# Colors +# predefined colors without and with opacity +fig2.draw_point([2,2], [Color.red(),Color.yellow(0.5)]) +# HTML color without and with opacity +fig2.draw_box([[2.4,2.9],[2.4,2.9]],[Color("#da3907"),Color("#da390755")]) +# HSV color without and with opacity +fig2.draw_box([[2.6,3.1],[2.6,3.1]],[Color([108,90,78],Model.HSV),Color([108,90,78,20],Model.HSV)]) +# RGB color auto cast from list without and with opacity +fig2.draw_box([[2.,2.3],[2.6,2.9]],[[255,0,255],[255,0,255,100]]) + +fig3 = Figure2D("ColorMap figure", GraphicOutput.VIBES | GraphicOutput.IPE) +fig3.set_axes(axis(0,[-1,21]), axis(1,[-5.5,0.5])) +fig3.set_window_properties([800,250],[500,500]) + +cmap_haxby=ColorMap.haxby() +cmap_default=ColorMap.basic() +cmap_blue_tube=ColorMap.blue_tube() +cmap_red_tube=ColorMap.red_tube() +cmap_rainbow=ColorMap.rainbow() + +for i in range (20): + ratio=i/20 + fig3.draw_box([[i,i+1],[-1,0]],[Color.black(),cmap_haxby.color(ratio)]) + fig3.draw_box([[i,i+1],[-2,-1]],[Color.black(),cmap_default.color(ratio)]) + fig3.draw_box([[i,i+1],[-3,-2]],[Color.black(),cmap_blue_tube.color(ratio)]) + fig3.draw_box([[i,i+1],[-4,-3]],[Color.black(),cmap_red_tube.color(ratio)]) + fig3.draw_box([[i,i+1],[-5,-4]],[Color.black(),cmap_rainbow.color(ratio)]) \ No newline at end of file diff --git a/examples/01_batman/CMakeLists.txt b/examples/01_batman/CMakeLists.txt index ce2e8a92..314b49ff 100644 --- a/examples/01_batman/CMakeLists.txt +++ b/examples/01_batman/CMakeLists.txt @@ -18,15 +18,6 @@ ibex_init_common() # IBEX should have installed this function message(STATUS "Found IBEX version ${IBEX_VERSION}") -# Adding Eigen3 - - # In case you installed Eigen3 in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option, e.g. - # set(CMAKE_PREFIX_PATH "~/eigen/build_install") - - find_package(Eigen3 3.4 REQUIRED NO_MODULE) - message(STATUS "Found Eigen3 version ${Eigen3_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -38,7 +29,12 @@ # Compilation + if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") + endif() + add_executable(${PROJECT_NAME} main.cpp) target_compile_options(${PROJECT_NAME} PUBLIC ${CODAC_CXX_FLAGS}) target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CODAC_INCLUDE_DIRS}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex Eigen3::Eigen) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/examples/02_centered_form/CMakeLists.txt b/examples/02_centered_form/CMakeLists.txt index ce2e8a92..314b49ff 100644 --- a/examples/02_centered_form/CMakeLists.txt +++ b/examples/02_centered_form/CMakeLists.txt @@ -18,15 +18,6 @@ ibex_init_common() # IBEX should have installed this function message(STATUS "Found IBEX version ${IBEX_VERSION}") -# Adding Eigen3 - - # In case you installed Eigen3 in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option, e.g. - # set(CMAKE_PREFIX_PATH "~/eigen/build_install") - - find_package(Eigen3 3.4 REQUIRED NO_MODULE) - message(STATUS "Found Eigen3 version ${Eigen3_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -38,7 +29,12 @@ # Compilation + if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") + endif() + add_executable(${PROJECT_NAME} main.cpp) target_compile_options(${PROJECT_NAME} PUBLIC ${CODAC_CXX_FLAGS}) target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CODAC_INCLUDE_DIRS}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex Eigen3::Eigen) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/examples/02_centered_form/main.py b/examples/02_centered_form/main.py index 34859894..374f861d 100644 --- a/examples/02_centered_form/main.py +++ b/examples/02_centered_form/main.py @@ -9,5 +9,5 @@ 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) )) -ctc = CtcInverse(f, [[0],[0]]) +ctc = CtcInverse(f, [0,0]) graphics.draw_while_paving([[0,2],[2,4],[0,10]], ctc, 0.004) \ No newline at end of file diff --git a/examples/02_centered_form/main_evans.cpp b/examples/02_centered_form/main_evans.cpp index 1657579e..1e7351b9 100644 --- a/examples/02_centered_form/main_evans.cpp +++ b/examples/02_centered_form/main_evans.cpp @@ -11,7 +11,7 @@ int main() 2*x[0]*x[1]+2*exp(-x[0]*x[2])*(x[1]*cos(x[1]*x[2])-x[0]*sin(x[1]*x[2]))-exp(-x[0]*x[3])*sin(x[1]*x[3]) )); - CtcInverse_ ctc(f, {{0.},{0.}}); + CtcInverse_ ctc(f, {0.,0.}); IntervalVector x0({{-10,10},{0,20},{1,1},{2,2}}); shared_ptr g = make_shared("Evans", GraphicOutput::VIBES); diff --git a/examples/02_centered_form/main_parabolas.cpp b/examples/02_centered_form/main_parabolas.cpp index 75ac425a..6902f389 100644 --- a/examples/02_centered_form/main_parabolas.cpp +++ b/examples/02_centered_form/main_parabolas.cpp @@ -22,12 +22,13 @@ int main() ); AnalyticFunction h({a}, fa(a[0],a[1])-fb(a[2],a[3])); - CtcInverse_ ctc(h, {{0.},{0.},{0.}}); + CtcInverse_ ctc(h, {0.,0.,0.}); - // to be restored... - /*IntervalVector x0({{0,1},{0,1},{0,1},{0,1}}); - Paver p(x0); + IntervalVector x0({{0,1},{0,1},{0,1},{0,1}}); + draw_while_paving(x0, ctc, 0.001); + /* + // to be restored... Figure2D g("(u1,v1)", GraphicOutput::VIBES); g.set_axes(axis(0,x0[0]), axis(1,x0[1])); g.set_window_properties({100,100},{600,600}); @@ -42,5 +43,6 @@ int main() l_34.push_back(fb.eval_centered(li[2],li[3])); } export_to_ObjectFileFormat(l_12, "output_u1v1.off"); - export_to_ObjectFileFormat(l_34, "output_u2v2.off");*/ + export_to_ObjectFileFormat(l_34, "output_u2v2.off"); + */ } \ No newline at end of file diff --git a/examples/02_centered_form/main_parabolas.py b/examples/02_centered_form/main_parabolas.py index 8ffed1b7..d2a62388 100644 --- a/examples/02_centered_form/main_parabolas.py +++ b/examples/02_centered_form/main_parabolas.py @@ -18,5 +18,5 @@ IntervalVector([[2],[0],[0.55]]),IntervalVector([[2],[1],[-0.45]]),IntervalVector([[2],[2],[0.55]])) ) -ctc = CtcInverse(h, [[0],[0],[0]]) +ctc = CtcInverse(h, [0,0,0]) draw_while_paving([[0,1],[0,1],[0,1],[0,1]], ctc, 0.001) \ No newline at end of file diff --git a/examples/03_sivia/CMakeLists.txt b/examples/03_sivia/CMakeLists.txt index ce2e8a92..314b49ff 100644 --- a/examples/03_sivia/CMakeLists.txt +++ b/examples/03_sivia/CMakeLists.txt @@ -18,15 +18,6 @@ ibex_init_common() # IBEX should have installed this function message(STATUS "Found IBEX version ${IBEX_VERSION}") -# Adding Eigen3 - - # In case you installed Eigen3 in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option, e.g. - # set(CMAKE_PREFIX_PATH "~/eigen/build_install") - - find_package(Eigen3 3.4 REQUIRED NO_MODULE) - message(STATUS "Found Eigen3 version ${Eigen3_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -38,7 +29,12 @@ # Compilation + if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") + endif() + add_executable(${PROJECT_NAME} main.cpp) target_compile_options(${PROJECT_NAME} PUBLIC ${CODAC_CXX_FLAGS}) target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CODAC_INCLUDE_DIRS}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex Eigen3::Eigen) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/examples/ellipsoid_dev/main.cpp b/examples/ellipsoid_dev/main.cpp index f8554893..0743b70b 100644 --- a/examples/ellipsoid_dev/main.cpp +++ b/examples/ellipsoid_dev/main.cpp @@ -63,8 +63,8 @@ int main() { // ---------------------------------------------------------- // step 1 identify the direction of non inclusion - Eigen::MatrixXd X = e4.G._e; - Eigen::MatrixXd Y = e6.G._e; + Eigen::MatrixXd X = e4.G; + Eigen::MatrixXd Y = e6.G; Eigen::MatrixXd Y_inv = Y.inverse(); Eigen::MatrixXd D = Eigen::MatrixXd::Identity(3,3)- X.transpose()*Y_inv.transpose()*Y_inv*X; cout << "D = " << D << endl; @@ -84,7 +84,7 @@ int main() { cout << " the vector associated to the min eigenvalue is " << v << endl; // select the less included point and draw it on the figures - Eigen::VectorXd x = e4.mu._e+e4.G._e*v; + Eigen::VectorXd x = e4.mu+e4.G*v; cout << "the point " << x << " is the less included point" << endl; fig2.draw_point(x, {Color::black()}); fig3.draw_point(x, {Color::black()}); diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index dff50e73..c3cb3753 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -13,10 +13,11 @@ int main() { fig1.set_window_properties({0, 100}, {500, 500}); // initial ellipsoid - Vector mu({1., 0.}); - Matrix G({{0.05, 0.0}, - {0., 0.05}}); - Ellipsoid e1(mu, G); + Ellipsoid e1( + {1., 0.}, // mu + {{0.05, 0.0}, // G + {0., 0.05}} + ); fig1.draw_ellipsoid(e1, {Color::red(), Color::red(0.3)}); cout << "Initial ellipsoid e1 (red):" << endl; cout << e1 << endl; @@ -31,7 +32,7 @@ int main() { Ellipsoid e2 = Ellipsoid(e1); for (int i = 0; i < N; i++) { Matrix A = h.diff(e2.mu).mid(); - Vector b(h.eval(e2.mu).mid()._e - A._e * e2.mu._e); + Vector b(h.eval(e2.mu).mid() - A * e2.mu); e2 = unreliable_linear_mapping(e2, A, b); fig1.draw_ellipsoid(e2, {Color::green(), Color::green(0.3)}); } @@ -51,10 +52,10 @@ int main() { int Np = 200; for (int i = 0; i < Np; i++) { Vector x0 = e1.rand(); - fig1.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig1.draw_point(x0, {Color::black(), Color::black(0.3)}); for (int j = 0; j < N; j++) { x0 = h.eval(x0).mid(); - fig1.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig1.draw_point(x0, {Color::black(), Color::black(0.3)}); } } @@ -62,19 +63,24 @@ int main() { // ellipsoid projections // ---------------------------------------------------------- - Vector mu4({1., 0., 0.}); - Matrix G4({{1., 0.5, 0.}, - {0.5, 2., 0.2}, - {0., 0.2, 3.}}); - Ellipsoid e4(mu4, G4); - - Matrix G5 = 0.7 * G4; - Ellipsoid e5(mu4, G5); - - Matrix G6({{2., 0., 0.5}, - {0., 1., 0.2}, - {0., 0.2, 3.}}); - Ellipsoid e6(mu4, G6); + Ellipsoid e4 { + {1., 0., 0.}, // mu + {{1., 0.5, 0.}, // G + {0.5, 2., 0.2}, + {0., 0.2, 3.}} + }; + + Ellipsoid e5 { + e4.mu, // mu + 0.7 * e4.G // G + }; + + Ellipsoid e6 { + e4.mu, // mu + {{2., 0., 0.5}, // G + {0., 1., 0.2}, + {0., 0.2, 3.}} + }; Figure2D fig2("Projected ellipsoid xy", GraphicOutput::VIBES); Figure2D fig3("Projected ellipsoid yz", GraphicOutput::VIBES); @@ -102,11 +108,10 @@ int main() { // particle cloud (draw the evolution of 200 points in the ellipsoid e5) for (int i = 0; i < Np; i++) { - IntervalVector x5(e5.rand()); - x5.inflate(0.001); - fig2.draw_box(x5, {Color::black(), Color::black(0.3)}); - fig3.draw_box(x5, {Color::black(), Color::black(0.3)}); - fig4.draw_box(x5, {Color::black(), Color::black(0.3)}); + Vector x5 = e5.rand(); + fig2.draw_point(x5, {Color::black(), Color::black(0.3)}); + fig3.draw_point(x5, {Color::black(), Color::black(0.3)}); + fig4.draw_point(x5, {Color::black(), Color::black(0.3)}); } // ---------------------------------------------------------- @@ -138,8 +143,8 @@ int main() { cout << e8 << endl; cout << "\nDifference between e7 and e8:" << endl; - cout << "mu diff norm is " << (e7.mu._e - e8.mu._e).norm() << endl; - cout << "G diff norm is " << (e7.G._e - e8.G._e).norm() << endl; + cout << "mu diff norm is " << (e7.mu - e8.mu).norm() << endl; + cout << "G diff norm is " << (e7.G - e8.G).norm() << endl; // ---------------------------------------------------------- // singular case for nonlinear mapping @@ -149,10 +154,16 @@ int main() { fig5.set_axes(axis(0, {-0.5, 2}), axis(1, {-1.5, 1.})); fig5.set_window_properties({700, 600}, {500, 500}); - Ellipsoid e9(Vector({0., 0.5}), Matrix({{0.25, 0.}, - {0., 0.}})); - Ellipsoid e10(Vector({0., -0.5}), Matrix({{0.25, 0.}, - {0., 0.25}})); + Ellipsoid e9 { + {0., 0.5}, // mu + {{0.25, 0.}, // G + {0., 0.}} + }; + Ellipsoid e10 { + {0., -0.5}, // mu + {{0.25, 0.}, // G + {0., 0.25}} + }; fig5.draw_ellipsoid(e9, {Color::blue(), Color::red(0.3)}); fig5.draw_ellipsoid(e10, {Color::red(), Color::red(0.3)}); @@ -176,14 +187,12 @@ int main() { // particle cloud (draw the evolution of 200 points in the ellipsoid) for (int i = 0; i < Np; i++) { Vector x0 = e9.rand(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); - x0 = h2.eval(x0).mid(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig5.draw_point(x0, {Color::black(), Color::black(0.3)}); + fig5.draw_point(h2.eval(x0).mid(), {Color::black(), Color::black(0.3)}); x0 = e10.rand(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); - x0 = h3.eval(x0).mid(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig5.draw_point(x0, {Color::black(), Color::black(0.3)}); + fig5.draw_point(h3.eval(x0).mid(), {Color::black(), Color::black(0.3)}); } // ---------------------------------------------------------- @@ -193,8 +202,14 @@ int main() { // pendulum example AnalyticFunction h4{ {x}, vec(x[0] + 0.5 * x[1] , x[1] + 0.5 * (-x[1]-sin(x[0])))}; - Ellipsoid e13(Vector(2), Matrix(2,2)); - Ellipsoid e13_out(Vector(2), Matrix(2,2)); + Ellipsoid e13 { + Vector::zero(2), // mu + Matrix::zero(2,2) // G + }; + Ellipsoid e13_out { + Vector::zero(2), // mu + Matrix::zero(2,2) // G + }; int alpha_max = 1; if(stability_analysis(h4,alpha_max, e13, e13_out) == BoolInterval::TRUE) diff --git a/packages/choco/codac/codac.nuspec b/packages/choco/codac/codac.nuspec index a4db6d02..8ca1fddf 100644 --- a/packages/choco/codac/codac.nuspec +++ b/packages/choco/codac/codac.nuspec @@ -27,7 +27,7 @@ Codac is a library providing tools for constraint programming over reals, trajec ## Package parameters The following package parameters can be set: -- `/url:URL` - Will install the specified binary package (e.g. built for Visual Studio), see versions from https://github.com/codac-team/codac/releases (the Windows `PATH` might need to be updated manually with e.g. `C:\ProgramData\chocolatey\lib\ibex\bin`, etc.). By default, only the MinGW libraries compatible with the corresponding MinGW Chocolatey package dependency are installed. Use the standard parameter `choco install --ignore-dependencies ...` to avoid installing the default MinGW and IBEX Chocolatey package dependencies if needed (you might want to install manually [IBEX](https://community.chocolatey.org/packages/ibex) package with the corresponding parameters, as well as the corresponding compiler and the Eigen package). +- `/url:URL` - Will install the specified binary package (e.g. built for Visual Studio), see versions from https://github.com/codac-team/codac/releases (the Windows `PATH` might need to be updated manually with e.g. `C:\ProgramData\chocolatey\lib\ibex\bin`, etc.). By default, only the MinGW libraries compatible with the corresponding MinGW Chocolatey package dependency are installed. Use the standard parameter `choco install --ignore-dependencies ...` to avoid installing the default MinGW and IBEX Chocolatey package dependencies if needed (you might want to install manually [IBEX](https://community.chocolatey.org/packages/ibex) package with the corresponding parameters, as well as the corresponding compiler). - `/checksum:SHA256` - SHA256 checksum of the binary package specified by the `/url` parameter. If needed, use the standard parameter `choco install --ignore-checksums ...` for trusted sources. - `/urlX:URL` - Same as above, with X in [1,99], except this will not disable the installation of the MinGW libraries compatible with the corresponding MinGW Chocolatey package dependency. - `/checksumX:SHA256` - SHA256 checksum of the binary package specified by the `/urlX` parameter. If needed, use the standard parameter `choco install --ignore-checksums ...` for trusted sources. @@ -44,7 +44,6 @@ choco install -y --ignore-dependencies codac --params "'/url:https://github.com/ - diff --git a/packages/deb/control b/packages/deb/control index 152866dc..7d652a59 100644 --- a/packages/deb/control +++ b/packages/deb/control @@ -1,7 +1,7 @@ Package: libcodac-dev Version: 1 Architecture: amd64 -Depends: libeigen3-dev (>=3.4.0), libibex-dev +Depends: libibex-dev Section: math Priority: optional Description: Codac is a library providing tools for constraint programming over reals, trajectories and sets diff --git a/packages/temporary/gennewcodacpi_armhf.sh b/packages/temporary/gennewcodacpi_armhf.sh index 4a6ea9b6..2a69afa0 100644 --- a/packages/temporary/gennewcodacpi_armhf.sh +++ b/packages/temporary/gennewcodacpi_armhf.sh @@ -23,11 +23,12 @@ else \ PIP_OPTIONS= ; \ #python3 -m pip install \$PIP_OPTIONS --upgrade \"auditwheel==5.1.2\" ; \\ fi && \ -sudo apt-get -q update --allow-releaseinfo-change ; sudo apt-get -y install libeigen3-dev python3-dev patchelf || true && \ +#sudo apt-get -q update --allow-releaseinfo-change ; sudo apt-get -y install libeigen3-dev python3-dev patchelf || true && \\ +sudo apt-get -q update --allow-releaseinfo-change ; sudo apt-get -y install python3-dev patchelf || true && \ python3 -m pip install \$PIP_OPTIONS --upgrade patchelf --prefer-binary --extra-index-url https://www.piwheels.org/simple && \ python3 -m pip install \$PIP_OPTIONS --upgrade auditwheel --prefer-binary --extra-index-url https://www.piwheels.org/simple && \ -# wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_armhf_\$(lsb_release -cs).zip --no-check-certificate -nv is causing illegal instruction on a Mac M1... \\ -curl -L -O https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_armhf_\$(lsb_release -cs).zip --insecure && \ +# wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_armhf_\$(lsb_release -cs).zip --no-check-certificate -nv is causing illegal instruction on a Mac M1... \\ +curl -L -O https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_armhf_\$(lsb_release -cs).zip --insecure && \ unzip -q ibex_armhf_\$(lsb_release -cs).zip && \ rm -Rf ibex_armhf_\$(lsb_release -cs).zip && \ sudo cp -Rf ibex/* /usr/local/ && \ @@ -36,6 +37,7 @@ git config --global --add safe.directory /io && \ cd /io && \ \ python3 -m pip install \$PIP_OPTIONS --upgrade pip && \ +python3 -m pip install \$PIP_OPTIONS --upgrade wheel setuptools && \ mkdir -p build_dir_\$(lsb_release -cs) && cd build_dir_\$(lsb_release -cs) && \ cmake -E env CXXFLAGS=\"-fPIC\" CFLAGS=\"-fPIC\" cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON -DWITH_CAPD=OFF -DWITH_PYTHON=ON .. && \ make -j4 && \ @@ -54,13 +56,14 @@ done ; \ #done ; \\ \ python3 -m pip install \$PIP_OPTIONS codac --no-deps --no-index -f /io/wheelhouse && \ -python3 -m ../examples/02_centered_form/main.py && \ +python3 ../examples/02_centered_form/main.py && \ # Prerequisites for numpy. \\ sudo apt-get -y install libatlas3-base || true && \ sudo apt-get -y install libopenblas0-pthread || true && \ sudo apt-get -y install libgfortran5 || true && \ python3 -m pip install \$PIP_OPTIONS numpy --prefer-binary --extra-index-url https://www.piwheels.org/simple && \ -#(cd \"\$HOME\"; python3 -m unittest discover codac.tests) && \\ +python3 -m unittest discover codac.tests && \ +\ if [ \"\$(lsb_release -cs)\" = \"buster\" ]; then \ echo \"TESTS DISABLED FOR BUSTER DUE TO CATCH2\" ; \ else \ diff --git a/doc/doc/tutorial-set4most/01-examples/index.rst b/prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/index.rst similarity index 100% rename from doc/doc/tutorial-set4most/01-examples/index.rst rename to prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/index.rst diff --git a/doc/doc/tutorial-set4most/01-examples/range-only-loc.py b/prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/range-only-loc.py similarity index 100% rename from doc/doc/tutorial-set4most/01-examples/range-only-loc.py rename to prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/range-only-loc.py diff --git a/doc/doc/tutorial-set4most/01-examples/slam.py b/prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/slam.py similarity index 100% rename from doc/doc/tutorial-set4most/01-examples/slam.py rename to prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/slam.py diff --git a/doc/doc/tutorial-set4most/01-examples/triskelion.py b/prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/triskelion.py similarity index 100% rename from doc/doc/tutorial-set4most/01-examples/triskelion.py rename to prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/triskelion.py diff --git a/doc/doc/tutorial-set4most/01-examples/walls-loc.py b/prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/walls-loc.py similarity index 100% rename from doc/doc/tutorial-set4most/01-examples/walls-loc.py rename to prev_versions/v1.5.2/doc/doc/tutorial-set4most/01-examples/walls-loc.py diff --git a/doc/doc/tutorial-set4most/index.rst b/prev_versions/v1.5.2/doc/doc/tutorial-set4most/index.rst similarity index 100% rename from doc/doc/tutorial-set4most/index.rst rename to prev_versions/v1.5.2/doc/doc/tutorial-set4most/index.rst diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index e0dab7f8..d2147460 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -178,7 +178,7 @@ def cart_prod(*args): if mode != -1 and mode != 0: codac_error("cart_prod: invalid input arguments, was expecting a " + mode_str[mode] + ", got a scalar domain") mode = 0 - lst.append(IntervalVector(1,Interval(arg))) + lst.append(IntervalVector([Interval(arg)])) elif isinstance(arg, (list,Vector,IntervalVector)): if mode != -1 and mode != 0: diff --git a/python/src/codac2_py_matlab.h b/python/src/codac2_py_matlab.h index 84854d6a..232ea746 100644 --- a/python/src/codac2_py_matlab.h +++ b/python/src/codac2_py_matlab.h @@ -10,15 +10,17 @@ #pragma once +#include + #define FOR_MATLAB false namespace codac2 { #if FOR_MATLAB - using size_t_type = double; + using Index_type = double; using int_type = double; #else - using size_t_type = size_t; + using Index_type = Index; using int_type = int; #endif @@ -40,7 +42,7 @@ namespace codac2 } template - size_t input_index(const I& x) + Index input_index(const I& x) { if constexpr(FOR_MATLAB) return x-1; diff --git a/python/src/core/CMakeLists.txt b/python/src/core/CMakeLists.txt index c936609b..0bc86a5a 100644 --- a/python/src/core/CMakeLists.txt +++ b/python/src/core/CMakeLists.txt @@ -13,14 +13,19 @@ contractors/codac2_py_Ctc.h contractors/codac2_py_CtcAction.cpp contractors/codac2_py_CtcCartProd.cpp + contractors/codac2_py_CtcCtcBoundary.cpp + contractors/codac2_py_CtcEmpty.cpp contractors/codac2_py_CtcFixpoint.cpp contractors/codac2_py_CtcInnerOuter.cpp + contractors/codac2_py_CtcIdentity.cpp contractors/codac2_py_CtcInter.cpp contractors/codac2_py_CtcInverse.h contractors/codac2_py_CtcInverseNotIn.h contractors/codac2_py_CtcLazy.cpp contractors/codac2_py_CtcNot.cpp contractors/codac2_py_CtcPolar.cpp + contractors/codac2_py_CtcPolygon.cpp + contractors/codac2_py_CtcProj.cpp contractors/codac2_py_CtcSegment.cpp contractors/codac2_py_CtcUnion.cpp contractors/codac2_py_CtcWrapper.cpp @@ -28,11 +33,14 @@ contractors/codac2_py_linear_ctc.cpp domains/ellipsoid/codac2_py_Ellipsoid.cpp + domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp domains/interval/codac2_py_Interval.cpp domains/interval/codac2_py_Interval_operations.cpp domains/interval/codac2_py_IntervalMatrix.cpp domains/interval/codac2_py_IntervalMatrixBase.h + domains/interval/codac2_py_IntervalRow.cpp domains/interval/codac2_py_IntervalVector.cpp + domains/interval/codac2_py_IntervalVector_templ.h domains/paving/codac2_py_Paving.cpp domains/paving/codac2_py_PavingNode.cpp domains/paving/codac2_py_Subpaving.cpp @@ -51,9 +59,10 @@ matrices/codac2_py_arithmetic_sub.cpp matrices/codac2_py_arithmetic_mul.cpp matrices/codac2_py_arithmetic_div.cpp + matrices/codac2_py_Inversion.cpp matrices/codac2_py_Matrix.cpp matrices/codac2_py_MatrixBase.h - matrices/codac2_py_MatrixBaseBlock.h + matrices/codac2_py_MatrixBlock.h matrices/codac2_py_Vector.cpp matrices/codac2_py_VectorBase.h @@ -108,4 +117,4 @@ # ex: from codac import core # core.Tube # ex: from codac.core import Tube - # Tube \ No newline at end of file + # Tube diff --git a/python/src/core/actions/codac2_py_OctaSym.cpp b/python/src/core/actions/codac2_py_OctaSym.cpp index 558b48f3..192678c0 100644 --- a/python/src/core/actions/codac2_py_OctaSym.cpp +++ b/python/src/core/actions/codac2_py_OctaSym.cpp @@ -34,7 +34,7 @@ void export_OctaSym(py::module& m) { vector v(l.size()); - size_t i = 0; + Index i = 0; for(const auto& li : l) { matlab::test_integer(li); @@ -57,7 +57,7 @@ void export_OctaSym(py::module& m) .def(py::self != py::self) .def("__call__", [](const OctaSym& a, const IntervalVector& x) { return a(x); }, - INTERVALVECTOR_OCTASYM_OPERATORCALL_CONST_INTERVALVECTOR_REF_CONST, + MAT_TMINUSONE1_OCTASYM_OPERATORCALL_CONST_MAT_TMINUSONE1_REF_CONST, "x"_a) .def("__call__", [](const OctaSym& a, const pyCtcIntervalVector& c) { return CtcAction(c.copy(),a); }, diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index 5085aedb..89c071a9 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -12,11 +12,13 @@ #include #include #include +#include +#include #include "codac2_py_AnalyticFunction.h" #include "codac2_py_CtcInverse.h" #include "codac2_py_CtcInverseNotIn.h" #include "codac2_py_SepInverse.h" -#include "codac2_py_MatrixBaseBlock.h" +#include "codac2_py_MatrixBlock.h" using namespace codac2; namespace py = pybind11; @@ -31,12 +33,17 @@ void export_OctaSym(py::module& m); py::class_,pyCtcIntervalVector> export_CtcIntervalVector(py::module& m/*, py::class_& py_ctc*/); void export_CtcAction(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcCartProd(py::module& m, py::class_,pyCtcIntervalVector>& ctc); +void export_CtcCtcBoundary(py::module& m, py::class_,pyCtcIntervalVector>& ctc); +void export_CtcEmpty(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcFixpoint(py::module& m, py::class_,pyCtcIntervalVector>& ctc); +void export_CtcIdentity(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcInnerOuter(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcInter(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcLazy(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcNot(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcPolar(py::module& m, py::class_,pyCtcIntervalVector>& ctc); +void export_CtcPolygon(py::module& m, py::class_,pyCtcIntervalVector>& ctc); +void export_CtcProj(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcSegment(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcUnion(py::module& m, py::class_,pyCtcIntervalVector>& ctc); void export_CtcWrapper(py::module& m, py::class_,pyCtcIntervalVector>& ctc); @@ -46,8 +53,10 @@ void export_linear_ctc(py::module& m); // domains void export_BoolInterval(py::module& m); void export_Ellipsoid(py::module& m); +void export_Ellipsoid_utils(py::module& m); py::class_ export_Interval(py::module& m); void export_Interval_operations(py::module& m, py::class_& py_Interval); +py::class_ export_IntervalRow(py::module& m); py::class_ export_IntervalVector(py::module& m); py::class_ export_IntervalMatrix(py::module& m); void export_Paving(py::module& m); @@ -66,24 +75,26 @@ void export_geometry(py::module& m); void export_Polygon(py::module& m); // matrices -void export_arithmetic_add(py::module& m, +void export_arithmetic_add( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, - py::class_&,double>>& py_B, py::class_&,Interval>>& py_IB); -void export_arithmetic_sub(py::module& m, + py::class_>& py_B, py::class_>& py_IB); +void export_arithmetic_sub( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, - py::class_&,double>>& py_B, py::class_&,Interval>>& py_IB); -void export_arithmetic_mul(py::module& m, + py::class_>& py_B, py::class_>& py_IB); +void export_arithmetic_mul( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, - py::class_&,double>>& py_B, py::class_&,Interval>>& py_IB); -void export_arithmetic_div(py::module& m, + py::class_>& py_B, py::class_>& py_IB); +void export_arithmetic_div( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, - py::class_&,double>>& py_B, py::class_&,Interval>>& py_IB); + py::class_>& py_B, py::class_>& py_IB); +py::class_ export_Row(py::module& m); py::class_ export_Vector(py::module& m); py::class_ export_Matrix(py::module& m); +void export_Inversion(py::module& m); // paver void export_pave(py::module& m); @@ -121,7 +132,10 @@ PYBIND11_MODULE(_core, m) auto py_ctc_iv = export_CtcIntervalVector(m/*,py_ctc*/); export_CtcAction(m, py_ctc_iv); export_CtcCartProd(m, py_ctc_iv); + export_CtcCtcBoundary(m, py_ctc_iv); + export_CtcEmpty(m, py_ctc_iv); export_CtcFixpoint(m, py_ctc_iv); + export_CtcIdentity(m, py_ctc_iv); export_CtcInnerOuter(m, py_ctc_iv); export_CtcInter(m, py_ctc_iv); export_CtcInverse(m,"CtcInverse_Interval",py_ctc_iv); @@ -131,6 +145,8 @@ PYBIND11_MODULE(_core, m) export_CtcLazy(m, py_ctc_iv); export_CtcNot(m, py_ctc_iv); export_CtcPolar(m, py_ctc_iv); + export_CtcPolygon(m, py_ctc_iv); + export_CtcProj(m, py_ctc_iv); export_CtcSegment(m, py_ctc_iv); export_CtcUnion(m, py_ctc_iv); export_CtcWrapper(m, py_ctc_iv); @@ -138,23 +154,31 @@ PYBIND11_MODULE(_core, m) export_linear_ctc(m); // matrices - auto py_M = export_Matrix(m); + py::class_ exported_row_class(m, "Row", DOC_TO_BE_DEFINED); auto py_V = export_Vector(m); - auto py_B = export_MatrixBaseBlock(m, "MatrixBaseBlock_Matrix_double"); + auto py_M = export_Matrix(m); + auto py_B = export_EigenBlock(m, "MatrixBlock"); + export_EigenBlock(m, "RowBlock"); + export_EigenBlock(m, "VectorBlock"); + export_Inversion(m); // domains export_BoolInterval(m); export_Ellipsoid(m); + export_Ellipsoid_utils(m); auto py_Interval = export_Interval(m); export_Interval_operations(m, py_Interval); + auto py_IR = export_IntervalRow(m); auto py_IV = export_IntervalVector(m); auto py_IM = export_IntervalMatrix(m); - auto py_IB = export_MatrixBaseBlock(m, "MatrixBaseBlock_IntervalMatrix_Interval"); - - export_arithmetic_add(m, py_V, py_IV, py_M, py_IM, py_B, py_IB); - export_arithmetic_sub(m, py_V, py_IV, py_M, py_IM, py_B, py_IB); - export_arithmetic_mul(m, py_V, py_IV, py_M, py_IM, py_B, py_IB); - export_arithmetic_div(m, py_V, py_IV, py_M, py_IM, py_B, py_IB); + auto py_IB = export_EigenBlock(m, "IntervalMatrixBlock"); + export_EigenBlock(m, "IntervalRowBlock"); + export_EigenBlock(m, "IntervalVectorBlock"); + + export_arithmetic_add(py_V, py_IV, py_M, py_IM, py_B, py_IB); + export_arithmetic_sub(py_V, py_IV, py_M, py_IM, py_B, py_IB); + export_arithmetic_mul(py_V, py_IV, py_M, py_IM, py_B, py_IB); + export_arithmetic_div(py_V, py_IV, py_M, py_IM, py_B, py_IB); export_Paving(m); export_PavingNode(m); @@ -197,4 +221,4 @@ PYBIND11_MODULE(_core, m) // tools export_Approx(m); -} \ No newline at end of file +} diff --git a/python/src/core/contractors/codac2_py_Ctc.cpp b/python/src/core/contractors/codac2_py_Ctc.cpp index fc44d53a..cc9aa9a9 100644 --- a/python/src/core/contractors/codac2_py_Ctc.cpp +++ b/python/src/core/contractors/codac2_py_Ctc.cpp @@ -36,11 +36,11 @@ py::class_,pyCtcIntervalVector> export_CtcIntervalVector py::class_,pyCtcIntervalVector> py_ctc_iv(m, "CtcIntervalVector"/*, py_ctc*/); py_ctc_iv - .def(py::init(), - CTCBASE_X_CTCBASE_SIZET) + .def(py::init(), + CTCBASE_X_CTCBASE_INDEX) .def("size", &CtcBase::size, - SIZET_CTCBASE_X_SIZE_CONST) + INDEX_CTCBASE_X_SIZE_CONST) .def("copy", [](const CtcBase& c) { diff --git a/python/src/core/contractors/codac2_py_Ctc.h b/python/src/core/contractors/codac2_py_Ctc.h index a26e4ea3..73d9626d 100644 --- a/python/src/core/contractors/codac2_py_Ctc.h +++ b/python/src/core/contractors/codac2_py_Ctc.h @@ -29,7 +29,7 @@ class pyCtcIntervalVector : public CtcBase { public: - pyCtcIntervalVector(size_t_type n) + pyCtcIntervalVector(Index_type n) : CtcBase(n) { matlab::test_integer(n); @@ -62,6 +62,8 @@ class pyCtcIntervalVector : public CtcBase assert_release(overload && "CtcBase: copy method not found"); auto obj = overload(); - return std::shared_ptr>(obj.cast*>(), [](auto p) { /* no delete */ }); + return std::shared_ptr>(obj.cast*>(), + []([[maybe_unused]] auto p) + { /* no delete */ }); } }; \ No newline at end of file diff --git a/python/src/core/contractors/codac2_py_CtcCtcBoundary.cpp b/python/src/core/contractors/codac2_py_CtcCtcBoundary.cpp new file mode 100644 index 00000000..fdd42b41 --- /dev/null +++ b/python/src/core/contractors/codac2_py_CtcCtcBoundary.cpp @@ -0,0 +1,41 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include +#include "codac2_py_Ctc.h" +#include "codac2_py_CtcCtcBoundary_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_CtcCtcBoundary(py::module& m, py::class_,pyCtcIntervalVector>& pyctc) +{ + py::class_ exported(m, "CtcCtcBoundary", pyctc, CTCCTCBOUNDARY_MAIN); + exported + + .def(py::init( + [](const CtcBase& ctc_boundary, const std::function& inside_test) + { + return std::make_unique(ctc_boundary.copy(),inside_test); + }), + CTCCTCBOUNDARY_CTCCTCBOUNDARY_CONST_C_REF_CONST_FUNCTION_BOOLINTERVAL_CONST_VECTOR_REF__REF, + "ctc_boundary"_a, "inside_test"_a) + + .def(CONTRACT_BOX_METHOD(CtcCtcBoundary, + VOID_CTCCTCBOUNDARY_CONTRACT_INTERVALVECTOR_REF_CONST)) + + ; +} \ No newline at end of file diff --git a/python/src/core/contractors/codac2_py_CtcEmpty.cpp b/python/src/core/contractors/codac2_py_CtcEmpty.cpp new file mode 100644 index 00000000..832ddd86 --- /dev/null +++ b/python/src/core/contractors/codac2_py_CtcEmpty.cpp @@ -0,0 +1,35 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include "codac2_py_Ctc.h" +#include "codac2_py_CtcEmpty_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_CtcEmpty(py::module& m, py::class_,pyCtcIntervalVector>& pyctc) +{ + py::class_ exported(m, "CtcEmpty", pyctc, CTCEMPTY_MAIN); + exported + + .def(py::init(), + CTCEMPTY_CTCEMPTY_INDEX + "n"_a) + + .def(CONTRACT_BOX_METHOD(CtcEmpty, + VOID_CTCEMPTY_CONTRACT_INTERVALVECTOR_REF_CONST)) + + ; +} \ No newline at end of file diff --git a/python/src/core/contractors/codac2_py_CtcIdentity.cpp b/python/src/core/contractors/codac2_py_CtcIdentity.cpp new file mode 100644 index 00000000..57e2f327 --- /dev/null +++ b/python/src/core/contractors/codac2_py_CtcIdentity.cpp @@ -0,0 +1,35 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include "codac2_py_Ctc.h" +#include "codac2_py_CtcIdentity_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_CtcIdentity(py::module& m, py::class_,pyCtcIntervalVector>& pyctc) +{ + py::class_ exported(m, "CtcIdentity", pyctc, CTCIDENTITY_MAIN); + exported + + .def(py::init(), + CTCIDENTITY_CTCIDENTITY_INDEX + "n"_a) + + .def(CONTRACT_BOX_METHOD(CtcIdentity, + VOID_CTCIDENTITY_CONTRACT_INTERVALVECTOR_REF_CONST)) + + ; +} \ No newline at end of file diff --git a/python/src/core/contractors/codac2_py_CtcInter.cpp b/python/src/core/contractors/codac2_py_CtcInter.cpp index 5d1f02ab..d3ea61d8 100644 --- a/python/src/core/contractors/codac2_py_CtcInter.cpp +++ b/python/src/core/contractors/codac2_py_CtcInter.cpp @@ -24,6 +24,10 @@ void export_CtcInter(py::module& m, py::class_,pyCtcInte py::class_> exported(m, "CtcInter", pyctc, CTCINTER_MAIN); exported + .def(py::init(), + CTCINTER_X_CTCINTER_INDEX, + "n"_a) + .def(py::init( [](const CtcBase& c) { diff --git a/python/src/core/contractors/codac2_py_CtcPolygon.cpp b/python/src/core/contractors/codac2_py_CtcPolygon.cpp new file mode 100644 index 00000000..8ce08d8b --- /dev/null +++ b/python/src/core/contractors/codac2_py_CtcPolygon.cpp @@ -0,0 +1,38 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include "codac2_py_Ctc.h" +#include "codac2_py_CtcPolygon_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_CtcPolygon(py::module& m, py::class_,pyCtcIntervalVector>& pyctc) +{ + py::class_ exported(m, "CtcPolygon", pyctc, CTCPOLYGON_MAIN); + exported + + .def(py::init(), + CTCPOLYGON_CTCPOLYGON_CONST_POLYGON_REF, + "p"_a) + + .def(CONTRACT_BOX_METHOD(CtcPolygon, + VOID_CTCPOLYGON_CONTRACT_INTERVALVECTOR_REF_CONST)) + + ; + + py::implicitly_convertible(); +} \ No newline at end of file diff --git a/python/src/core/contractors/codac2_py_CtcProj.cpp b/python/src/core/contractors/codac2_py_CtcProj.cpp new file mode 100644 index 00000000..2630aff6 --- /dev/null +++ b/python/src/core/contractors/codac2_py_CtcProj.cpp @@ -0,0 +1,64 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include "codac2_py_Ctc.h" +#include "codac2_py_CtcProj_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_CtcProj(py::module& m, py::class_,pyCtcIntervalVector>& pyctc) +{ + py::class_ exported(m, "CtcProj", pyctc, CTCPROJ_MAIN); + exported + + .def(py::init( + [](const CtcBase& c, std::vector proj_indices, double default_eps) + { + std::transform(std::begin(proj_indices),std::end(proj_indices),std::begin(proj_indices), + [](Index_type x) + { + matlab::test_integer(x); + return matlab::input_index(x); + }); + + return std::make_unique(c.copy(), proj_indices, default_eps); + }), + CTCPROJ_CTCPROJ_CONST_C_REF_CONST_VECTOR_INDEX_REF_DOUBLE, + "c"_a, "proj_indices"_a, "default_eps"_a=0.01) + + .def(py::init( + [](const CtcBase& c, std::vector proj_indices, const IntervalVector& y, double default_eps) + { + std::transform(std::begin(proj_indices),std::end(proj_indices),std::begin(proj_indices), + [](Index_type x) + { + matlab::test_integer(x); + return matlab::input_index(x); + }); + + return std::make_unique(c.copy(), proj_indices, y, default_eps); + }), + CTCPROJ_CTCPROJ_CONST_C_REF_CONST_VECTOR_INDEX_REF_CONST_INTERVALVECTOR_REF_DOUBLE, + "c"_a, "proj_indices"_a, "y"_a, "default_eps"_a=0.01) + + .def("contract", (void(CtcProj::*)(IntervalVector&,double) const) &CtcProj::contract, + VOID_CTCPROJ_CONTRACT_INTERVALVECTOR_REF_DOUBLE_CONST, + "x"_a, "eps"_a) + + .def(CONTRACT_BOX_METHOD(CtcProj, + VOID_CTCPROJ_CONTRACT_INTERVALVECTOR_REF_CONST)) + ; +} \ No newline at end of file diff --git a/python/src/core/contractors/codac2_py_CtcUnion.cpp b/python/src/core/contractors/codac2_py_CtcUnion.cpp index 9282c873..2505b2ed 100644 --- a/python/src/core/contractors/codac2_py_CtcUnion.cpp +++ b/python/src/core/contractors/codac2_py_CtcUnion.cpp @@ -24,6 +24,10 @@ void export_CtcUnion(py::module& m, py::class_,pyCtcInte py::class_> exported(m, "CtcUnion", pyctc, CTCUNION_MAIN); exported + .def(py::init(), + CTCUNION_X_CTCUNION_INDEX, + "n"_a) + .def(py::init( [](const CtcBase& c) { diff --git a/python/src/core/contractors/codac2_py_directed_ctc.cpp b/python/src/core/contractors/codac2_py_directed_ctc.cpp index 5190a954..bfc07beb 100644 --- a/python/src/core/contractors/codac2_py_directed_ctc.cpp +++ b/python/src/core/contractors/codac2_py_directed_ctc.cpp @@ -335,11 +335,11 @@ void export_directed_ctc(py::module& m) py::class_(m, "ComponentOp") - .def_static("fwd", (Interval(*)(const IntervalVector&,size_t)) &ComponentOp::fwd, - STATIC_INTERVAL_COMPONENTOP_FWD_CONST_INTERVALVECTOR_REF_SIZET, + .def_static("fwd", (Interval(*)(const IntervalVector&,Index)) &ComponentOp::fwd, + STATIC_INTERVAL_COMPONENTOP_FWD_CONST_INTERVALVECTOR_REF_INDEX, "x1"_a, "i"_a) - .def_static("bwd", (void(*)(const Interval&,IntervalVector&,size_t)) &ComponentOp::bwd, - STATIC_VOID_COMPONENTOP_BWD_CONST_INTERVAL_REF_INTERVALVECTOR_REF_SIZET, + .def_static("bwd", (void(*)(const Interval&,IntervalVector&,Index)) &ComponentOp::bwd, + STATIC_VOID_COMPONENTOP_BWD_CONST_INTERVAL_REF_INTERVALVECTOR_REF_INDEX, "y"_a, "x1"_a, "i"_a) ; diff --git a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp index a65e7f85..e1784a10 100644 --- a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp +++ b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp @@ -29,8 +29,8 @@ void export_Ellipsoid(py::module& m) .def_readwrite("G", &Ellipsoid::G, MATRIX_ELLIPSOID_G) - .def(py::init(), - ELLIPSOID_ELLIPSOID_SIZET, + .def(py::init(), + ELLIPSOID_ELLIPSOID_INDEX, "n"_a) .def(py::init(), @@ -40,15 +40,8 @@ void export_Ellipsoid(py::module& m) .def(py::init(), "e"_a) - .def("__repr__", [](const Ellipsoid& e) { - std::ostringstream s; - s << e; - return string(s.str()); - }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_ELLIPSOID_REF) - .def("size", &Ellipsoid::size, - SIZET_ELLIPSOID_SIZE_CONST) + INDEX_ELLIPSOID_SIZE_CONST) .def("rand", &Ellipsoid::rand, VECTOR_ELLIPSOID_RAND_CONST) @@ -60,8 +53,20 @@ void export_Ellipsoid(py::module& m) BOOLINTERVAL_ELLIPSOID_IS_CONCENTRIC_SUBSET_CONST_ELLIPSOID_REF_CONST, "e"_a) + .def("proj_2d", &Ellipsoid::proj_2d, + ELLIPSOID_ELLIPSOID_PROJ_2D_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST, + "d"_a, "v"_a, "u"_a) + + .def("__repr__", [](const Ellipsoid& e) { + std::ostringstream s; + s << e; + return string(s.str()); + }, + OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_ELLIPSOID_REF) + .def(py::self + py::self, - ELLIPSOID_OPERATORPLUS_CONST_ELLIPSOID_REF_CONST_ELLIPSOID_REF) + ELLIPSOID_OPERATORPLUS_CONST_ELLIPSOID_REF_CONST_ELLIPSOID_REF, + py::is_operator()) ; diff --git a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp new file mode 100644 index 00000000..1fd51de1 --- /dev/null +++ b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp @@ -0,0 +1,35 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include "codac2_py_Ellipsoid_utils_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_Ellipsoid_utils(py::module& m) +{ + m + + .def("stability_analysis", &codac2::stability_analysis, + BOOLINTERVAL_STABILITY_ANALYSIS_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF_UNSIGNED_INT_ELLIPSOID_REF_ELLIPSOID_REF_BOOL, + "f"_a, "alpha_max"_a, "e"_a, "e_out"_a, "verbose"_a=false) + + .def("solve_discrete_lyapunov", &codac2::solve_discrete_lyapunov, + MATRIX_SOLVE_DISCRETE_LYAPUNOV_CONST_MATRIX_REF_CONST_MATRIX_REF, + "A"_a, "Q"_a) + + ; +} \ No newline at end of file diff --git a/python/src/core/domains/interval/codac2_py_Interval.cpp b/python/src/core/domains/interval/codac2_py_Interval.cpp index d64f0364..f2d5cd70 100644 --- a/python/src/core/domains/interval/codac2_py_Interval.cpp +++ b/python/src/core/domains/interval/codac2_py_Interval.cpp @@ -77,6 +77,12 @@ py::class_ export_Interval(py::module& m) .def("mid", &Interval::mid, DOUBLE_INTERVAL_MID_CONST) + .def("mag", &Interval::mag, + DOUBLE_INTERVAL_MAG_CONST) + + .def("mig", &Interval::mig, + DOUBLE_INTERVAL_MIG_CONST) + .def("rand", &Interval::rand, DOUBLE_INTERVAL_RAND_CONST) @@ -90,7 +96,7 @@ py::class_ export_Interval(py::module& m) DOUBLE_INTERVAL_VOLUME_CONST) .def("size", &Interval::size, - SIZET_INTERVAL_SIZE_CONST) + INDEX_INTERVAL_SIZE_CONST) .def("set_empty", &Interval::set_empty, VOID_INTERVAL_SET_EMPTY) @@ -266,4 +272,4 @@ py::class_ export_Interval(py::module& m) "x"_a); return exported_interval_class; -} \ No newline at end of file +} diff --git a/python/src/core/domains/interval/codac2_py_IntervalMatrix.cpp b/python/src/core/domains/interval/codac2_py_IntervalMatrix.cpp index feeb208e..d27bc63d 100644 --- a/python/src/core/domains/interval/codac2_py_IntervalMatrix.cpp +++ b/python/src/core/domains/interval/codac2_py_IntervalMatrix.cpp @@ -12,11 +12,32 @@ #include #include #include +#include +#include +#include +#include #include -#include "codac2_py_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_doc.h" +#include "codac2_py_Matrix_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_matrices_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_matrices_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_IntervalMatrix_docs.h" #include "codac2_py_IntervalMatrixBase.h" @@ -27,79 +48,75 @@ using namespace pybind11::literals; py::class_ export_IntervalMatrix(py::module& m) { - py::class_ exported_intervalmatrix_class(m, "IntervalMatrix", INTERVALMATRIX_MAIN); + py::class_ exported_intervalmatrix_class(m, "IntervalMatrix", DOC_TO_BE_DEFINED); export_IntervalMatrixBase(m, exported_intervalmatrix_class); exported_intervalmatrix_class .def(py::init( - [](size_t_type r, size_t_type c) + [](Index_type r, Index_type c) { matlab::test_integer(r,c); return std::make_unique(r,c); }), - INTERVALMATRIX_INTERVALMATRIX_SIZET_SIZET, + DOC_TO_BE_DEFINED, "r"_a, "c"_a) - .def(py::init( - [](size_t_type r, size_t_type c, const Interval& x) - { - matlab::test_integer(r,c); - return std::make_unique(r,c,x); - }), - INTERVALMATRIX_INTERVALMATRIX_SIZET_SIZET_CONST_INTERVAL_REF, - "r"_a, "c"_a, "x"_a) - .def(py::init(), "x"_a) .def(py::init(), - INTERVALMATRIX_INTERVALMATRIX_CONST_MATRIX_REF, "x"_a) .def(py::init(), - INTERVALMATRIX_INTERVALMATRIX_CONST_MATRIX_REF_CONST_MATRIX_REF, + MATRIX_ADDONS_INTERVALMATRIXBASE_MATRIX_CONST_MATRIX_DOUBLERC_REF_CONST_MATRIX_DOUBLERC_REF, "lb"_a, "ub"_a) - .def(py::init(), - INTERVALMATRIX_INTERVALMATRIX_CONST_INTERVALVECTOR_REF, + .def(py::init(), + DOC_TO_BE_DEFINED, "x"_a) - .def(py::init&,double>&>(), - INTERVALMATRIX_INTERVALMATRIX_CONST_MATRIXBASEBLOCK_QT_REF, + .def(py::init(), + DOC_TO_BE_DEFINED, "x"_a) - .def(py::init&,Interval>&>(), - INTERVALMATRIX_INTERVALMATRIX_CONST_MATRIXBASEBLOCK_QT_REF, + .def(py::init&>(), + DOC_TO_BE_DEFINED, + "x"_a) + + .def(py::init&>(), + DOC_TO_BE_DEFINED, "x"_a) .def(py::init( // this constructor must be the last one to be declared [](const std::vector& v) { assert_release(!std::empty(v)); - auto iv = std::make_unique(v.size(),v[0].size()); + auto im = std::make_unique(v.size(),v[0].size()); for(size_t i = 0 ; i < v.size() ; i++) { - assert_release(v[i].size() == iv->nb_cols() && "IntervalVector objects of different size"); - iv->row(i) = v[i].transpose(); + assert_release(v[i].size() == im->cols() && "IntervalVector objects of different size"); + im->row(i) = v[i].transpose(); } - return iv; + return im; }), - INTERVALMATRIX_INTERVALMATRIX_INITIALIZER_LIST_INITIALIZER_LIST_INTERVAL, + DOC_TO_BE_DEFINED, "v"_a) - .def("transpose", &IntervalMatrix::transpose, - INTERVALMATRIX_INTERVALMATRIX_TRANSPOSE_CONST) + .def(py::init(), + DOC_TO_BE_DEFINED, + "x"_a) - .def("diag_matrix", &IntervalMatrix::diag_matrix, - INTERVALMATRIX_INTERVALMATRIX_DIAG_MATRIX_CONST) + .def(py::init(), + DOC_TO_BE_DEFINED, + "x"_a) - .def_static("empty", [](size_t_type r, size_t_type c) + .def_static("empty", [](Index_type r, Index_type c) { matlab::test_integer(r,c); return IntervalMatrix::empty(r,c); }, - STATIC_INTERVALMATRIX_INTERVALMATRIX_EMPTY_SIZET_SIZET, + MATRIX_ADDONS_INTERVALMATRIXBASE_STATIC_AUTO_EMPTY_INDEX_INDEX, "r"_a, "c"_a) .def("__repr__", [](const IntervalMatrix& x) diff --git a/python/src/core/domains/interval/codac2_py_IntervalMatrixBase.h b/python/src/core/domains/interval/codac2_py_IntervalMatrixBase.h index e7890645..1204acb8 100644 --- a/python/src/core/domains/interval/codac2_py_IntervalMatrixBase.h +++ b/python/src/core/domains/interval/codac2_py_IntervalMatrixBase.h @@ -28,142 +28,154 @@ void export_IntervalMatrixBase(py::module& m, py::class_& pyclass) pyclass - .def("volume", &S::volume, - DOUBLE_INTERVALMATRIXBASE_SV_VOLUME_CONST) + .def("volume", [](const S& x) { return x.volume(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_DOUBLE_VOLUME_CONST) - .def("is_empty", &S::is_empty, - BOOL_INTERVALMATRIXBASE_SV_IS_EMPTY_CONST) + .def("is_empty", [](const S& x) { return x.is_empty(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_EMPTY_CONST) - .def("set_empty", &S::set_empty, - VOID_INTERVALMATRIXBASE_SV_SET_EMPTY) + .def("set_empty", [](S& x) { x.set_empty(); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_VOID_SET_EMPTY) - .def("lb", &S::lb, - V_INTERVALMATRIXBASE_SV_LB_CONST) + .def("lb", [](const S& x) { return x.lb(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_LB_CONST) - .def("ub", &S::ub, - V_INTERVALMATRIXBASE_SV_UB_CONST) + .def("ub", [](const S& x) { return x.ub(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_UB_CONST) - .def("mid", &S::mid, - V_INTERVALMATRIXBASE_SV_MID_CONST) + .def("mid", [](const S& x) { return x.mid(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_MID_CONST) - .def("rand", &S::rand, - V_INTERVALMATRIXBASE_SV_RAND_CONST) + .def("mag", [](const S& x) { return x.mag(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_MAG_CONST) - .def("rad", &S::rad, - V_INTERVALMATRIXBASE_SV_RAD_CONST) + .def("mig", [](const S& x) { return x.mig(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_MIG_CONST) - .def("diam", &S::diam, - V_INTERVALMATRIXBASE_SV_DIAM_CONST) + .def("rand", [](const S& x) { return x.rand(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_RAND_CONST) - .def("min_diam", &S::min_diam, - DOUBLE_INTERVALMATRIXBASE_SV_MIN_DIAM_CONST) + .def("rad", [](const S& x) { return x.rad(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_RAD_CONST) - .def("max_diam", &S::max_diam, - DOUBLE_INTERVALMATRIXBASE_SV_MAX_DIAM_CONST) + .def("diam", [](const S& x) { return x.diam(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_AUTO_DIAM_CONST) + + .def("min_rad", [](const S& x) { return x.min_rad(); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_DOUBLE_MIN_RAD_CONST) + + .def("max_rad", [](const S& x) { return x.max_rad(); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_DOUBLE_MAX_RAD_CONST) + + .def("min_diam", [](const S& x) { return x.min_diam(); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_DOUBLE_MIN_DIAM_CONST) + + .def("max_diam", [](const S& x) { return x.max_diam(); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_DOUBLE_MAX_DIAM_CONST) .def("min_diam_index", [](const S& x) { return matlab::output_index(x.min_diam_index()); }, - SIZET_INTERVALMATRIXBASE_SV_MIN_DIAM_INDEX_CONST) + MATRIX_ADDONS_INTERVALMATRIXBASE_INDEX_MIN_DIAM_INDEX_CONST) .def("max_diam_index", [](const S& x) { return matlab::output_index(x.max_diam_index()); }, - SIZET_INTERVALMATRIXBASE_SV_MAX_DIAM_INDEX_CONST) + MATRIX_ADDONS_INTERVALMATRIXBASE_INDEX_MAX_DIAM_INDEX_CONST) .def("extr_diam_index", [](const S& x, bool min) { return matlab::output_index(x.extr_diam_index(min)); }, - SIZET_INTERVALMATRIXBASE_SV_EXTR_DIAM_INDEX_BOOL_CONST, + MATRIX_ADDONS_INTERVALMATRIXBASE_INDEX_EXTR_DIAM_INDEX_BOOL_CONST, "min"_a) - .def("__contains__", &S::contains, - BOOL_INTERVALMATRIXBASE_SV_CONTAINS_CONST_V_REF_CONST) + .def("__contains__", [](const S& x, const V& y) { return x.contains(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_CONTAINS_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("contains", &S::contains, - BOOL_INTERVALMATRIXBASE_SV_CONTAINS_CONST_V_REF_CONST) + .def("contains", [](const S& x, const V& y) { return x.contains(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_CONTAINS_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("interior_contains", &S::interior_contains, - BOOL_INTERVALMATRIXBASE_SV_INTERIOR_CONTAINS_CONST_V_REF_CONST) + .def("interior_contains", [](const S& x, const V& y) { return x.interior_contains(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_INTERIOR_CONTAINS_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_unbounded", &S::is_unbounded, - BOOL_INTERVALMATRIXBASE_SV_IS_UNBOUNDED_CONST) + .def("is_unbounded", [](const S& x) { return x.is_unbounded(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_UNBOUNDED_CONST) - .def("is_degenerated", &S::is_degenerated, - BOOL_INTERVALMATRIXBASE_SV_IS_DEGENERATED_CONST) + .def("is_degenerated", [](const S& x) { return x.is_degenerated(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_DEGENERATED_CONST) - .def("is_flat", &S::is_flat, - BOOL_INTERVALMATRIXBASE_SV_IS_FLAT_CONST) + .def("is_flat", [](const S& x) { return x.is_flat(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_FLAT_CONST) - .def("intersects", &S::intersects, - BOOL_INTERVALMATRIXBASE_SV_INTERSECTS_CONST_S_REF_CONST) + .def("intersects", [](const S& x, const S& y) { return x.intersects(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_INTERSECTS_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_disjoint", &S::is_disjoint, - BOOL_INTERVALMATRIXBASE_SV_IS_DISJOINT_CONST_S_REF_CONST) + .def("is_disjoint", [](const S& x, const S& y) { return x.is_disjoint(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_DISJOINT_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("overlaps", &S::overlaps, - BOOL_INTERVALMATRIXBASE_SV_OVERLAPS_CONST_S_REF_CONST) + .def("overlaps", [](const S& x, const S& y) { return x.overlaps(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_OVERLAPS_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_subset", &S::is_subset, - BOOL_INTERVALMATRIXBASE_SV_IS_SUBSET_CONST_S_REF_CONST) + .def("is_subset", [](const S& x, const S& y) { return x.is_subset(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_SUBSET_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_strict_subset", &S::is_strict_subset, - BOOL_INTERVALMATRIXBASE_SV_IS_STRICT_SUBSET_CONST_S_REF_CONST) + .def("is_strict_subset", [](const S& x, const S& y) { return x.is_strict_subset(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_STRICT_SUBSET_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_interior_subset", &S::is_interior_subset, - BOOL_INTERVALMATRIXBASE_SV_IS_INTERIOR_SUBSET_CONST_S_REF_CONST) + .def("is_interior_subset", [](const S& x, const S& y) { return x.is_interior_subset(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_INTERIOR_SUBSET_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_strict_interior_subset", &S::is_strict_interior_subset, - BOOL_INTERVALMATRIXBASE_SV_IS_STRICT_INTERIOR_SUBSET_CONST_S_REF_CONST) + .def("is_strict_interior_subset", [](const S& x, const S& y) { return x.is_strict_interior_subset(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_STRICT_INTERIOR_SUBSET_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_superset", &S::is_superset, - BOOL_INTERVALMATRIXBASE_SV_IS_SUPERSET_CONST_S_REF_CONST) + .def("is_superset", [](const S& x, const S& y) { return x.is_superset(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_SUPERSET_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_strict_superset", &S::is_strict_superset, - BOOL_INTERVALMATRIXBASE_SV_IS_STRICT_SUPERSET_CONST_S_REF_CONST) + .def("is_strict_superset", [](const S& x, const S& y) { return x.is_strict_superset(y); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_STRICT_SUPERSET_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST) - .def("is_bisectable", &S::is_bisectable, - BOOL_INTERVALMATRIXBASE_SV_IS_BISECTABLE_CONST) + .def("is_bisectable", [](const S& x) { return x.is_bisectable(); }, + MATRIXBASE_ADDONS_INTERVALMATRIXBASE_BOOL_IS_BISECTABLE_CONST) - .def("inflate", (S&(S::*)(double))&S::inflate, - S_REF_INTERVALMATRIXBASE_SV_INFLATE_DOUBLE, + .def("inflate", [](S& x, double r) { return x.inflate(r); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_REF_INFLATE_DOUBLE, "r"_a) - .def("inflate", (S&(S::*)(const V&))&S::inflate, - S_REF_INTERVALMATRIXBASE_SV_INFLATE_CONST_V_REF, + .def("inflate", [](S& x, const V& r) { return x.inflate(r); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_REF_INFLATE_CONST_MATRIXBASE_OTHERDERIVED_REF, "r"_a) - .def("bisect", [](const S& x, size_t_type i, double ratio) + .def("bisect", [](const S& x, Index_type i, double ratio) { matlab::test_integer(i); return x.bisect(matlab::input_index(i),ratio); }, - PAIR_SS_INTERVALMATRIXBASE_SV_BISECT_SIZET_FLOAT_CONST, + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_BISECT_INDEX_FLOAT_CONST, "i"_a, "ratio"_a = 0.49) - .def("bisect_largest", &S::bisect_largest, - PAIR_SS_INTERVALMATRIXBASE_SV_BISECT_LARGEST_FLOAT_CONST, + .def("bisect_largest", [](const S& x, double ratio = 0.49) { return x.bisect_largest(ratio); }, + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_BISECT_LARGEST_FLOAT_CONST, "ratio"_a = 0.49) .def(py::self &= py::self, - S_REF_INTERVALMATRIXBASE_SV_OPERATORANDEQ_CONST_S_REF + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_REF_OPERATORANDEQ_CONST_MATRIXBASE_OTHERDERIVED_REF "x"_a) .def(py::self |= py::self, - S_REF_INTERVALMATRIXBASE_SV_OPERATOROREQ_CONST_S_REF + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_REF_OPERATOROREQ_CONST_MATRIXBASE_OTHERDERIVED_REF "x"_a) .def(py::self & py::self, - S_INTERVALMATRIXBASE_SV_OPERATORAND_CONST_S_REF_CONST + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_OPERATORAND_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST "x"_a) .def(py::self | py::self, - S_INTERVALMATRIXBASE_SV_OPERATOROR_CONST_S_REF_CONST, + MATRIX_ADDONS_INTERVALMATRIXBASE_AUTO_OPERATOROR_CONST_MATRIXBASE_OTHERDERIVED_REF_CONST, "x"_a) ; py::implicitly_convertible(); -} \ No newline at end of file +} diff --git a/python/src/core/domains/interval/codac2_py_IntervalRow.cpp b/python/src/core/domains/interval/codac2_py_IntervalRow.cpp new file mode 100644 index 00000000..80c828b6 --- /dev/null +++ b/python/src/core/domains/interval/codac2_py_IntervalRow.cpp @@ -0,0 +1,51 @@ +/** + * Interval Python binding + * Originated from the former pyIbex library (Benoît Desrochers) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Benoît Desrochers, Simon Rohou, Fabrice Le Bars + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "codac2_py_doc.h" +#include "codac2_py_Matrix_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_matrices_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_IntervalVector_docs.h" + +#include "codac2_py_IntervalVector_templ.h" + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +py::class_ export_IntervalRow(py::module& m) +{ + py::class_ exported_intervalrow_class(m, "IntervalRow", DOC_TO_BE_DEFINED); + export_IntervalVector_(m, exported_intervalrow_class); + return exported_intervalrow_class; +} \ No newline at end of file diff --git a/python/src/core/domains/interval/codac2_py_IntervalVector.cpp b/python/src/core/domains/interval/codac2_py_IntervalVector.cpp index c7c758dd..82642be6 100644 --- a/python/src/core/domains/interval/codac2_py_IntervalVector.cpp +++ b/python/src/core/domains/interval/codac2_py_IntervalVector.cpp @@ -13,14 +13,29 @@ #include #include #include - -#include "codac2_py_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) - -#include "codac2_py_VectorBase.h" -#include "codac2_py_IntervalMatrixBase.h" +#include + +#include "codac2_py_doc.h" +#include "codac2_py_Matrix_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_matrices_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_IntervalVector_docs.h" + +#include "codac2_py_IntervalVector_templ.h" using namespace std; using namespace codac2; @@ -29,110 +44,7 @@ using namespace pybind11::literals; py::class_ export_IntervalVector(py::module& m) { - py::class_ exported_intervalvector_class(m, "IntervalVector", INTERVALVECTOR_MAIN); - export_IntervalMatrixBase(m, exported_intervalvector_class); - export_VectorBase(m, exported_intervalvector_class); - - exported_intervalvector_class - - .def(py::init( - [](size_t_type n) - { - matlab::test_integer(n); - return std::make_unique(n); - }), - INTERVALVECTOR_INTERVALVECTOR_SIZET, - "n"_a) - - .def(py::init( - [](size_t_type n, const Interval& x) - { - matlab::test_integer(n); - return std::make_unique(n,x); - }), - INTERVALVECTOR_INTERVALVECTOR_SIZET_CONST_INTERVAL_REF, - "n"_a, "x"_a) - - .def(py::init(), - "x"_a) - - .def(py::init(), - INTERVALVECTOR_INTERVALVECTOR_CONST_VECTOR_REF, - "x"_a) - - .def(py::init(), - INTERVALVECTOR_INTERVALVECTOR_CONST_VECTOR_REF_CONST_VECTOR_REF, - "lb"_a, "ub"_a) - - .def(py::init( // this constructor must be the last one to be declared - [](const std::vector& v) - { - auto iv = std::make_unique(v.size()); - for(size_t i = 0 ; i < v.size() ; i++) - (*iv)[i] = v[i]; - return iv; - }), - INTERVALVECTOR_INTERVALVECTOR_INITIALIZER_LIST_INTERVAL, - "v"_a) - - .def(py::init( // this constructor must be the last one to be declared - [](const std::vector>& v) - { - auto iv = std::make_unique(v.size()); - for(size_t i = 0 ; i < v.size() ; i++) - { - if(v[i].size() == 1) - (*iv)[i] = Interval(v[i][0]); - else if(v[i].size() == 2) - (*iv)[i] = Interval(v[i][0],v[i][1]); - else - throw invalid_argument("Interval is not made of one or two values."); - } - return iv; - }), - INTERVALVECTOR_INTERVALVECTOR_INITIALIZER_LIST_INTERVAL, - "v"_a) - - .def("complementary", &IntervalVector::complementary, - LIST_INTERVALVECTOR_INTERVALVECTOR_COMPLEMENTARY_CONST) - - .def("diff", &IntervalVector::diff, - LIST_INTERVALVECTOR_INTERVALVECTOR_DIFF_CONST_INTERVALVECTOR_REF_BOOL_CONST, - "y"_a, "compactness"_a = true) - - .def_static("empty", [](size_t_type n) - { - matlab::test_integer(n); - return IntervalVector::empty(n); - }, - STATIC_INTERVALVECTOR_INTERVALVECTOR_EMPTY_SIZET, - "n"_a) - - .def("__repr__", [](const IntervalVector& x) - { - std::ostringstream s; - s << x; - return string(s.str()); - }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_INTERVALVECTOR_REF) - - ; - - py::implicitly_convertible(); - - m.def("cart_prod_boxes", [](const std::list& l) - { - IntervalVector c = *l.begin(); - for(auto it = std::next(l.cbegin()); it != l.cend(); it++) - c = cart_prod(c,*it); - return c; - }, - INTERVALVECTOR_CART_PROD_CONST_X_REF_VARIADIC); - // The variadic version of this function is defined in __init__.py file - - m.def("hull", &codac2::hull, - INTERVALVECTOR_HULL_CONST_LIST_INTERVALVECTOR_REF, - "l"_a); - + py::class_ exported_intervalvector_class(m, "IntervalVector", DOC_TO_BE_DEFINED); + export_IntervalVector_(m, exported_intervalvector_class); return exported_intervalvector_class; } \ No newline at end of file diff --git a/python/src/core/domains/interval/codac2_py_IntervalVector_templ.h b/python/src/core/domains/interval/codac2_py_IntervalVector_templ.h new file mode 100644 index 00000000..e55418c8 --- /dev/null +++ b/python/src/core/domains/interval/codac2_py_IntervalVector_templ.h @@ -0,0 +1,111 @@ +/** + * IV_templ binding + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include +#include +#include + +#include + +#include "codac2_py_MatrixBase.h" +#include "codac2_py_IntervalMatrixBase.h" +#include "codac2_py_VectorBase.h" + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + + +template +void export_IntervalVector_(py::module& m, py::class_& pyclass) +{ + export_IntervalMatrixBase(m, pyclass); + export_VectorBase(m, pyclass); + + pyclass + + .def(py::init( + [](Index_type n) + { + matlab::test_integer(n); + return std::make_unique(n); + }), + DOC_TO_BE_DEFINED, + "n"_a) + + .def(py::init(), + "x"_a) + + .def(py::init(), + "x"_a) + + .def(py::init(), + MATRIX_ADDONS_INTERVALMATRIXBASE_MATRIX_CONST_MATRIX_DOUBLERC_REF_CONST_MATRIX_DOUBLERC_REF, + "lb"_a, "ub"_a) + + .def(py::init( // this constructor must be the last one to be declared + [](const std::vector& v) + { + auto iv = std::make_unique(v.size()); + for(size_t i = 0 ; i < v.size() ; i++) + (*iv)[i] = v[i]; + return iv; + }), + MATRIX_ADDONS_INTERVALVECTOR_MATRIX_CONST_INITIALIZER_LIST_INTERVAL_REF, + "v"_a) + + .def("complementary", [](const IV& x) { return x.complementary(); }, + MATRIXBASE_ADDONS_INTERVALVECTOR_AUTO_COMPLEMENTARY_CONST) + + .def("diff", [](const IV& x, const IV& y, bool compactness = true) { return x.diff(y,compactness); }, + MATRIXBASE_ADDONS_INTERVALVECTOR_LIST_MATRIX_INTERVALRC_DIFF_CONST_MATRIXBASE_OTHERDERIVED_REF_BOOL_CONST, + "y"_a, "compactness"_a = true) + + .def_static("empty", [](Index_type n) + { + matlab::test_integer(n); + return IV::empty(n); + }, + MATRIX_ADDONS_INTERVALVECTOR_STATIC_AUTO_EMPTY_INDEX, + "n"_a) + + .def("__repr__", [](const IV& x) + { + std::ostringstream s; + s << x; + return string(s.str()); + }, + OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_INTERVALVECTOR_REF) + + ; + + py::implicitly_convertible(); + py::implicitly_convertible(); + + if constexpr(std::is_same_v) + { + m.def("cart_prod_boxes", [](const std::list& l) + { + IV c = *l.begin(); + for(auto it = std::next(l.cbegin()); it != l.cend(); it++) + c = cart_prod(c,*it); + return c; + }, + INTERVALVECTOR_CART_PROD_CONST_X_REF_VARIADIC); + // The variadic version of this function is defined in __init__.py file + } + + m.def("hull", [](const std::list& l) { return hull(l); }, + AUTO_HULL_CONST_LIST_EIGEN_MATRIX_SCALARROWSATCOMPILETIMECOLSATCOMPILETIME_REF, + "l"_a); +} \ No newline at end of file diff --git a/python/src/core/domains/paving/codac2_py_Paving.cpp b/python/src/core/domains/paving/codac2_py_Paving.cpp index f5692f6f..55be29b5 100644 --- a/python/src/core/domains/paving/codac2_py_Paving.cpp +++ b/python/src/core/domains/paving/codac2_py_Paving.cpp @@ -28,7 +28,7 @@ void export_paving_base(py::class_

& c) c .def("size", &Paving::size, - SIZET_PAVING_PX_SIZE_CONST) + INDEX_PAVING_PX_SIZE_CONST) .def("tree", (std::shared_ptr>(Paving::*)()) &Paving::tree, SHARED_PTR_PAVINGNODE_P_PAVING_PX_TREE) @@ -46,8 +46,8 @@ void export_Paving(py::module& m) export_paving_base(exported_paving_out); exported_paving_out - .def(py::init(), - PAVINGOUT_PAVINGOUT_SIZET) + .def(py::init(), + PAVINGOUT_PAVINGOUT_INDEX) .def(py::init(), PAVINGOUT_PAVINGOUT_CONST_INTERVALVECTOR_REF) @@ -71,8 +71,8 @@ void export_Paving(py::module& m) export_paving_base(exported_paving_inout); exported_paving_inout - .def(py::init(), - PAVINGINOUT_PAVINGINOUT_SIZET) + .def(py::init(), + PAVINGINOUT_PAVINGINOUT_INDEX) .def(py::init(), PAVINGINOUT_PAVINGINOUT_CONST_INTERVALVECTOR_REF) diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index 368369b9..9dd8c75b 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -68,7 +68,7 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) [](const std::vector& l, const ExprWrapper& expr) { FunctionArgsList args {}; - size_t i = 0; + Index i = 0; for(const auto& li : l) { @@ -89,7 +89,7 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) ), ANALYTICFUNCTION_T_ANALYTICFUNCTION_CONST_FUNCTIONARGSLIST_REF_CONST_SHARED_PTR_ANALYTICEXPR_T_REF) .def("input_size", &AnalyticFunction::input_size, - SIZET_FUNCTIONBASE_E_INPUT_SIZE_CONST) + INDEX_FUNCTIONBASE_E_INPUT_SIZE_CONST) .def("__call__", [](const AnalyticFunction& f, const std::vector& x) { @@ -115,7 +115,7 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) .def("__repr__", [](const AnalyticFunction& f) { std::ostringstream stream; stream << f; - return string(stream.str()); + return std::string(stream.str()); }, OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_ANALYTICFUNCTION_T_REF) ; diff --git a/python/src/core/functions/analytic/codac2_py_ExprWrapper.h b/python/src/core/functions/analytic/codac2_py_ExprWrapper.h index ec86d507..0bac7b35 100644 --- a/python/src/core/functions/analytic/codac2_py_ExprWrapper.h +++ b/python/src/core/functions/analytic/codac2_py_ExprWrapper.h @@ -39,7 +39,7 @@ struct ExprWrapperBase }; template<> -struct ExprWrapper : public ExprWrapperBase +struct ExprWrapper { ExprWrapper(const Interval& e) : e(std::dynamic_pointer_cast>(const_value(e)->copy())) @@ -110,7 +110,7 @@ inline ScalarExpr operator/(const ScalarExpr& e1, const ScalarExpr& e2) } template<> -struct ExprWrapper : public ExprWrapperBase +struct ExprWrapper { ExprWrapper(const IntervalVector& e) : e(std::dynamic_pointer_cast>(const_value(e)->copy())) diff --git a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp index 58e6c73e..ba7f2c7f 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp @@ -32,7 +32,7 @@ void export_ScalarVar(py::module& m) SCALARVAR_SCALARVAR) .def("size", &ScalarVar::size, - SIZET_SCALARVAR_SIZE_CONST) + INDEX_SCALARVAR_SIZE_CONST) .def("__pos__", [](const ScalarVar& e1) { return ScalarExpr(ScalarExpr(e1)); }, py::is_operator()) .def("__add__", [](const ScalarVar& e1, const ScalarVar& e2) { return ScalarExpr(ScalarExpr(e1) + ScalarExpr(e2)); }, py::is_operator()) @@ -60,12 +60,12 @@ void export_ScalarVar(py::module& m) py::implicitly_convertible(); } -ScalarExpr get_item(const VectorVar& v, size_t_type i) +ScalarExpr get_item(const VectorVar& v, Index_type i) { matlab::test_integer(i); i = matlab::input_index(i); - if(i < 0 || i >= static_cast(v.size())) + if(i < 0 || i >= static_cast(v.size())) throw py::index_error("index is out of range"); return ScalarExpr(std::dynamic_pointer_cast>(v[static_cast(i)]->copy())); @@ -79,37 +79,37 @@ void export_VectorVar(py::module& m) exported .def(py::init( - [](size_t_type n) + [](Index_type n) { matlab::test_integer(n); return std::make_unique(n); }), - VECTORVAR_VECTORVAR_SIZET, + VECTORVAR_VECTORVAR_INDEX, "n"_a) .def("size", &VectorVar::size, - SIZET_VECTORVAR_SIZE_CONST); + INDEX_VECTORVAR_SIZE_CONST); if(FOR_MATLAB) - exported.def("__call__", [](const VectorVar& v, size_t_type i) -> ScalarExpr + exported.def("__call__", [](const VectorVar& v, Index_type i) -> ScalarExpr { return get_item(v, i); - }, SHARED_PTR_ANALYTICEXPR_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_SIZET_CONST); + }, SHARED_PTR_ANALYTICEXPR_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); else - exported.def("__getitem__", [](const VectorVar& v, size_t_type i) -> ScalarExpr + exported.def("__getitem__", [](const VectorVar& v, Index_type i) -> ScalarExpr { return get_item(v, i); - }, SHARED_PTR_ANALYTICEXPR_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_SIZET_CONST); + }, SHARED_PTR_ANALYTICEXPR_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); exported - .def("subvector", [](const VectorVar& v, size_t_type i, size_t_type j) -> VectorExpr + .def("subvector", [](const VectorVar& v, Index_type i, Index_type j) -> VectorExpr { matlab::test_integer(i, j); return VectorExpr(std::dynamic_pointer_cast>( v.subvector(matlab::input_index(i),matlab::input_index(j))->copy())); - }, SHARED_PTR_ANALYTICEXPR_VECTOROPVALUE_VECTORVAR_SUBVECTOR_SIZET_SIZET_CONST) + }, SHARED_PTR_ANALYTICEXPR_VECTOROPVALUE_VECTORVAR_SUBVECTOR_INDEX_INDEX_CONST) .def("__pos__", [](const VectorVar& e1) { return VectorExpr(VectorExpr(e1)); }, py::is_operator()) .def("__add__", [](const VectorVar& e1, const VectorVar& e2) { return VectorExpr(VectorExpr(e1) + VectorExpr(e2)); }, py::is_operator()) diff --git a/python/src/core/matrices/codac2_py_Inversion.cpp b/python/src/core/matrices/codac2_py_Inversion.cpp new file mode 100644 index 00000000..d99d732c --- /dev/null +++ b/python/src/core/matrices/codac2_py_Inversion.cpp @@ -0,0 +1,53 @@ +/** + * Inversion of matrices + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Damien Massé + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "codac2_py_doc.h" +#include "codac2_py_Inversion_docs.h" // Generated file from Doxygen + + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_Inversion(py::module& m) +{ + m + + .def("infinite_sum_enclosure", [](const IntervalMatrix& A) { double mrad; return infinite_sum_enclosure(A,mrad); }, + INTERVALMATRIX_INFINITE_SUM_ENCLOSURE_CONST_INTERVALMATRIX_REF_DOUBLE_REF, + "A"_a) + + .def("inverse_correction", [](const IntervalMatrix& A, const IntervalMatrix& B, bool left_inv = true) + { + return left_inv ? inverse_correction(A,B) : inverse_correction(A,B); + }, + INTERVALMATRIX_INVERSE_CORRECTION_CONST_EIGEN_MATRIXBASE_OTHERDERIVED_REF_CONST_EIGEN_MATRIXBASE_OTHERDERIVED__REF, + "A"_a, "B"_a, "left_inv"_a) + + .def("inverse_enclosure", [](const Matrix& A) { return inverse_enclosure(A); }, + INTERVALMATRIX_INVERSE_ENCLOSURE_CONST_EIGEN_MATRIXBASE_OTHERDERIVED_REF, + "A"_a) + + .def("inverse_enclosure", + (IntervalMatrix(*)(const IntervalMatrix&)) + &codac2::inverse_enclosure, + INTERVALMATRIX_INVERSE_ENCLOSURE_CONST_INTERVALMATRIX_REF, + "A"_a) + + ; +} diff --git a/python/src/core/matrices/codac2_py_Matrix.cpp b/python/src/core/matrices/codac2_py_Matrix.cpp index e4664f58..31ec6ce2 100644 --- a/python/src/core/matrices/codac2_py_Matrix.cpp +++ b/python/src/core/matrices/codac2_py_Matrix.cpp @@ -14,9 +14,25 @@ #include #include -#include "codac2_py_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_doc.h" +#include "codac2_py_Matrix_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_matrices_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_docs.h" #include "codac2_py_MatrixBase.h" @@ -27,64 +43,48 @@ using namespace pybind11::literals; py::class_ export_Matrix(py::module& m) { - py::class_ exported_matrix_class(m, "Matrix", MATRIX_MAIN); + py::class_ exported_matrix_class(m, "Matrix", DOC_TO_BE_DEFINED); export_MatrixBase(m, exported_matrix_class); exported_matrix_class .def(py::init( - [](size_t_type r, size_t_type c) + [](Index_type r, Index_type c) { matlab::test_integer(r,c); return std::make_unique(r,c); }), - MATRIX_MATRIX_SIZET_SIZET, + DOC_TO_BE_DEFINED, "r"_a, "c"_a) - .def(py::init( - [](size_t_type r, size_t_type c, double x) - { - matlab::test_integer(r,c); - return std::make_unique(r,c,x); - }), - MATRIX_MATRIX_SIZET_SIZET_DOUBLE, - "r"_a, "c"_a, "x"_a) - .def(py::init(), - MATRIX_MATRIX_CONST_MATRIXBASE_MATRIXDOUBLE_REF, + DOC_TO_BE_DEFINED, "x"_a) .def(py::init(), - MATRIX_MATRIX_CONST_VECTOR_REF, - "x"_a) - - .def(py::init&,double>&>(), - MATRIX_MATRIX_CONST_MATRIXBASEBLOCK_QDOUBLE_REF, + DOC_TO_BE_DEFINED, "x"_a) .def(py::init( // this constructor must be the last one to be declared [](const std::vector& v) { assert_release(!std::empty(v)); - auto iv = std::make_unique(v.size(),v[0].size()); + auto m = std::make_unique(v.size(),v[0].size()); for(size_t i = 0 ; i < v.size() ; i++) { - assert_release(v[i].size() == iv->nb_cols() && "Vector objects of different size"); - iv->row(i) = v[i].transpose(); + assert_release(v[i].size() == m->cols() && "Vector objects of different size"); + m->row(i) = v[i].transpose(); } - return iv; + return m; }), - MATRIX_MATRIX_INITIALIZER_LIST_INITIALIZER_LIST_DOUBLE, + DOC_TO_BE_DEFINED, "v"_a) - .def("transpose", &Matrix::transpose, - MATRIX_MATRIX_TRANSPOSE_CONST) - - .def("diag_matrix", &Matrix::diag_matrix, - MATRIX_MATRIX_DIAG_MATRIX_CONST) - - .def("inverse", &Matrix::inverse, - MATRIX_MATRIX_INVERSE_CONST) + .def("inverse", [](const Matrix& x) + { + return x.inverse().eval(); + }, + DOC_TO_BE_DEFINED) ; diff --git a/python/src/core/matrices/codac2_py_MatrixBase.h b/python/src/core/matrices/codac2_py_MatrixBase.h index 407bfb02..1239e573 100644 --- a/python/src/core/matrices/codac2_py_MatrixBase.h +++ b/python/src/core/matrices/codac2_py_MatrixBase.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include "codac2_py_matlab.h" using namespace std; @@ -29,53 +29,59 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) .def(py::self == py::self) .def(py::self != py::self) + .def("__eq__", [](const S& x1, const Eigen::Matrix& x2) + { + return x1 == x2; + }, + DOC_TO_BE_DEFINED) + .def("__len__", [](const S& x) { return x.size(); }, - SIZET_MATRIXBASE_ST_SIZE_CONST) + DOC_TO_BE_DEFINED) .def("size", [](const S& x) { return x.size(); }, - SIZET_MATRIXBASE_ST_SIZE_CONST) + DOC_TO_BE_DEFINED) - .def("nb_rows", [](const S& x) + .def("rows", [](const S& x) { - return x.nb_rows(); + return x.rows(); }, - SIZET_MATRIXBASE_ST_NB_ROWS_CONST) + DOC_TO_BE_DEFINED) - .def("nb_cols", [](const S& x) + .def("cols", [](const S& x) { - return x.nb_cols(); + return x.cols(); }, - SIZET_MATRIXBASE_ST_NB_COLS_CONST) + DOC_TO_BE_DEFINED) .def("min_coeff", [](const S& x) { return x.min_coeff(); }, - T_MATRIXBASE_ST_MIN_COEFF_CONST) + MATRIXBASE_ADDONS_BASE_SCALAR_MIN_COEFF_CONST) .def("max_coeff", [](const S& x) { return x.max_coeff(); }, - T_MATRIXBASE_ST_MAX_COEFF_CONST) + MATRIXBASE_ADDONS_BASE_SCALAR_MAX_COEFF_CONST) .def("norm", [](const S& x) { return x.norm(); }, - T_MATRIXBASE_ST_NORM_CONST) + DOC_TO_BE_DEFINED) .def("squared_norm", [](const S& x) { return x.squared_norm(); }, - T_MATRIXBASE_ST_SQUARED_NORM_CONST) + MATRIXBASE_ADDONS_BASE_AUTO_SQUARED_NORM_CONST) ; @@ -87,7 +93,7 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) { return x.is_squared(); }, - BOOL_MATRIXBASE_ST_IS_SQUARED_CONST) + MATRIXBASE_ADDONS_BASE_BOOL_IS_SQUARED_CONST) .def("__getitem__", [](const S& x, const py::tuple& ij) -> const T& { @@ -99,7 +105,7 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) return x(matlab::input_index(i), matlab::input_index(j)); }, py::return_value_policy::reference_internal, - CONST_T_REF_MATRIXBASE_ST_OPERATORCALL_SIZET_SIZET_CONST) + MATRIX_ADDONS_BASE_CONST_SCALAR_REF_OPERATORCALL_INDEX_INDEX_CONST) .def("__setitem__", [](S& x, const py::tuple& ij, const T& a) { @@ -111,7 +117,7 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) x(matlab::input_index(i), matlab::input_index(j)) = a; }, - T_REF_MATRIXBASE_ST_OPERATORCALL_SIZET_SIZET) + MATRIX_ADDONS_BASE_SCALAR_REF_OPERATORCALL_INDEX_INDEX) ; } @@ -122,14 +128,14 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) { x.init(a); }, - VOID_MATRIXBASE_ST_INIT_CONST_T_REF, + MATRIX_ADDONS_BASE_AUTO_REF_INIT_CONST_SCALAR_REF, "x"_a) .def("init", [](S& x, const S& a) { x.init(a); }, - VOID_MATRIXBASE_ST_INIT_CONST_S_REF, + MATRIX_ADDONS_BASE_AUTO_REF_INIT_CONST_MATRIX_SCALARROWSATCOMPILETIMECOLSATCOMPILETIME_REF, "x"_a) .def("__repr__", [](const S& x) @@ -138,7 +144,19 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) s << x; return string(s.str()); }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_MATRIXBASE_ST_REF) + DOC_TO_BE_DEFINED) + + .def("transpose", [](const S& x) -> Eigen::Matrix + { + return x.transpose().eval(); + }, + DOC_TO_BE_DEFINED) + + .def("diag_matrix", [](const S& x) + { + return x.diagonal().asDiagonal(); + }, + DOC_TO_BE_DEFINED) ; if constexpr(!VECTOR_INHERITANCE) @@ -148,76 +166,147 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) pyclass - .def("block", [](S& x, size_t_type i, size_t_type j, size_t_type p, size_t_type q) -> MatrixBaseBlock&,T> + .def("block", [](S& x, Index_type i, Index_type j, Index_type p, Index_type q) -> Eigen::Matrix { matlab::test_integer(i,j); matlab::test_integer(p,q); return x.block(matlab::input_index(i),matlab::input_index(j),matlab::input_index(p),matlab::input_index(q)); }, py::keep_alive<0,1>(), - MATRIXBASEBLOCK_EIGENMATRIX_T_REFT_MATRIXBASE_ST_BLOCK_SIZET_SIZET_SIZET_SIZET) + DOC_TO_BE_DEFINED) - .def("col", [](S& x, size_t_type i) -> MatrixBaseBlock&,T> + .def("col", [](S& x, Index_type i) -> Eigen::Matrix { matlab::test_integer(i); - return x.col(matlab::input_index(i)); + return x.col(matlab::input_index(i)).eval(); }, - py::keep_alive<0,1>(), - MATRIXBASEBLOCK_EIGENMATRIX_T_REFT_MATRIXBASE_ST_COL_SIZET) + DOC_TO_BE_DEFINED) - .def("row", [](S& x, size_t_type i) -> MatrixBaseBlock&,T> + .def("row", [](S& x, Index_type i) -> Eigen::Matrix { matlab::test_integer(i); - return x.row(matlab::input_index(i)); + return x.row(matlab::input_index(i)).eval(); + }, + DOC_TO_BE_DEFINED) + + .def("set_block", [](S& x, Index_type i, Index_type j, Index_type p, Index_type q, const S& y) + { + matlab::test_integer(i,j); + matlab::test_integer(p,q); + x.block(matlab::input_index(i),matlab::input_index(j),matlab::input_index(p),matlab::input_index(q)) = y; + }, + py::keep_alive<0,1>(), + DOC_TO_BE_DEFINED) + + .def("set_block", [](S& x, Index_type i, Index_type j, Index_type p, Index_type q, const Eigen::Matrix& y) + { + matlab::test_integer(i,j); + matlab::test_integer(p,q); + x.block(matlab::input_index(i),matlab::input_index(j),matlab::input_index(p),matlab::input_index(q)) = y; + }, + py::keep_alive<0,1>(), + DOC_TO_BE_DEFINED) + + .def("set_block", [](S& x, Index_type i, Index_type j, Index_type p, Index_type q, const Eigen::Matrix& y) + { + matlab::test_integer(i,j); + matlab::test_integer(p,q); + x.block(matlab::input_index(i),matlab::input_index(j),matlab::input_index(p),matlab::input_index(q)) = y; }, py::keep_alive<0,1>(), - MATRIXBASEBLOCK_EIGENMATRIX_T_REFT_MATRIXBASE_ST_ROW_SIZET) + DOC_TO_BE_DEFINED) + + .def("set_col", [](S& x, Index_type i, const Eigen::Matrix& y) + { + matlab::test_integer(i); + x.col(matlab::input_index(i)) = y; + }, + DOC_TO_BE_DEFINED) + + .def("set_col", [](S& x, Index_type i, const Eigen::Matrix& y) + { + assert_release(y.cols() == 1); + matlab::test_integer(i); + x.col(matlab::input_index(i)) = y; + }, + DOC_TO_BE_DEFINED) + + .def("set_row", [](S& x, Index_type i, const Eigen::Matrix& y) + { + matlab::test_integer(i); + x.row(matlab::input_index(i)) = y; + }, + DOC_TO_BE_DEFINED) - .def("__call__", [](S& x, size_t_type i, size_t_type j) -> T& + .def("set_row", [](S& x, Index_type i, const Eigen::Matrix& y) + { + assert_release(y.rows() == 1); + matlab::test_integer(i); + x.row(matlab::input_index(i)) = y; + }, + DOC_TO_BE_DEFINED) + + .def("__call__", [](S& x, Index_type i, Index_type j) -> T& { matlab::test_integer(i,j); return x(matlab::input_index(i),matlab::input_index(j)); }, py::return_value_policy::reference_internal, - T_REF_MATRIXBASE_ST_OPERATORCALL_SIZET_SIZET) + MATRIX_ADDONS_BASE_SCALAR_REF_OPERATORCALL_INDEX_INDEX) - .def("resize", [](S& x, size_t_type nb_rows, size_t_type nb_cols) + .def("resize", [](S& x, Index_type nb_rows, Index_type nb_cols) { matlab::test_integer(nb_rows, nb_cols); x.resize(nb_rows, nb_cols); }, - VOID_MATRIXBASE_ST_RESIZE_SIZET_SIZET, + DOC_TO_BE_DEFINED, "nb_rows"_a, "nb_cols"_a) - .def_static("zeros", [](size_t_type r, size_t_type c) + .def("resize_save_values", [](S& x, Index_type nb_rows, Index_type nb_cols) + { + matlab::test_integer(nb_rows, nb_cols); + x.resize_save_values(nb_rows, nb_cols); + }, + MATRIX_ADDONS_MATRIXBASE_VOID_RESIZE_SAVE_VALUES_INDEX_INDEX, + "nb_rows"_a, "nb_cols"_a) + + .def_static("zero", [](Index_type r, Index_type c) { matlab::test_integer(r,c); - return S::zeros(r,c); + return S::zero(r,c); }, - STATIC_S_MATRIXBASE_ST_ZEROS_SIZET_SIZET, + MATRIX_ADDONS_MATRIXBASE_STATIC_MATRIX_SCALARRC_ZERO_INDEX_INDEX, "r"_a, "c"_a) - .def_static("ones", [](size_t_type r, size_t_type c) + .def_static("ones", [](Index_type r, Index_type c) { matlab::test_integer(r,c); return S::ones(r,c); }, - STATIC_S_MATRIXBASE_ST_ONES_SIZET_SIZET, + MATRIX_ADDONS_MATRIXBASE_STATIC_MATRIX_SCALARRC_ONES_INDEX_INDEX, "r"_a, "c"_a) - .def_static("eye", [](size_t_type r, size_t_type c) + .def_static("constant", [](Index_type r, Index_type c, const T& x) + { + matlab::test_integer(r,c); + return S::constant(r,c,x); + }, + MATRIX_ADDONS_MATRIXBASE_STATIC_MATRIX_SCALARRC_CONSTANT_INDEX_INDEX_CONST_SCALAR_REF, + "r"_a, "c"_a, "x"_a) + + .def_static("eye", [](Index_type r, Index_type c) { matlab::test_integer(r,c); return S::eye(r,c); }, - STATIC_S_MATRIXBASE_ST_EYE_SIZET_SIZET, + MATRIX_ADDONS_MATRIXBASE_STATIC_MATRIX_SCALARRC_EYE_INDEX_INDEX, "r"_a, "c"_a) - .def_static("random", [](size_t_type r, size_t_type c) + .def_static("random", [](Index_type r, Index_type c) { matlab::test_integer(r,c); return S::random(r,c); }, - STATIC_S_MATRIXBASE_ST_RANDOM_SIZET_SIZET, + MATRIX_ADDONS_MATRIXBASE_STATIC_MATRIX_SCALARRC_RANDOM_INDEX_INDEX, "r"_a, "c"_a) ; @@ -225,5 +314,5 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) //S abs(const MatrixBase& x) m.def("abs", [](const S& x) { return abs(x); }, - S_ABS_CONST_MATRIXBASE_ST_REF); + AUTO_ABS_CONST_EIGEN_MATRIXBASE_OTHERDERIVED_REF); } \ No newline at end of file diff --git a/python/src/core/matrices/codac2_py_MatrixBaseBlock.h b/python/src/core/matrices/codac2_py_MatrixBaseBlock.h deleted file mode 100644 index 6e1e98dd..00000000 --- a/python/src/core/matrices/codac2_py_MatrixBaseBlock.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * MatrixBase binding - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include -#include -#include -#include -#include -#include "codac2_py_MatrixBaseBlock_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) - -using namespace std; -using namespace codac2; -namespace py = pybind11; -using namespace pybind11::literals; - -template -py::class_&,T>> export_MatrixBaseBlock(py::module& m, const std::string& name) -{ - py::class_&,T>> exported_mbb_class(m, name.c_str(), MATRIXBASEBLOCK_MAIN); - - exported_mbb_class - - .def("init", [](MatrixBaseBlock&,T>& x, const S& a) - { - return x = a; - }, - VOID_MATRIXBASEBLOCK_QT_INIT_CONST_S__REF, - "x"_a) - - .def("nb_rows", &MatrixBaseBlock&,T>::nb_rows, - SIZET_MATRIXBASEBLOCK_QT_NB_ROWS_CONST) - - .def("nb_cols", &MatrixBaseBlock&,T>::nb_cols, - SIZET_MATRIXBASEBLOCK_QT_NB_COLS_CONST) - - .def("eval", &MatrixBaseBlock&,T>::eval, - AUTO_MATRIXBASEBLOCK_QT_EVAL_CONST) - - .def(py::self == py::self) - .def(py::self != py::self) - - .def("__repr__", [](const MatrixBaseBlock&,T>& x) - { - std::ostringstream s; - s << x; - return string(s.str()); - }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_MATRIXBASEBLOCK_QT_REF) - - ; - - return exported_mbb_class; -} \ No newline at end of file diff --git a/python/src/core/matrices/codac2_py_MatrixBlock.h b/python/src/core/matrices/codac2_py_MatrixBlock.h new file mode 100644 index 00000000..99b51a4f --- /dev/null +++ b/python/src/core/matrices/codac2_py_MatrixBlock.h @@ -0,0 +1,56 @@ +/** + * MatrixBase binding + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include +#include +#include + +#include "codac2_py_doc.h" + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +template +py::class_> export_EigenBlock(py::module& m, const std::string& name) +{ + py::class_> exported_mbb_class(m, name.c_str(), DOC_TO_BE_DEFINED); + + exported_mbb_class + + .def("rows", &Eigen::Block::rows, + DOC_TO_BE_DEFINED) + + .def("cols", &Eigen::Block::cols, + DOC_TO_BE_DEFINED) + + .def("eval", &Eigen::Block::eval, + DOC_TO_BE_DEFINED) + + .def(py::self == py::self) + .def(py::self != py::self) + + .def("__repr__", [](const Eigen::Block& x) + { + std::ostringstream s; + s << x; + return string(s.str()); + }, + DOC_TO_BE_DEFINED) + + ; + + py::implicitly_convertible,S>(); + + return exported_mbb_class; +} \ No newline at end of file diff --git a/python/src/core/matrices/codac2_py_Vector.cpp b/python/src/core/matrices/codac2_py_Vector.cpp index 1eb00908..1377daff 100644 --- a/python/src/core/matrices/codac2_py_Vector.cpp +++ b/python/src/core/matrices/codac2_py_Vector.cpp @@ -14,9 +14,25 @@ #include #include -#include "codac2_py_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_doc.h" +#include "codac2_py_Matrix_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_Matrix_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Matrix_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Base_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_IntervalMatrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalMatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_IntervalVector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_Matrix_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +//#include "codac2_py_MatrixBase_addons_MatrixBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_Vector_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_MatrixBase_addons_VectorBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_matrices_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) +#include "codac2_py_Vector_docs.h" #include "codac2_py_VectorBase.h" @@ -27,48 +43,46 @@ using namespace pybind11::literals; py::class_ export_Vector(py::module& m) { - py::class_ exported_vector_class(m, "Vector", VECTOR_MAIN); + py::class_ exported_vector_class(m, "Vector", DOC_TO_BE_DEFINED); export_MatrixBase(m, exported_vector_class); export_VectorBase(m, exported_vector_class); exported_vector_class .def(py::init( - [](size_t_type n) + [](Index_type n) { matlab::test_integer(n); return std::make_unique(n); }), - VECTOR_VECTOR_SIZET, + DOC_TO_BE_DEFINED, "n"_a) - .def(py::init( - [](size_t_type n, double x) - { - matlab::test_integer(n); - return std::make_unique(n,x); - }), - VECTOR_VECTOR_SIZET_DOUBLE, - "n"_a, "x"_a) - .def(py::init(), "x"_a) - .def(py::init>(), // this constructor must be the last one to be declared - VECTOR_VECTOR_CONST_VECTOR_DOUBLE_REF, - "x"_a) + .def(py::init( // this constructor must be the last one to be declared + [](const std::vector& v_) + { + auto v = std::make_unique(v_.size()); + for(size_t i = 0 ; i < v_.size() ; i++) + (*v)[i] = v_[i]; + return v; + }), + MATRIX_ADDONS_VECTOR_MATRIX_INITIALIZER_LIST_DOUBLE, + "v"_a) .def("min_coeff_index", [](const Vector& x) { return matlab::output_index(x.min_coeff_index()); }, - SIZET_VECTOR_MIN_COEFF_INDEX_CONST) + MATRIXBASE_ADDONS_VECTOR_INDEX_MIN_COEFF_INDEX_CONST) .def("max_coeff_index", [](const Vector& x) { return matlab::output_index(x.max_coeff_index()); }, - SIZET_VECTOR_MAX_COEFF_INDEX_CONST) + MATRIXBASE_ADDONS_VECTOR_INDEX_MAX_COEFF_INDEX_CONST) .def("__repr__", [](const Vector& x) { @@ -76,7 +90,7 @@ py::class_ export_Vector(py::module& m) s << x; return string(s.str()); }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_VECTOR_REF) + DOC_TO_BE_DEFINED) ; diff --git a/python/src/core/matrices/codac2_py_VectorBase.h b/python/src/core/matrices/codac2_py_VectorBase.h index bfe85c57..bcebe0c5 100644 --- a/python/src/core/matrices/codac2_py_VectorBase.h +++ b/python/src/core/matrices/codac2_py_VectorBase.h @@ -22,7 +22,7 @@ namespace py = pybind11; using namespace pybind11::literals; template -void export_VectorBase(py::module& m, py::class_& pyclass) +void export_VectorBase([[maybe_unused]] py::module& m, py::class_& pyclass) { //export_MatrixBase(m, pyclass); // ^ We do not "inherit" from export_MatrixBase here, in order to @@ -31,72 +31,90 @@ void export_VectorBase(py::module& m, py::class_& pyclass) pyclass - .def("__getitem__", [](const S& x, size_t_type index) -> const T& + .def(py::init( + [](const Eigen::Matrix& x) + { + return std::make_unique(x); + }), + DOC_TO_BE_DEFINED, + "x"_a) + + .def("__getitem__", [](const S& x, Index_type index) -> const T& { matlab::test_integer(index); return x[matlab::input_index(index)]; }, py::return_value_policy::reference_internal, - CONST_T_REF_VECTORBASE_SMT_OPERATORCOMPO_SIZET_CONST) + MATRIX_ADDONS_VECTORBASE_CONST_SCALAR_REF_OPERATORCOMPO_INDEX_CONST) - .def("__setitem__", [](S& x, size_t_type index, const T& a) + .def("__setitem__", [](S& x, Index_type index, const T& a) { matlab::test_integer(index); x[matlab::input_index(index)] = a; }, - T_REF_VECTORBASE_SMT_OPERATORCOMPO_SIZET) + MATRIX_ADDONS_VECTORBASE_SCALAR_REF_OPERATORCOMPO_INDEX) - .def("subvector", [](const S& x, size_t_type start_id, size_t_type end_id) + .def("subvector", [](const S& x, Index_type start_id, Index_type end_id) -> S { matlab::test_integer(start_id, end_id); return x.subvector(matlab::input_index(start_id), matlab::input_index(end_id)); }, - S_VECTORBASE_SMT_SUBVECTOR_SIZET_SIZET_CONST, + MATRIXBASE_ADDONS_VECTORBASE_AUTO_SUBVECTOR_INDEX_INDEX_CONST, "start_id"_a, "end_id"_a) - .def("resize", [](S& x, size_t_type n) + .def("resize", [](S& x, Index_type n) { matlab::test_integer(n); x.resize(n); }, - VOID_VECTORBASE_SMT_RESIZE_SIZET, + DOC_TO_BE_DEFINED, + "n"_a) + + .def("resize_save_values", [](S& x, Index_type n) + { + matlab::test_integer(n); + x.resize_save_values(n); + }, + MATRIX_ADDONS_VECTORBASE_VOID_RESIZE_SAVE_VALUES_INDEX, "n"_a) - .def("put", [](S& x, size_t_type start_id, const S& x1) + .def("put", [](S& x, Index_type start_id, const S& x1) { matlab::test_integer(start_id); x.put(matlab::input_index(start_id), x1); }, - VOID_VECTORBASE_SMT_PUT_SIZET_CONST_S_REF, + MATRIX_ADDONS_VECTORBASE_VOID_PUT_INDEX_CONST_MATRIXBASE_OTHERDERIVED_REF, "start_id"_a, "x"_a) - - .def("transpose", &S::transpose, - M_VECTORBASE_SMT_TRANSPOSE_CONST) - - .def("diag_matrix", &S::diag_matrix, - M_VECTORBASE_SMT_DIAG_MATRIX_CONST) - .def_static("zeros", [](size_t_type n) + .def_static("zero", [](Index_type n) { matlab::test_integer(n); - return S::zeros(n); + return S::zero(n); }, - STATIC_S_VECTORBASE_SMT_ZEROS_SIZET, + MATRIX_ADDONS_VECTORBASE_STATIC_MATRIX_SCALARRC_ZERO_INDEX, "n"_a) - .def_static("ones", [](size_t_type n) + .def_static("ones", [](Index_type n) { matlab::test_integer(n); return S::ones(n); }, - STATIC_S_VECTORBASE_SMT_ONES_SIZET, + MATRIX_ADDONS_VECTORBASE_STATIC_MATRIX_SCALARRC_ONES_INDEX, "n"_a) - .def_static("random", [](size_t_type n) + .def_static("constant", [](Index_type n, const T& x) + { + matlab::test_integer(n); + return S::constant(n,x); + }, + MATRIX_ADDONS_VECTORBASE_STATIC_MATRIX_SCALARRC_CONSTANT_INDEX_CONST_SCALAR_REF, + "n"_a, "x"_a) + + .def_static("random", [](Index_type n) { matlab::test_integer(n); return S::random(n); }, - STATIC_S_VECTORBASE_SMT_RANDOM_SIZET, + MATRIX_ADDONS_VECTORBASE_STATIC_MATRIX_SCALARRC_RANDOM_INDEX, "n"_a) .def("__repr__", [](const S& x) @@ -105,12 +123,11 @@ void export_VectorBase(py::module& m, py::class_& pyclass) s << x; return string(s.str()); }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_VECTORBASE_SMT_REF) + DOC_TO_BE_DEFINED) .def("__iter__", [](const S &x) { - auto x_ = x._e.reshaped(); - return py::make_iterator(x_.begin(), x_.end()); + return py::make_iterator(x.begin(), x.end()); }, py::keep_alive<0, 1>() /* keep object alive while iterator exists */) ; diff --git a/python/src/core/matrices/codac2_py_arithmetic_add.cpp b/python/src/core/matrices/codac2_py_arithmetic_add.cpp index 5c5b8fbd..4a92fe8d 100644 --- a/python/src/core/matrices/codac2_py_arithmetic_add.cpp +++ b/python/src/core/matrices/codac2_py_arithmetic_add.cpp @@ -11,83 +11,86 @@ #include #include #include -#include +#include +#include +#include +#include using namespace std; using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -using B = MatrixBaseBlock&,double>; -using IB = MatrixBaseBlock&,Interval>; +using B = Eigen::Block; +using IB = Eigen::Block; -void export_arithmetic_add(py::module& m, +void export_arithmetic_add( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, py::class_& py_B, py::class_& py_IB) { // ====== First operand: vector - py_V.def(+py::self); + py_V.def("__add__", [](const Vector& x1) -> Vector { return x1; }, py::is_operator()); - //inline Vector operator+(const Vector& x1, const Vector& x2) - py_V.def("__add__", [](const Vector& x1, const Vector& x2) { return x1+x2; }, py::is_operator()); + //inline Vector operator-(const Vector& x1, const Vector& x2) + py_V.def("__add__", [](const Vector& x1, const Vector& x2) -> Vector { return x1+x2; }, py::is_operator()); - //inline IntervalVector operator+(const Vector& x1, const IntervalVector& x2) - py_V.def("__add__", [](const Vector& x1, const IntervalVector& x2) { return x1+x2; }, py::is_operator()); + //inline IntervalVector operator-(const Vector& x1, const IntervalVector& x2) + py_V.def("__add__", [](const Vector& x1, const IntervalVector& x2) -> IntervalVector { return x1.template cast()+x2; }, py::is_operator()); py_V.def("__iadd__", [](Vector& x1, const Vector& x2) { return x1+=x2; }, py::is_operator()); // ====== First operand: matrix - py_M.def(+py::self); + py_M.def("__add__", [](const Matrix& x1) -> Matrix { return x1; }, py::is_operator()); - //Matrix operator+(const M& x1, const M_& x2) - py_M.def("__add__", [](const Matrix& x1, const Matrix& x2) { return x1+x2; }, py::is_operator()); - py_M.def("__add__", [](const Matrix& x1, const B& x2) { return x1+x2; }, py::is_operator()); - py_B.def("__add__", [](const B& x1, const Matrix& x2) { return x1+x2; }, py::is_operator()); - py_B.def("__add__", [](const B& x1, const B& x2) { return x1+x2; }, py::is_operator()); + //Matrix operator-(const M& x1, const M_& x2) + py_M.def("__add__", [](const Matrix& x1, const Matrix& x2) -> Matrix { return x1+x2; }, py::is_operator()); + py_M.def("__add__", [](const Matrix& x1, const B& x2) -> Matrix { return x1+x2; }, py::is_operator()); + py_B.def("__add__", [](const B& x1, const Matrix& x2) -> Matrix { return x1+x2; }, py::is_operator()); + py_B.def("__add__", [](const B& x1, const B& x2) -> Matrix { return x1+x2; }, py::is_operator()); - //IntervalMatrix operator+(const M& x1, const IM& x2) - py_M.def("__add__", [](const Matrix& x1, const IntervalMatrix& x2) { return x1+x2; }, py::is_operator()); - py_M.def("__add__", [](const Matrix& x1, const IB& x2) { return x1+x2; }, py::is_operator()); - py_B.def("__add__", [](const B& x1, const IntervalMatrix& x2) { return x1+x2; }, py::is_operator()); - py_B.def("__add__", [](const B& x1, const IB& x2) { return x1+x2; }, py::is_operator()); + //IntervalMatrix operator-(const M& x1, const IM& x2) + py_M.def("__add__", [](const Matrix& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1.template cast()+x2; }, py::is_operator()); + py_M.def("__add__", [](const Matrix& x1, const IB& x2) -> IntervalMatrix { return x1.template cast()+x2; }, py::is_operator()); + py_B.def("__add__", [](const B& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1.template cast()+x2; }, py::is_operator()); + py_B.def("__add__", [](const B& x1, const IB& x2) -> IntervalMatrix { return x1.template cast()+x2; }, py::is_operator()); - py_V.def("__iadd__", [](Matrix& x1, const Matrix& x2) { return x1+=x2; }, py::is_operator()); - py_V.def("__iadd__", [](Matrix& x1, const B& x2) { return x1+=x2; }, py::is_operator()); + py_M.def("__iadd__", [](Matrix& x1, const Matrix& x2) { return x1+=x2; }, py::is_operator()); + py_M.def("__iadd__", [](Matrix& x1, const B& x2) { return x1+=x2; }, py::is_operator()); // ====== First operand: interval vector - py_IV.def(+py::self); + py_IV.def("__add__", [](const IntervalVector& x1) -> IntervalVector { return x1; }, py::is_operator()); - //inline IntervalVector operator+(const IntervalVector& x1, const Vector& x2) - py_IV.def("__add__", [](const IntervalVector& x1, const Vector& x2) { return x1+x2; }, py::is_operator()); + //inline IntervalVector operator-(const IntervalVector& x1, const Vector& x2) + py_IV.def("__add__", [](const IntervalVector& x1, const Vector& x2) -> IntervalVector { return x1+x2.template cast(); }, py::is_operator()); - //inline IntervalVector operator+(const IntervalVector& x1, const IntervalVector& x2) - py_IV.def("__add__", [](const IntervalVector& x1, const IntervalVector& x2) { return x1+x2; }, py::is_operator()); + //inline IntervalVector operator-(const IntervalVector& x1, const IntervalVector& x2) + py_IV.def("__add__", [](const IntervalVector& x1, const IntervalVector& x2) -> IntervalVector { return x1+x2; }, py::is_operator()); - py_V.def("__iadd__", [](IntervalVector& x1, const Vector& x2) { return x1+=x2; }, py::is_operator()); - py_V.def("__iadd__", [](IntervalVector& x1, const IntervalVector& x2) { return x1+=x2; }, py::is_operator()); + py_IV.def("__iadd__", [](IntervalVector& x1, const Vector& x2) { return x1+=x2.template cast(); }, py::is_operator()); + py_IV.def("__iadd__", [](IntervalVector& x1, const IntervalVector& x2) { return x1+=x2; }, py::is_operator()); // ====== First operand: interval matrix - py_IM.def(+py::self); + py_IM.def("__add__", [](const IntervalMatrix& x1) -> IntervalMatrix { return x1; }, py::is_operator()); - //IntervalMatrix operator+(const IM& x1, const M& x2) - py_IM.def("__add__", [](const IntervalMatrix& x1, const Matrix& x2) { return x1+x2; }, py::is_operator()); - py_IM.def("__add__", [](const IntervalMatrix& x1, const B& x2) { return x1+x2; }, py::is_operator()); - py_IB.def("__add__", [](const IB& x1, const Matrix& x2) { return x1+x2; }, py::is_operator()); - py_IB.def("__add__", [](const IB& x1, const B& x2) { return x1+x2; }, py::is_operator()); + //IntervalMatrix operator-(const IM& x1, const M& x2) + py_IM.def("__add__", [](const IntervalMatrix& x1, const Matrix& x2) -> IntervalMatrix { return x1+x2.template cast(); }, py::is_operator()); + py_IM.def("__add__", [](const IntervalMatrix& x1, const B& x2) -> IntervalMatrix { return x1+x2.template cast(); }, py::is_operator()); + py_IB.def("__add__", [](const IB& x1, const Matrix& x2) -> IntervalMatrix { return x1+x2.template cast(); }, py::is_operator()); + py_IB.def("__add__", [](const IB& x1, const B& x2) -> IntervalMatrix { return x1+x2.template cast(); }, py::is_operator()); - //IntervalMatrix operator+(const IM& x1, const IM_& x2) - py_IM.def("__add__", [](const IntervalMatrix& x1, const IntervalMatrix& x2) { return x1+x2; }, py::is_operator()); - py_IM.def("__add__", [](const IntervalMatrix& x1, const IB& x2) { return x1+x2; }, py::is_operator()); - py_IB.def("__add__", [](const IB& x1, const IntervalMatrix& x2) { return x1+x2; }, py::is_operator()); - py_IB.def("__add__", [](const IB& x1, const IB& x2) { return x1+x2; }, py::is_operator()); + //IntervalMatrix operator-(const IM& x1, const IM_& x2) + py_IM.def("__add__", [](const IntervalMatrix& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1+x2; }, py::is_operator()); + py_IM.def("__add__", [](const IntervalMatrix& x1, const IB& x2) -> IntervalMatrix { return x1+x2; }, py::is_operator()); + py_IB.def("__add__", [](const IB& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1+x2; }, py::is_operator()); + py_IB.def("__add__", [](const IB& x1, const IB& x2) -> IntervalMatrix { return x1+x2; }, py::is_operator()); - py_IM.def("__iadd__", [](IntervalMatrix& x1, const Matrix& x2) { return x1+=x2; }, py::is_operator()); - py_IM.def("__iadd__", [](IntervalMatrix& x1, const B& x2) { return x1+=x2; }, py::is_operator()); + py_IM.def("__iadd__", [](IntervalMatrix& x1, const Matrix& x2) { return x1+=x2.template cast(); }, py::is_operator()); + py_IM.def("__iadd__", [](IntervalMatrix& x1, const B& x2) { return x1+=x2.template cast(); }, py::is_operator()); py_IM.def("__iadd__", [](IntervalMatrix& x1, const IntervalMatrix& x2) { return x1+=x2; }, py::is_operator()); py_IM.def("__iadd__", [](IntervalMatrix& x1, const IB& x2) { return x1+=x2; }, py::is_operator()); diff --git a/python/src/core/matrices/codac2_py_arithmetic_div.cpp b/python/src/core/matrices/codac2_py_arithmetic_div.cpp index eb318df7..5aab18d8 100644 --- a/python/src/core/matrices/codac2_py_arithmetic_div.cpp +++ b/python/src/core/matrices/codac2_py_arithmetic_div.cpp @@ -11,17 +11,20 @@ #include #include #include -#include +#include +#include +#include +#include using namespace std; using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -using B = MatrixBaseBlock&,double>; -using IB = MatrixBaseBlock&,Interval>; +using B = Eigen::Block; +using IB = Eigen::Block; -void export_arithmetic_div(py::module& m, +void export_arithmetic_div( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, py::class_& py_B, py::class_& py_IB) @@ -29,32 +32,32 @@ void export_arithmetic_div(py::module& m, // ====== First operand: vector //inline Vector operator/(const Vector& x1, double x2) - py_V.def("__truediv__", [](const Vector& x1, double x2) { return x1/x2; }, py::is_operator()); + py_V.def("__truediv__", [](const Vector& x1, double x2) -> Vector { return x1/x2; }, py::is_operator()); //inline IntervalVector operator/(const Vector& x1, const Interval& x2) - py_V.def("__truediv__", [](const Vector& x1, const Interval& x2) { return x1/x2; }, py::is_operator()); + py_V.def("__truediv__", [](const Vector& x1, const Interval& x2) -> IntervalVector { return x1.template cast()/x2; }, py::is_operator()); py_V.def("__itruediv__", [](Vector& x1, double x2) { return x1/=x2; }, py::is_operator()); // ====== First operand: matrix //Matrix operator/(const M& x1, double x2) - py_M.def("__truediv__", [](const Matrix& x1, double x2) { return x1/x2; }, py::is_operator()); - py_B.def("__truediv__", [](const B& x1, double x2) { return x1/x2; }, py::is_operator()); + py_M.def("__truediv__", [](const Matrix& x1, double x2) -> Matrix { return x1/x2; }, py::is_operator()); + py_B.def("__truediv__", [](const Eigen::Block& x1, double x2) -> Matrix { return x1/x2; }, py::is_operator()); //IntervalMatrix operator/(const M& x1, const Interval& x2) - py_M.def("__truediv__", [](const Matrix& x1, const Interval& x2) { return x1/x2; }, py::is_operator()); - py_B.def("__truediv__", [](const B& x1, const Interval& x2) { return x1/x2; }, py::is_operator()); + py_M.def("__truediv__", [](const Matrix& x1, const Interval& x2) -> IntervalMatrix { return x1.template cast()/x2; }, py::is_operator()); + py_B.def("__truediv__", [](const B& x1, const Interval& x2) -> IntervalMatrix { return x1.template cast()/x2; }, py::is_operator()); py_M.def("__itruediv__", [](Matrix& x1, double x2) { return x1/=x2; }, py::is_operator()); // ====== First operand: interval vector //inline IntervalVector operator/(const IntervalVector& x1, double x2) - py_IV.def("__truediv__", [](const IntervalVector& x1, double x2) { return x1/x2; }, py::is_operator()); + py_IV.def("__truediv__", [](const IntervalVector& x1, double x2) -> IntervalVector { return x1/x2; }, py::is_operator()); //inline IntervalVector operator/(const IntervalVector& x1, const Interval& x2) - py_IV.def("__truediv__", [](const IntervalVector& x1, const Interval& x2) { return x1/x2; }, py::is_operator()); + py_IV.def("__truediv__", [](const IntervalVector& x1, const Interval& x2) -> IntervalVector { return x1/x2; }, py::is_operator()); py_IV.def("__itruediv__", [](IntervalVector& x1, double x2) { return x1/=x2; }, py::is_operator()); py_IV.def("__itruediv__", [](IntervalVector& x1, const Interval& x2) { return x1/=x2; }, py::is_operator()); @@ -62,12 +65,12 @@ void export_arithmetic_div(py::module& m, // ====== First operand: interval matrix //IntervalMatrix operator/(const IM& x1, double x2) - py_IM.def("__truediv__", [](const IntervalMatrix& x1, double x2) { return x1/x2; }, py::is_operator()); - py_IB.def("__truediv__", [](const IB& x1, double x2) { return x1/x2; }, py::is_operator()); + py_IM.def("__truediv__", [](const IntervalMatrix& x1, double x2) -> IntervalMatrix { return x1/x2; }, py::is_operator()); + py_IB.def("__truediv__", [](const IB& x1, double x2) -> IntervalMatrix { return x1/x2; }, py::is_operator()); //IntervalMatrix operator/(const IM& x1, const Interval& x2) - py_IM.def("__truediv__", [](const IntervalMatrix& x1, const Interval& x2) { return x1/x2; }, py::is_operator()); - py_IB.def("__truediv__", [](const IB& x1, const Interval& x2) { return x1/x2; }, py::is_operator()); + py_IM.def("__truediv__", [](const IntervalMatrix& x1, const Interval& x2) -> IntervalMatrix { return x1/x2; }, py::is_operator()); + py_IB.def("__truediv__", [](const IB& x1, const Interval& x2) -> IntervalMatrix { return x1/x2; }, py::is_operator()); py_IM.def("__itruediv__", [](IntervalMatrix& x1, double x2) { return x1/=x2; }, py::is_operator()); py_IM.def("__itruediv__", [](IntervalMatrix& x1, const Interval& x2) { return x1/=x2; }, py::is_operator()); diff --git a/python/src/core/matrices/codac2_py_arithmetic_mul.cpp b/python/src/core/matrices/codac2_py_arithmetic_mul.cpp index 94713df0..12f56a67 100644 --- a/python/src/core/matrices/codac2_py_arithmetic_mul.cpp +++ b/python/src/core/matrices/codac2_py_arithmetic_mul.cpp @@ -11,17 +11,20 @@ #include #include #include -#include +#include +#include +#include +#include using namespace std; using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -using B = MatrixBaseBlock&,double>; -using IB = MatrixBaseBlock&,Interval>; +using B = Eigen::Block; +using IB = Eigen::Block; -void export_arithmetic_mul(py::module& m, +void export_arithmetic_mul( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, py::class_& py_B, py::class_& py_IB) @@ -29,74 +32,74 @@ void export_arithmetic_mul(py::module& m, // ====== First operand: double //inline Vector operator*(double x1, const Vector& x2) - py_V.def("__rmul__", [](const Vector& x2, double x1) { return x1*x2; }, py::is_operator()); + py_V.def("__rmul__", [](const Vector& x2, double x1) -> Vector { return x1*x2; }, py::is_operator()); //Matrix operator*(double x1, const M& x2) - py_M.def("__rmul__", [](const Matrix& x2, double x1) { return x1*x2; }, py::is_operator()); - py_B.def("__rmul__", [](const B& x2, double x1) { return x1*x2; }, py::is_operator()); + py_M.def("__rmul__", [](const Matrix& x2, double x1) -> Matrix { return x1*x2; }, py::is_operator()); + py_B.def("__rmul__", [](const B& x2, double x1) -> Matrix { return x1*x2; }, py::is_operator()); //inline IntervalVector operator*(double x1, const IntervalVector& x2) - py_IV.def("__rmul__", [](const IntervalVector& x2, double x1) { return x1*x2; }, py::is_operator()); + py_IV.def("__rmul__", [](const IntervalVector& x2, double x1) -> IntervalVector { return x1*x2; }, py::is_operator()); //IntervalMatrix operator*(double x1, const IM& x2) - py_IM.def("__rmul__", [](const IntervalMatrix& x2, double x1) { return x1*x2; }, py::is_operator()); - py_IB.def("__rmul__", [](const IB& x2, double x1) { return x1*x2; }, py::is_operator()); + py_IM.def("__rmul__", [](const IntervalMatrix& x2, double x1) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_IB.def("__rmul__", [](const IB& x2, double x1) -> IntervalMatrix { return x1*x2; }, py::is_operator()); // ====== First operand: interval //inline IntervalVector operator*(const Interval& x1, const Vector& x2) - py_V.def("__rmul__", [](const Vector& x2, const Interval& x1) { return x1*x2; }, py::is_operator()); + py_V.def("__rmul__", [](const Vector& x2, const Interval& x1) -> IntervalVector { return x1*x2; }, py::is_operator()); //IntervalMatrix operator*(const Interval& x1, const M& x2) - py_M.def("__rmul__", [](const Matrix& x2, const Interval& x1) { return x1*x2; }, py::is_operator()); - py_B.def("__rmul__", [](const B& x2, const Interval& x1) { return x1*x2; }, py::is_operator()); + py_M.def("__rmul__", [](const Matrix& x2, const Interval& x1) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_B.def("__rmul__", [](const B& x2, const Interval& x1) -> IntervalMatrix { return x1*x2; }, py::is_operator()); //inline IntervalVector operator*(const Interval& x1, const IntervalVector& x2) - py_IV.def("__rmul__", [](const IntervalVector& x2, const Interval& x1) { return x1*x2; }, py::is_operator()); + py_IV.def("__rmul__", [](const IntervalVector& x2, const Interval& x1) -> IntervalVector { return x1*x2; }, py::is_operator()); //IntervalMatrix operator*(const Interval& x1, const IM& x2) - py_IM.def("__rmul__", [](const IntervalMatrix& x2, const Interval& x1) { return x1*x2; }, py::is_operator()); - py_IB.def("__rmul__", [](const IB& x2, const Interval& x1) { return x1*x2; }, py::is_operator()); + py_IM.def("__rmul__", [](const IntervalMatrix& x2, const Interval& x1) -> IntervalMatrix{ return x1*x2; }, py::is_operator()); + py_IB.def("__rmul__", [](const IB& x2, const Interval& x1) -> IntervalMatrix { return x1*x2; }, py::is_operator()); // ====== First operand: vector //inline Vector operator*(const Vector& x1, double x2) - py_V.def("__mul__", [](const Vector& x1, double x2) { return x1*x2; }, py::is_operator()); + py_V.def("__mul__", [](const Vector& x1, double x2) -> Vector { return x1*x2; }, py::is_operator()); //inline IntervalVector operator*(const Vector& x1, const Interval& x2) - py_V.def("__mul__", [](const Vector& x1, const Interval& x2) { return x1*x2; }, py::is_operator()); + py_V.def("__mul__", [](const Vector& x1, const Interval& x2) -> IntervalVector { return x1*x2; }, py::is_operator()); py_V.def("__imul__", [](Vector& x1, double x2) { return x1*=x2; }, py::is_operator()); // ====== First operand: matrix //Interval operator*(const M& x1, double x2) - py_M.def("__mul__", [](const Matrix& x1, double x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, double x2) { return x1*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, double x2) -> Matrix { return x1*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, double x2) -> Matrix { return x1*x2; }, py::is_operator()); //IntervalMatrix operator*(const M& x1, const Interval& x2) - py_M.def("__mul__", [](const Matrix& x1, const Interval& x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, const Interval& x2) { return x1*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, const Interval& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, const Interval& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); //Vector operator*(const M& x1, const Vector& x2) - py_M.def("__mul__", [](const Matrix& x1, const Vector& x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, const Vector& x2) { return x1*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, const Vector& x2) -> Vector { return x1*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, const Vector& x2) -> Vector { return x1*x2; }, py::is_operator()); //Matrix operator*(const M& x1, const M_& x2) - py_M.def("__mul__", [](const Matrix& x1, const Matrix& x2) { return x1*x2; }, py::is_operator()); - py_M.def("__mul__", [](const Matrix& x1, const B& x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, const Matrix& x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, const B& x2) { return x1*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, const Matrix& x2) -> Matrix { return x1*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, const B& x2) -> Matrix { return x1*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, const Matrix& x2) -> Matrix { return x1*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, const B& x2) -> Matrix { return x1*x2; }, py::is_operator()); //IntervalVector operator*(const M& x1, const IntervalVector& x2) - py_M.def("__mul__", [](const Matrix& x1, const IntervalVector& x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, const IntervalVector& x2) { return x1*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, const IntervalVector& x2) -> IntervalVector { return x1*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, const IntervalVector& x2) -> IntervalVector { return x1*x2; }, py::is_operator()); //IntervalMatrix operator*(const M& x1, const IM& x2) - py_M.def("__mul__", [](const Matrix& x1, const IntervalMatrix& x2) { return x1*x2; }, py::is_operator()); - py_M.def("__mul__", [](const Matrix& x1, const IB& x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, const IntervalMatrix& x2) { return x1*x2; }, py::is_operator()); - py_B.def("__mul__", [](const B& x1, const IB& x2) { return x1*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1.template cast()*x2; }, py::is_operator()); + py_M.def("__mul__", [](const Matrix& x1, const IB& x2) -> IntervalMatrix { return x1.template cast()*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1.template cast()*x2; }, py::is_operator()); + py_B.def("__mul__", [](const B& x1, const IB& x2) -> IntervalMatrix { return x1.template cast()*x2; }, py::is_operator()); py_M.def("__imul__", [](Matrix& x1, double x2) { return x1*=x2; }, py::is_operator()); py_M.def("__imul__", [](Matrix& x1, const Matrix& x2) { return x1*=x2; }, py::is_operator()); @@ -105,10 +108,10 @@ void export_arithmetic_mul(py::module& m, // ====== First operand: interval vector //inline IntervalVector operator*(const IntervalVector& x1, double x2) - py_IV.def("__mul__", [](const IntervalVector& x1, double x2) { return x1*x2; }, py::is_operator()); + py_IV.def("__mul__", [](const IntervalVector& x1, double x2) -> IntervalVector { return x1*x2; }, py::is_operator()); //inline IntervalVector operator*(const IntervalVector& x1, const Interval& x2) - py_IV.def("__mul__", [](const IntervalVector& x1, const Interval& x2) { return x1*x2; }, py::is_operator()); + py_IV.def("__mul__", [](const IntervalVector& x1, const Interval& x2) -> IntervalVector { return x1*x2; }, py::is_operator()); py_IV.def("__imul__", [](IntervalVector& x1, double x2) { return x1*=x2; }, py::is_operator()); py_IV.def("__imul__", [](IntervalVector& x1, const Interval& x2) { return x1*=x2; }, py::is_operator()); @@ -116,36 +119,36 @@ void export_arithmetic_mul(py::module& m, // ====== First operand: interval matrix //IntervalMatrix operator*(const IM& x1, double x2) - py_IM.def("__mul__", [](const IntervalMatrix& x1, double x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, double x2) { return x1*x2; }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, double x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, double x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); //IntervalMatrix operator*(const IM& x1, const Interval& x2) - py_IM.def("__mul__", [](const IntervalMatrix& x1, const Interval& x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, const Interval& x2) { return x1*x2; }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, const Interval& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, const Interval& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); //IntervalVector operator*(const IM& x1, const Vector& x2) - py_IM.def("__mul__", [](const IntervalMatrix& x1, const Vector& x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, const Vector& x2) { return x1*x2; }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, const Vector& x2) -> IntervalVector { return x1*x2.template cast(); }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, const Vector& x2) -> IntervalVector { return x1*x2.template cast(); }, py::is_operator()); //IntervalMatrix operator*(const IM& x1, const M& x2) - py_IM.def("__mul__", [](const IntervalMatrix& x1, const Matrix& x2) { return x1*x2; }, py::is_operator()); - py_IM.def("__mul__", [](const IntervalMatrix& x1, const B& x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, const Matrix& x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, const B& x2) { return x1*x2; }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, const Matrix& x2) -> IntervalMatrix { return x1*x2.template cast(); }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, const B& x2) -> IntervalMatrix { return x1*x2.template cast(); }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, const Matrix& x2) -> IntervalMatrix { return x1*x2.template cast(); }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, const B& x2) -> IntervalMatrix { return x1*x2.template cast(); }, py::is_operator()); //IntervalVector operator*(const IM& x1, const IntervalVector& x2) - py_IM.def("__mul__", [](const IntervalMatrix& x1, const IntervalVector& x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, const IntervalVector& x2) { return x1*x2; }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, const IntervalVector& x2) -> IntervalVector { return x1*x2; }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, const IntervalVector& x2) -> IntervalVector { return x1*x2; }, py::is_operator()); //IntervalMatrix operator*(const IM& x1, const IM_& x2) - py_IM.def("__mul__", [](const IntervalMatrix& x1, const IntervalMatrix& x2) { return x1*x2; }, py::is_operator()); - py_IM.def("__mul__", [](const IntervalMatrix& x1, const IB& x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, const IntervalMatrix& x2) { return x1*x2; }, py::is_operator()); - py_IB.def("__mul__", [](const IB& x1, const IB& x2) { return x1*x2; }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_IM.def("__mul__", [](const IntervalMatrix& x1, const IB& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); + py_IB.def("__mul__", [](const IB& x1, const IB& x2) -> IntervalMatrix { return x1*x2; }, py::is_operator()); py_IM.def("__imul__", [](IntervalMatrix& x1, double x2) { return x1*=x2; }, py::is_operator()); - py_IM.def("__imul__", [](IntervalMatrix& x1, const Matrix& x2) { return x1*=x2; }, py::is_operator()); - py_IM.def("__imul__", [](IntervalMatrix& x1, const B& x2) { return x1*=x2; }, py::is_operator()); + py_IM.def("__imul__", [](IntervalMatrix& x1, const Matrix& x2) { return x1*=x2.template cast(); }, py::is_operator()); + py_IM.def("__imul__", [](IntervalMatrix& x1, const B& x2) { return x1*=x2.template cast(); }, py::is_operator()); py_IM.def("__imul__", [](IntervalMatrix& x1, const Interval& x2) { return x1*=x2; }, py::is_operator()); py_IM.def("__imul__", [](IntervalMatrix& x1, const IntervalMatrix& x2) { return x1*=x2; }, py::is_operator()); py_IM.def("__imul__", [](IntervalMatrix& x1, const IB& x2) { return x1*=x2; }, py::is_operator()); diff --git a/python/src/core/matrices/codac2_py_arithmetic_sub.cpp b/python/src/core/matrices/codac2_py_arithmetic_sub.cpp index 715fb06e..bc1fe3b6 100644 --- a/python/src/core/matrices/codac2_py_arithmetic_sub.cpp +++ b/python/src/core/matrices/codac2_py_arithmetic_sub.cpp @@ -11,83 +11,86 @@ #include #include #include -#include +#include +#include +#include +#include using namespace std; using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -using B = MatrixBaseBlock&,double>; -using IB = MatrixBaseBlock&,Interval>; +using B = Eigen::Block; +using IB = Eigen::Block; -void export_arithmetic_sub(py::module& m, +void export_arithmetic_sub( py::class_& py_V, py::class_& py_IV, py::class_& py_M, py::class_& py_IM, py::class_& py_B, py::class_& py_IB) { // ====== First operand: vector - py_V.def(-py::self); + py_V.def("__neg__", [](const Vector& x1) -> Vector { return -x1; }, py::is_operator()); //inline Vector operator-(const Vector& x1, const Vector& x2) - py_V.def("__sub__", [](const Vector& x1, const Vector& x2) { return x1-x2; }, py::is_operator()); + py_V.def("__sub__", [](const Vector& x1, const Vector& x2) -> Vector { return x1-x2; }, py::is_operator()); //inline IntervalVector operator-(const Vector& x1, const IntervalVector& x2) - py_V.def("__sub__", [](const Vector& x1, const IntervalVector& x2) { return x1-x2; }, py::is_operator()); + py_V.def("__sub__", [](const Vector& x1, const IntervalVector& x2) -> IntervalVector { return x1.template cast()-x2; }, py::is_operator()); py_V.def("__isub__", [](Vector& x1, const Vector& x2) { return x1-=x2; }, py::is_operator()); // ====== First operand: matrix - py_M.def(-py::self); + py_M.def("__neg__", [](const Matrix& x1) -> Matrix { return -x1; }, py::is_operator()); //Matrix operator-(const M& x1, const M_& x2) - py_M.def("__sub__", [](const Matrix& x1, const Matrix& x2) { return x1-x2; }, py::is_operator()); - py_M.def("__sub__", [](const Matrix& x1, const B& x2) { return x1-x2; }, py::is_operator()); - py_B.def("__sub__", [](const B& x1, const Matrix& x2) { return x1-x2; }, py::is_operator()); - py_B.def("__sub__", [](const B& x1, const B& x2) { return x1-x2; }, py::is_operator()); + py_M.def("__sub__", [](const Matrix& x1, const Matrix& x2) -> Matrix { return x1-x2; }, py::is_operator()); + py_M.def("__sub__", [](const Matrix& x1, const B& x2) -> Matrix { return x1-x2; }, py::is_operator()); + py_B.def("__sub__", [](const B& x1, const Matrix& x2) -> Matrix { return x1-x2; }, py::is_operator()); + py_B.def("__sub__", [](const B& x1, const B& x2) -> Matrix { return x1-x2; }, py::is_operator()); //IntervalMatrix operator-(const M& x1, const IM& x2) - py_M.def("__sub__", [](const Matrix& x1, const IntervalMatrix& x2) { return x1-x2; }, py::is_operator()); - py_M.def("__sub__", [](const Matrix& x1, const IB& x2) { return x1-x2; }, py::is_operator()); - py_B.def("__sub__", [](const B& x1, const IntervalMatrix& x2) { return x1-x2; }, py::is_operator()); - py_B.def("__sub__", [](const B& x1, const IB& x2) { return x1-x2; }, py::is_operator()); + py_M.def("__sub__", [](const Matrix& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1.template cast()-x2; }, py::is_operator()); + py_M.def("__sub__", [](const Matrix& x1, const IB& x2) -> IntervalMatrix { return x1.template cast()-x2; }, py::is_operator()); + py_B.def("__sub__", [](const B& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1.template cast()-x2; }, py::is_operator()); + py_B.def("__sub__", [](const B& x1, const IB& x2) -> IntervalMatrix { return x1.template cast()-x2; }, py::is_operator()); - py_V.def("__isub__", [](Matrix& x1, const Matrix& x2) { return x1-=x2; }, py::is_operator()); - py_V.def("__isub__", [](Matrix& x1, const B& x2) { return x1-=x2; }, py::is_operator()); + py_M.def("__isub__", [](Matrix& x1, const Matrix& x2) { return x1-=x2; }, py::is_operator()); + py_M.def("__isub__", [](Matrix& x1, const B& x2) { return x1-=x2; }, py::is_operator()); // ====== First operand: interval vector - py_IV.def(-py::self); + py_IV.def("__neg__", [](const IntervalVector& x1) -> IntervalVector { return -x1; }, py::is_operator()); //inline IntervalVector operator-(const IntervalVector& x1, const Vector& x2) - py_IV.def("__sub__", [](const IntervalVector& x1, const Vector& x2) { return x1-x2; }, py::is_operator()); + py_IV.def("__sub__", [](const IntervalVector& x1, const Vector& x2) -> IntervalVector { return x1-x2.template cast(); }, py::is_operator()); //inline IntervalVector operator-(const IntervalVector& x1, const IntervalVector& x2) - py_IV.def("__sub__", [](const IntervalVector& x1, const IntervalVector& x2) { return x1-x2; }, py::is_operator()); + py_IV.def("__sub__", [](const IntervalVector& x1, const IntervalVector& x2) -> IntervalVector { return x1-x2; }, py::is_operator()); - py_V.def("__isub__", [](IntervalVector& x1, const Vector& x2) { return x1-=x2; }, py::is_operator()); - py_V.def("__isub__", [](IntervalVector& x1, const IntervalVector& x2) { return x1-=x2; }, py::is_operator()); + py_IV.def("__isub__", [](IntervalVector& x1, const Vector& x2) { return x1-=x2.template cast(); }, py::is_operator()); + py_IV.def("__isub__", [](IntervalVector& x1, const IntervalVector& x2) { return x1-=x2; }, py::is_operator()); // ====== First operand: interval matrix - py_IM.def(-py::self); + py_IM.def("__neg__", [](const IntervalMatrix& x1) -> IntervalMatrix { return -x1; }, py::is_operator()); //IntervalMatrix operator-(const IM& x1, const M& x2) - py_IM.def("__sub__", [](const IntervalMatrix& x1, const Matrix& x2) { return x1-x2; }, py::is_operator()); - py_IM.def("__sub__", [](const IntervalMatrix& x1, const B& x2) { return x1-x2; }, py::is_operator()); - py_IB.def("__sub__", [](const IB& x1, const Matrix& x2) { return x1-x2; }, py::is_operator()); - py_IB.def("__sub__", [](const IB& x1, const B& x2) { return x1-x2; }, py::is_operator()); + py_IM.def("__sub__", [](const IntervalMatrix& x1, const Matrix& x2) -> IntervalMatrix { return x1-x2.template cast(); }, py::is_operator()); + py_IM.def("__sub__", [](const IntervalMatrix& x1, const B& x2) -> IntervalMatrix { return x1-x2.template cast(); }, py::is_operator()); + py_IB.def("__sub__", [](const IB& x1, const Matrix& x2) -> IntervalMatrix { return x1-x2.template cast(); }, py::is_operator()); + py_IB.def("__sub__", [](const IB& x1, const B& x2) -> IntervalMatrix { return x1-x2.template cast(); }, py::is_operator()); //IntervalMatrix operator-(const IM& x1, const IM_& x2) - py_IM.def("__sub__", [](const IntervalMatrix& x1, const IntervalMatrix& x2) { return x1-x2; }, py::is_operator()); - py_IM.def("__sub__", [](const IntervalMatrix& x1, const IB& x2) { return x1-x2; }, py::is_operator()); - py_IB.def("__sub__", [](const IB& x1, const IntervalMatrix& x2) { return x1-x2; }, py::is_operator()); - py_IB.def("__sub__", [](const IB& x1, const IB& x2) { return x1-x2; }, py::is_operator()); + py_IM.def("__sub__", [](const IntervalMatrix& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1-x2; }, py::is_operator()); + py_IM.def("__sub__", [](const IntervalMatrix& x1, const IB& x2) -> IntervalMatrix { return x1-x2; }, py::is_operator()); + py_IB.def("__sub__", [](const IB& x1, const IntervalMatrix& x2) -> IntervalMatrix { return x1-x2; }, py::is_operator()); + py_IB.def("__sub__", [](const IB& x1, const IB& x2) -> IntervalMatrix { return x1-x2; }, py::is_operator()); - py_IM.def("__isub__", [](IntervalMatrix& x1, const Matrix& x2) { return x1-=x2; }, py::is_operator()); - py_IM.def("__isub__", [](IntervalMatrix& x1, const B& x2) { return x1-=x2; }, py::is_operator()); + py_IM.def("__isub__", [](IntervalMatrix& x1, const Matrix& x2) { return x1-=x2.template cast(); }, py::is_operator()); + py_IM.def("__isub__", [](IntervalMatrix& x1, const B& x2) { return x1-=x2.template cast(); }, py::is_operator()); py_IM.def("__isub__", [](IntervalMatrix& x1, const IntervalMatrix& x2) { return x1-=x2; }, py::is_operator()); py_IM.def("__isub__", [](IntervalMatrix& x1, const IB& x2) { return x1-=x2; }, py::is_operator()); diff --git a/python/src/core/separators/codac2_py_Sep.cpp b/python/src/core/separators/codac2_py_Sep.cpp index 9cc7a75d..9148232e 100644 --- a/python/src/core/separators/codac2_py_Sep.cpp +++ b/python/src/core/separators/codac2_py_Sep.cpp @@ -47,7 +47,7 @@ py::class_ export_Sep(py::module& m) .def("__repr__", [](const BoxPair& x) { std::ostringstream stream; stream << x; - return string(stream.str()); + return std::string(stream.str()); }, OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_BOXPAIR_REF) ; @@ -55,11 +55,11 @@ py::class_ export_Sep(py::module& m) py::class_ py_sep(m, "SepBase"); py_sep - .def(py::init(), - SEPBASE_SEPBASE_SIZET) + .def(py::init(), + SEPBASE_SEPBASE_INDEX) .def("size", &SepBase::size, - SIZET_SEPBASE_SIZE_CONST) + INDEX_SEPBASE_SIZE_CONST) .def("copy", [](SepBase& s) { diff --git a/python/src/core/separators/codac2_py_Sep.h b/python/src/core/separators/codac2_py_Sep.h index 51cf4a23..9825f870 100644 --- a/python/src/core/separators/codac2_py_Sep.h +++ b/python/src/core/separators/codac2_py_Sep.h @@ -26,7 +26,7 @@ class pySep : public SepBase { public: - pySep(size_t_type n) + pySep(Index_type n) : SepBase(n) { matlab::test_integer(n); @@ -63,6 +63,8 @@ class pySep : public SepBase assert(overload && "SepBase: copy method not found"); auto obj = overload(); - return std::shared_ptr(obj.cast(), [](auto p) { /* no delete */ }); + return std::shared_ptr(obj.cast(), + []([[maybe_unused]] auto p) + { /* no delete */ }); } }; \ No newline at end of file diff --git a/python/src/core/separators/codac2_py_SepProj.cpp b/python/src/core/separators/codac2_py_SepProj.cpp index 0ec43047..bfee8d87 100644 --- a/python/src/core/separators/codac2_py_SepProj.cpp +++ b/python/src/core/separators/codac2_py_SepProj.cpp @@ -19,19 +19,19 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -vector test_and_convert(const vector& indices) +vector test_and_convert(const vector& indices) { #if FOR_MATLAB - vector indices_size_t(indices.size()); + vector indices_Index(indices.size()); - for(size_t i = 0 ; i < indices.size() ; i++) + for(Index i = 0 ; i < indices.size() ; i++) { matlab::test_integer(indices[i]); - indices_size_t[i] = matlab::input_index(indices[i]); + indices_Index[i] = matlab::input_index(indices[i]); } - #else // same types: size_t_type == size_t + #else // same types: Index_type == Index return indices; @@ -44,19 +44,19 @@ void export_SepProj(py::module& m, py::class_& pysep) exported .def(py::init( - [](const SepBase& s, vector proj_indices, double default_eps) + [](const SepBase& s, vector proj_indices, double default_eps) { return make_unique(s.copy(), test_and_convert(proj_indices), default_eps); }), - SEPPROJ_SEPPROJ_CONST_S_REF_CONST_VECTOR_SIZET_REF_DOUBLE, + SEPPROJ_SEPPROJ_CONST_S_REF_CONST_VECTOR_INDEX_REF_DOUBLE, "s"_a, "proj_indices"_a, "default_eps"_a=0.01) .def(py::init( - [](const SepBase& s, vector proj_indices, const IntervalVector& y, double default_eps) + [](const SepBase& s, vector proj_indices, const IntervalVector& y, double default_eps) { return make_unique(s.copy(), test_and_convert(proj_indices), y, default_eps); }), - SEPPROJ_SEPPROJ_CONST_S_REF_CONST_VECTOR_SIZET_REF_CONST_INTERVALVECTOR_REF_DOUBLE, + SEPPROJ_SEPPROJ_CONST_S_REF_CONST_VECTOR_INDEX_REF_CONST_INTERVALVECTOR_REF_DOUBLE, "s"_a, "proj_indices"_a, "y"_a, "default_eps"_a=0.01) .def("separate", (BoxPair(SepProj::*)(const IntervalVector&) const) &SepProj::separate, @@ -64,7 +64,7 @@ void export_SepProj(py::module& m, py::class_& pysep) "x"_a) .def("separate", (BoxPair(SepProj::*)(const IntervalVector&,double) const) &SepProj::separate, - BOXPAIR_SEPPROJ_SEPARATE_CONST_INTERVALVECTOR_REF_CONST, + BOXPAIR_SEPPROJ_SEPARATE_CONST_INTERVALVECTOR_REF_DOUBLE_CONST, "x"_a, "eps"_a) ; } \ No newline at end of file diff --git a/python/src/core/tools/codac2_py_Approx.cpp b/python/src/core/tools/codac2_py_Approx.cpp index 4b14a393..c3d52c8c 100644 --- a/python/src/core/tools/codac2_py_Approx.cpp +++ b/python/src/core/tools/codac2_py_Approx.cpp @@ -12,7 +12,10 @@ #include #include #include +#include #include +#include +#include #include #include "codac2_py_Approx_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_doc.h" diff --git a/python/src/graphics/CMakeLists.txt b/python/src/graphics/CMakeLists.txt index 29bd2047..8b5add11 100644 --- a/python/src/graphics/CMakeLists.txt +++ b/python/src/graphics/CMakeLists.txt @@ -12,6 +12,7 @@ paver/codac2_py_drawwhilepaving.cpp styles/codac2_py_Color.cpp + styles/codac2_py_ColorMap.cpp styles/codac2_py_StyleProperties.cpp ) diff --git a/python/src/graphics/codac2_py_graphics.cpp b/python/src/graphics/codac2_py_graphics.cpp index 5ae28b1d..c5f9b520 100644 --- a/python/src/graphics/codac2_py_graphics.cpp +++ b/python/src/graphics/codac2_py_graphics.cpp @@ -22,6 +22,7 @@ void export_drawwhilepaving(py::module& m); // styles void export_Color(py::module& m); +void export_ColorMap(py::module& m); void export_StyleProperties(py::module& m); @@ -31,6 +32,7 @@ PYBIND11_MODULE(_graphics, m) // styles export_Color(m); + export_ColorMap(m); export_StyleProperties(m); // figures diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index f35947aa..4c9e143f 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -36,12 +36,12 @@ void export_Figure2D(py::module& m) .def_readwrite("label", &FigureAxis::label) ; - m.def("axis", [](size_t_type n, const Interval& limits, const std::string& label) + m.def("axis", [](Index_type n, const Interval& limits, const std::string& label) { matlab::test_integer(n); return axis(matlab::input_index(n), limits, label); }, - FIGUREAXIS_AXIS_SIZET_CONST_INTERVAL_REF_CONST_STRING_REF, + FIGUREAXIS_AXIS_INDEX_CONST_INTERVAL_REF_CONST_STRING_REF, "dim_id"_a, "limits"_a, "label"_a=""); py::class_ /* due to enable_shared_from_this */> @@ -56,7 +56,7 @@ void export_Figure2D(py::module& m) CONST_STRING_REF_FIGURE2D_NAME_CONST) .def("size", &Figure2D::size, - SIZET_FIGURE2D_SIZE_CONST) + INDEX_FIGURE2D_SIZE_CONST) .def("axes", &Figure2D::axes, CONST_VECTOR_FIGUREAXIS_REF_FIGURE2D_AXES_CONST) @@ -65,6 +65,12 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_SET_AXES_CONST_FIGUREAXIS_REF_CONST_FIGUREAXIS_REF, "axis1"_a, "axis2"_a) + .def("i", &Figure2D::i, + CONST_INDEX_REF_FIGURE2D_I_CONST) + + .def("j", &Figure2D::j, + CONST_INDEX_REF_FIGURE2D_J_CONST) + .def("pos", &Figure2D::pos, CONST_VECTOR_REF_FIGURE2D_POS_CONST) @@ -140,6 +146,16 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_AUV_CONST_VECTOR_REF_FLOAT_CONST_STYLEPROPERTIES_REF, "x"_a, "size"_a, "s"_a=StyleProperties()) + // Pavings + + .def("draw_paving", (void(Figure2D::*)(const PavingOut&,const StyleProperties&,const StyleProperties&))&Figure2D::draw_paving, + VOID_FIGURE2D_DRAW_PAVING_CONST_PAVINGOUT_REF_CONST_STYLEPROPERTIES_REF_CONST_STYLEPROPERTIES_REF, + "p"_a, "boundary_style"_a=StyleProperties::boundary(), "outside_style"_a=StyleProperties::outside()) + + .def("draw_paving", (void(Figure2D::*)(const PavingInOut&,const StyleProperties&,const StyleProperties&,const StyleProperties&))&Figure2D::draw_paving, + VOID_FIGURE2D_DRAW_PAVING_CONST_PAVINGINOUT_REF_CONST_STYLEPROPERTIES_REF_CONST_STYLEPROPERTIES_REF_CONST_STYLEPROPERTIES_REF, + "p"_a, "boundary_style"_a=StyleProperties::boundary(), "outside_style"_a=StyleProperties::outside(), "inside_style"_a=StyleProperties::inside()) + ; py::class_ exported_default_view(m, "DefaultView", DEFAULTVIEW_MAIN); diff --git a/python/src/graphics/styles/codac2_py_Color.cpp b/python/src/graphics/styles/codac2_py_Color.cpp index 861b7651..d960b3ac 100644 --- a/python/src/graphics/styles/codac2_py_Color.cpp +++ b/python/src/graphics/styles/codac2_py_Color.cpp @@ -19,24 +19,59 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; + void export_Color(py::module& m) { + + py::enum_(m, "Model") + .value("RGB", Model::RGB) + .value("HSV", Model::HSV) + ; + py::class_ exported_color(m, "Color", COLOR_MAIN); exported_color + + .def(py::init<>(),COLOR_COLOR) + + .def(py::init&,Model>(), + COLOR_COLOR_CONST_ARRAY_FLOAT3_REF_MODEL, + "xyz"_a, "m_"_a=Model::RGB) + + .def(py::init&,Model>(), + COLOR_COLOR_CONST_ARRAY_FLOAT4_REF_MODEL, + "xyza"_a, "m_"_a=Model::RGB) + + .def(py::init(), + COLOR_COLOR_CONST_STRING_REF, + "hex_str"_a) + + .def("model", &Color::model, + CONST_MODEL_REF_COLOR_MODEL_CONST) - .def_readwrite("r", &Color::r) - .def_readwrite("g", &Color::g) - .def_readwrite("b", &Color::b) - .def_readwrite("alpha", &Color::alpha) - .def_readwrite("hex_str", &Color::hex_str) - .def(py::init(), - COLOR_COLOR_INT_INT_INT_INT, - "r"_a, "g"_a, "b"_a, "alpha"_a=255) + // Other formats - .def(py::init(), - COLOR_COLOR_FLOAT_FLOAT_FLOAT_FLOAT, - "r"_a, "g"_a, "b"_a, "alpha"_a=1.) + .def("hex_str", &Color::hex_str, + STRING_COLOR_HEX_STR_CONST) + + .def("vec", &Color::vec, + VECTOR_COLOR_VEC_CONST) + + // Conversions + + .def("rgb", &Color::rgb, + COLOR_COLOR_RGB_CONST) + + .def("hsv", &Color::hsv, + COLOR_COLOR_HSV_CONST) + + // Overload flux operator + + .def("__str__", [](const Color& c) { + std::ostringstream oss; + oss << c; + return oss.str(); + }) // Predefined colors @@ -75,4 +110,6 @@ void export_Color(py::module& m) STATIC_COLOR_COLOR_DARK_GRAY_FLOAT, "alpha"_a=1.) ; + + py::implicitly_convertible(); } \ No newline at end of file diff --git a/python/src/graphics/styles/codac2_py_ColorMap.cpp b/python/src/graphics/styles/codac2_py_ColorMap.cpp new file mode 100644 index 00000000..e127777e --- /dev/null +++ b/python/src/graphics/styles/codac2_py_ColorMap.cpp @@ -0,0 +1,55 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include "codac2_py_ColorMap_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_ColorMap(py::module& m) +{ + py::class_ exported_colormap(m, "ColorMap", COLORMAP_MAIN); + exported_colormap + + .def(py::init(), + COLORMAP_COLORMAP_MODEL, + "m"_a=Model::RGB) + + .def("model", &ColorMap::model, + CONST_MODEL_REF_COLORMAP_MODEL_CONST) + + .def("color", &ColorMap::color, + COLOR_COLORMAP_COLOR_FLOAT_CONST, + "r"_a) + + // Predifined color maps + + .def_static("haxby", &ColorMap::haxby, + STATIC_COLORMAP_COLORMAP_HAXBY) + + .def_static("basic", &ColorMap::basic, + STATIC_COLORMAP_COLORMAP_BASIC) + + .def_static("blue_tube", &ColorMap::blue_tube, + STATIC_COLORMAP_COLORMAP_BLUE_TUBE) + + .def_static("red_tube", &ColorMap::red_tube, + STATIC_COLORMAP_COLORMAP_RED_TUBE) + + .def_static("rainbow", &ColorMap::rainbow, + STATIC_COLORMAP_COLORMAP_RAINBOW) + + ; +} \ No newline at end of file diff --git a/python/src/graphics/styles/codac2_py_StyleProperties.cpp b/python/src/graphics/styles/codac2_py_StyleProperties.cpp index aa222d0e..0259a3db 100644 --- a/python/src/graphics/styles/codac2_py_StyleProperties.cpp +++ b/python/src/graphics/styles/codac2_py_StyleProperties.cpp @@ -45,10 +45,6 @@ void export_StyleProperties(py::module& m) }), STYLEPROPERTIES_STYLEPROPERTIES_INITIALIZER_LIST_COLOR, "v"_a) - - .def(py::init(), - STYLEPROPERTIES_STYLEPROPERTIES_CONST_STRING_REF, - "vibes_style"_a) .def_static("inside", &StyleProperties::inside, STATIC_STYLEPROPERTIES_STYLEPROPERTIES_INSIDE) diff --git a/scripts/CMakeModules/FindSphinx.cmake b/scripts/CMakeModules/FindSphinx.cmake new file mode 100644 index 00000000..6190fa01 --- /dev/null +++ b/scripts/CMakeModules/FindSphinx.cmake @@ -0,0 +1,20 @@ +include(FindPackageHandleStandardArgs) + +# We are likely to find Sphinx near the Python interpreter +find_package(PythonInterp) +if(PYTHONINTERP_FOUND) + get_filename_component(_PYTHON_DIR "${PYTHON_EXECUTABLE}" DIRECTORY) + set( + _PYTHON_PATHS + "${_PYTHON_DIR}" + "${_PYTHON_DIR}/bin" + "${_PYTHON_DIR}/Scripts") +endif() + +find_program( + SPHINX_EXECUTABLE + NAMES sphinx-build sphinx-build.exe + HINTS ${_PYTHON_PATHS}) +mark_as_advanced(SPHINX_EXECUTABLE) + +find_package_handle_standard_args(Sphinx DEFAULT_MSG SPHINX_EXECUTABLE) \ No newline at end of file diff --git a/scripts/CMakeModules/version_from_git.cmake b/scripts/CMakeModules/version_from_git.cmake index fa5542f1..34b6c491 100644 --- a/scripts/CMakeModules/version_from_git.cmake +++ b/scripts/CMakeModules/version_from_git.cmake @@ -20,7 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required( VERSION 3.0.0 ) +#cmake_minimum_required( VERSION 3.0.0 ) +cmake_minimum_required(VERSION 3.14...3.25) include( CMakeParseArguments ) diff --git a/scripts/dependencies/install_ibex.sh b/scripts/dependencies/install_ibex.sh index e115fb32..40c682d4 100644 --- a/scripts/dependencies/install_ibex.sh +++ b/scripts/dependencies/install_ibex.sh @@ -3,7 +3,8 @@ cd $HOME echo 'Installing IBEX in ' $HOME '...'; if [ ! -e "ibex-lib/README.md" ]; then - git clone -b master https://github.com/lebarsfa/ibex-lib.git ; + #git clone -b master https://github.com/lebarsfa/ibex-lib.git ; + git clone -b ibex-2.8.9.20241117 https://github.com/lebarsfa/ibex-lib.git ; # To test a specific version of IBEX... cd ibex-lib ; mkdir build && cd build ; cmake -E env CXXFLAGS="-fPIC" CFLAGS="-fPIC" cmake -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Debug .. ; diff --git a/scripts/docker/build_pybinding.sh b/scripts/docker/build_pybinding.sh index 81bf7972..f9a50cd5 100755 --- a/scripts/docker/build_pybinding.sh +++ b/scripts/docker/build_pybinding.sh @@ -2,7 +2,7 @@ set -e -x -wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20240417/ibex_$(uname -m)_manylinux2014.zip --no-check-certificate -nv +wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_$(uname -m)_manylinux2014.zip --no-check-certificate -nv unzip -q ibex_$(uname -m)_manylinux2014.zip rm -Rf ibex_$(uname -m)_manylinux2014.zip sudo cp -Rf ibex/* /usr/local/ @@ -16,6 +16,7 @@ for PYBIN in /opt/python/cp3*/bin; do #fi "${PYBIN}/python" -m pip install --upgrade pip + "${PYBIN}/python" -m pip install --upgrade wheel setuptools mkdir -p build_dir && cd build_dir cmake -E env CXXFLAGS="-fPIC" CFLAGS="-fPIC" cmake -DPYTHON_EXECUTABLE=${PYBIN}/python -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON -DWITH_CAPD=OFF -DWITH_PYTHON=ON .. make -j4 @@ -27,8 +28,8 @@ for PYBIN in /opt/python/cp3*/bin; do done "${PYBIN}/python" -m pip install codac --no-deps --no-index -f /io/wheelhouse - "${PYBIN}/python" -m pip install numpy --prefer-binary "${PYBIN}/python" ../examples/02_centered_form/main.py + "${PYBIN}/python" -m pip install numpy --prefer-binary "${PYBIN}/python" -m unittest discover codac.tests make test ARGS="-V --output-on-failure" diff --git a/scripts/docker/build_pybinding_codac4matlab.sh b/scripts/docker/build_pybinding_codac4matlab.sh new file mode 100644 index 00000000..d0ea4b3d --- /dev/null +++ b/scripts/docker/build_pybinding_codac4matlab.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -e -x + +wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_$(uname -m)_manylinux2014.zip --no-check-certificate -nv +unzip -q ibex_$(uname -m)_manylinux2014.zip +rm -Rf ibex_$(uname -m)_manylinux2014.zip +sudo cp -Rf ibex/* /usr/local/ + +git config --global --add safe.directory /io +cd /io +for PYBIN in /opt/python/cp3*/bin; do + + #if [ "${PYBIN}" = "/opt/python/cp310-cp310/bin" ]; then + # continue + #fi + + "${PYBIN}/python" -m pip install --upgrade pip + "${PYBIN}/python" -m pip install --upgrade wheel setuptools + mkdir -p build_dir && cd build_dir + cmake -E env CXXFLAGS="-fPIC" CFLAGS="-fPIC" cmake -DPYTHON_EXECUTABLE=${PYBIN}/python -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON -DWITH_CAPD=OFF -DWITH_PYTHON=ON .. + make -j4 + + make pip_package + echo "copy wheel and clean build_dir" + for whl in *.whl; do + auditwheel repair "$whl" -w /io/wheelhouse/ + done + + "${PYBIN}/python" -m pip install codac4matlab --no-deps --no-index -f /io/wheelhouse + "${PYBIN}/python" -c "import sys; print(sys.version); import codac4matlab; print(codac4matlab.__version__); from codac4matlab import *; print(IntervalVector([[-0.1],[0],[0.2]]))" + #"${PYBIN}/python" ../examples/02_centered_form/main.py + #"${PYBIN}/python" -m pip install numpy --prefer-binary + #"${PYBIN}/python" -m unittest discover codac.tests + + #make test ARGS="-V --output-on-failure" + #echo "start of Testing/Temporary/LastTest.log" + #cat Testing/Temporary/LastTest.log + #echo "end of Testing/Temporary/LastTest.log" + + cd /io + rm -fr build_dir + +done diff --git a/scripts/pybind/doxygen2docstring.py b/scripts/pybind/doxygen2docstring.py index 1c3a4dc5..de333bdc 100644 --- a/scripts/pybind/doxygen2docstring.py +++ b/scripts/pybind/doxygen2docstring.py @@ -68,9 +68,9 @@ def normalize_label(str_label): .replace("__PTR", "_PTR") \ .replace("-1", "MINUSONE") -def docstring_varname(memberdef): +def docstring_varname(memberdef, prefix=''): - txt = normalize_label(memberdef.find(".//definition").text) + txt = prefix + normalize_label(memberdef.find(".//definition").text) for param in memberdef.findall("param"): if param.find("type") != None: @@ -105,24 +105,30 @@ def get_originate_file(m): class_compound = root.find("./compounddef") if class_compound == None or (class_compound.get('kind') != None and \ - (class_compound.attrib['kind'] == "file" or class_compound.attrib['kind'] == "dir")): + class_compound.attrib['kind'] == "dir"): continue class_name = class_compound.find("./compoundname").text - with open(sys.argv[2] + "/" + get_originate_file(class_compound), 'a', encoding='utf-8') as f: + if class_compound.attrib['kind'] != "file": - print("/// Class " + class_name, file=f) - #print("const char* " - # + normalize_label(class_name + "_MAIN").upper() - # + " = R\"Docstring documentation will be available in next release.\";", file=f) - print("#define " - + normalize_label(class_name + "_MAIN").upper() - + " \"Docstring documentation will be available in next release.\"", file=f) + with open(sys.argv[2] + "/" + get_originate_file(class_compound), 'a', encoding='utf-8') as f: + + print("/// Class " + class_name, file=f) + #print("const char* " + # + normalize_label(class_name + "_MAIN").upper() + # + " = R\"Docstring documentation will be available in next release.\";", file=f) + print("#define " + + normalize_label(class_name + "_MAIN").upper() + + " \"Docstring documentation will be available in next release.\"", file=f) # Members documentation (ex: methods, functions, etc.) + prefix = "" + if class_compound.attrib['kind'] == "file": + prefix = class_name.replace(".h", "").replace("codac2_", "") + "_" + for memberdef in root.findall(".//memberdef"): with open(sys.argv[2] + "/" + get_originate_file(memberdef), 'a', encoding='utf-8') as f: @@ -152,7 +158,7 @@ def get_originate_file(m): # + " = R\"Docstring documentation will be available in next release.\";", file=f) print("#define " - + docstring_varname(memberdef) + + docstring_varname(memberdef, prefix) + " \"Docstring documentation will be available in next release.\"", file=f) print("\n", file=f) \ No newline at end of file diff --git a/scripts/wheels/gencodacwhl.sh b/scripts/wheels/gencodacwhl.sh index 7b94aba7..bff102d5 100644 --- a/scripts/wheels/gencodacwhl.sh +++ b/scripts/wheels/gencodacwhl.sh @@ -10,7 +10,7 @@ for PY_V_MIN in 6 7; do done done -for PY_V_MIN in 8 9 10 11 12; do +for PY_V_MIN in 8 9 10 11 12 13; do for CPCFG in "-macosx_10_16_x86_64" "-macosx_11_0_arm64" "-manylinux_2_17_x86_64.manylinux2014_x86_64" "-win32" "-win_amd64"; do rm -Rf codac-$PACKAGE_VERSION-cp$PY_V_MAJ$PY_V_MIN-cp$PY_V_MAJ$PY_V_MIN$CPCFG.whl ; wget https://github.com/codac-team/codac/releases/download/v$PACKAGE_VERSION/codac-$PACKAGE_VERSION-cp$PY_V_MAJ$PY_V_MIN-cp$PY_V_MAJ$PY_V_MIN$CPCFG.whl --no-check-certificate -nv done diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f146faa7..2a3f79a4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,7 +65,7 @@ set(CODAC_VERSION ${PROJECT_VERSION}) set(CODAC_LIBRARIES \${CODAC_CORE_LIBRARY} \${CODAC_GRAPHICS_LIBRARY} \${CODAC_UNSUPPORTED_LIBRARY} \${CODAC_CORE_LIBRARY}) - set(CODAC_INCLUDE_DIRS \${CODAC_CORE_INCLUDE_DIR}/../ \${CODAC_CORE_INCLUDE_DIR} \${CODAC_GRAPHICS_INCLUDE_DIR} \${CODAC_UNSUPPORTED_INCLUDE_DIR}) + set(CODAC_INCLUDE_DIRS \${CODAC_CORE_INCLUDE_DIR}/../ \${CODAC_CORE_INCLUDE_DIR}/../eigen3/ \${CODAC_CORE_INCLUDE_DIR} \${CODAC_GRAPHICS_INCLUDE_DIR} \${CODAC_UNSUPPORTED_INCLUDE_DIR}) set(CODAC_C_FLAGS \"\") set(CODAC_CXX_FLAGS \"\") diff --git a/src/core/3rd/codac2_eigen.h b/src/core/3rd/codac2_eigen.h deleted file mode 100644 index e0d4fbd8..00000000 --- a/src/core/3rd/codac2_eigen.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef EIGEN_NO_DEBUG -/* Disables Eigen's assertions if defined. - * Not defined by default, unless the NDEBUG macro is defined - * (this is a standard C++ macro which disables all asserts). - * https://eigen.tuxfamily.org/dox/TopicPreprocessorDirectives.html - */ -#define EIGEN_NO_DEBUG -#endif - -#pragma once - -#include -#include -#include "codac2_Interval.h" -#include "codac2_Interval_operations.h" - -namespace Eigen -{ - template<> struct NumTraits - : NumTraits // permits to get the epsilon, dummy_precision, lowest, highest functions - { - typedef codac2::Interval Real; - typedef codac2::Interval NonInteger; - typedef codac2::Interval Nested; - - enum { - IsComplex = 0, - IsInteger = 0, - IsSigned = 1, - RequireInitialization = 1, - ReadCost = 1, - AddCost = 3, - MulCost = 3 - }; - }; -} - -namespace codac2 -{ - using Eigen::Dynamic; - - inline const Interval& conj(const Interval& x) { return x; } - inline const Interval& real(const Interval& x) { return x; } - inline Interval imag(const Interval&) { return 0.; } - //inline Interval abs(const Interval& x) { return codac2::abs(x); } - inline Interval abs2(const Interval& x) { return codac2::sqr(x); } - -} \ No newline at end of file diff --git a/src/core/3rd/codac2_ibex.cpp b/src/core/3rd/codac2_ibex.cpp index e84e6cba..338b5fa5 100644 --- a/src/core/3rd/codac2_ibex.cpp +++ b/src/core/3rd/codac2_ibex.cpp @@ -32,7 +32,7 @@ namespace codac2 #define cast_vector(OutputType,convert) \ \ OutputType x_(x.size()); \ - for(size_t i = 0 ; i < (size_t)x.size() ; i++) \ + for(Index i = 0 ; i < (Index)x.size() ; i++) \ x_[i] = convert(x[i]); \ return x_; \ @@ -56,32 +56,32 @@ namespace codac2 cast_vector(codac2::IntervalVector,to_codac); } - #define cast_matrix(OutputType,convert_f,output_ij,input_ij) \ + #define cast_matrix(OutputType,convert_f,output_ij,input_ij,rows_,cols_) \ \ - OutputType x_(x.nb_rows(), x.nb_cols()); \ - for(size_t i = 0 ; i < (size_t)x.nb_rows() ; i++) \ - for(size_t j = 0 ; j < (size_t)x.nb_cols() ; j++) \ + OutputType x_(x.rows_(), x.cols_()); \ + for(Index i = 0 ; i < (Index)x.rows_() ; i++) \ + for(Index j = 0 ; j < (Index)x.cols_() ; j++) \ output_ij = convert_f(input_ij); \ return x_; \ ibex::Matrix to_ibex(const codac2::Matrix& x) { - cast_matrix(ibex::Matrix,double,x_[i][j],x(i,j)); + cast_matrix(ibex::Matrix,double,x_[i][j],x(i,j),rows,cols); } codac2::Matrix to_codac(const ibex::Matrix& x) { - cast_matrix(codac2::Matrix,double,x_(i,j),x[i][j]); + cast_matrix(codac2::Matrix,double,x_(i,j),x[i][j],nb_rows,nb_cols); } ibex::IntervalMatrix to_ibex(const codac2::IntervalMatrix& x) { - cast_matrix(ibex::IntervalMatrix,to_ibex,x_[i][j],x(i,j)); + cast_matrix(ibex::IntervalMatrix,to_ibex,x_[i][j],x(i,j),rows,cols); } codac2::IntervalMatrix to_codac(const ibex::IntervalMatrix& x) { - cast_matrix(codac2::IntervalMatrix,to_codac,x_(i,j),x[i][j]); + cast_matrix(codac2::IntervalMatrix,to_codac,x_(i,j),x[i][j],nb_rows,nb_cols); } } // namespace codac \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fa36996c..98c9c3d7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -4,7 +4,6 @@ list(APPEND CODAC_CORE_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/3rd/codac2_eigen.h ${CMAKE_CURRENT_SOURCE_DIR}/3rd/codac2_ibex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/3rd/codac2_ibex.h @@ -15,12 +14,18 @@ ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcAction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcAction.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcCartProd.h + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcCtcBoundary.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcCtcBoundary.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcDist.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcDist.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcEllipse.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcEllipse.h + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcEmpty.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcEmpty.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcFixpoint.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcFixpoint.h + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcIdentity.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcIdentity.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcInnerOuter.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcInter.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcInverse.h @@ -31,6 +36,10 @@ ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcUnion.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcPolar.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcPolar.h + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcPolygon.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcPolygon.h + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcProj.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcProj.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcSegment.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcSegment.h ${CMAKE_CURRENT_SOURCE_DIR}/contractors/codac2_CtcWrapper.h @@ -45,14 +54,11 @@ ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid_utils.h - ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval_operations.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval_operations.h - ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_IntervalMatrix.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_IntervalMatrix.h - ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_IntervalMatrixBase.h - ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_IntervalVector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_IntervalRow.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_IntervalVector.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/paving/codac2_Paving.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/paving/codac2_Paving.h @@ -83,25 +89,42 @@ ${CMAKE_CURRENT_SOURCE_DIR}/geometry/codac2_geometry.h ${CMAKE_CURRENT_SOURCE_DIR}/geometry/codac2_Polygon.cpp ${CMAKE_CURRENT_SOURCE_DIR}/geometry/codac2_Polygon.h + + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Base.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_include.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrix.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrixBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalVector.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Matrix.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_MatrixBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Vector.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons/codac2_Matrix_addons_VectorBase.h + + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Base.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_include.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrix.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrixBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalVector.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Matrix.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_MatrixBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Vector.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_VectorBase.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_arithmetic.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_arithmetic_add.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_arithmetic_div.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_arithmetic_mul.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_arithmetic_sub.h ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_GaussJordan.cpp ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_GaussJordan.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_Matrix.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_Inversion.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_Inversion.h + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_matrices.h ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_Matrix.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_MatrixBase.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_MatrixBaseBlock.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_Vector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_Row.h ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_Vector.h - ${CMAKE_CURRENT_SOURCE_DIR}/matrices/codac2_VectorBase.h ${CMAKE_CURRENT_SOURCE_DIR}/paver/codac2_pave.cpp ${CMAKE_CURRENT_SOURCE_DIR}/paver/codac2_pave.h + ${CMAKE_CURRENT_SOURCE_DIR}/proj/codac2_ProjBase.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/proj/codac2_ProjBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/separators/codac2_Sep.h ${CMAKE_CURRENT_SOURCE_DIR}/separators/codac2_SepAction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/separators/codac2_SepAction.h @@ -131,6 +154,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_Approx.h ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_assert.h ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_Collection.h + ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_Index.h ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_math.h ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_object_file_format.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_object_file_format.h @@ -154,6 +178,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/domains ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval + ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/eigen ${CMAKE_CURRENT_SOURCE_DIR}/domains/paving ${CMAKE_CURRENT_SOURCE_DIR}/functions ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic @@ -163,7 +188,10 @@ ${CMAKE_CURRENT_SOURCE_DIR}/graphics/ipe ${CMAKE_CURRENT_SOURCE_DIR}/graphics/vibes ${CMAKE_CURRENT_SOURCE_DIR}/matrices + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/Matrix_addons + ${CMAKE_CURRENT_SOURCE_DIR}/matrices/eigen/MatrixBase_addons ${CMAKE_CURRENT_SOURCE_DIR}/paver + ${CMAKE_CURRENT_SOURCE_DIR}/proj ${CMAKE_CURRENT_SOURCE_DIR}/separators ${CMAKE_CURRENT_SOURCE_DIR}/tools ) @@ -199,7 +227,9 @@ file(APPEND ${CODAC_CORE_MAIN_HEADER} "#pragma once\n\n") foreach(header_path ${CODAC_CORE_HDR}) get_filename_component(header_name ${header_path} NAME) - file(APPEND ${CODAC_CORE_MAIN_HEADER} "#include <${header_name}>\n") + if(NOT header_name MATCHES "^.*_addons.*$") + file(APPEND ${CODAC_CORE_MAIN_HEADER} "#include <${header_name}>\n") + endif() endforeach() file(COPY ${CODAC_CORE_MAIN_HEADER} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../include) @@ -208,4 +238,4 @@ install(TARGETS ${PROJECT_NAME}-core DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES ${CODAC_CORE_HDR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-core) - install(FILES ${CODAC_CORE_MAIN_HEADER} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-core) \ No newline at end of file + install(FILES ${CODAC_CORE_MAIN_HEADER} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-core) diff --git a/src/core/actions/codac2_OctaSym.cpp b/src/core/actions/codac2_OctaSym.cpp index e5e3f909..355bbb5b 100644 --- a/src/core/actions/codac2_OctaSym.cpp +++ b/src/core/actions/codac2_OctaSym.cpp @@ -15,22 +15,12 @@ using namespace std; using namespace codac2; -Interval sign(int a) -{ - return (a > 0) ? 1 : ((a < 0) ? -1 : 0); -} - -int isign(int a) -{ - return (a > 0) ? 1 : ((a < 0) ? -1 : 0); -} - OctaSym::OctaSym(const vector& s) : std::vector(s) { - for(const auto& i : s) + for([[maybe_unused]] const auto& i : s) { - assert_release((size_t)std::abs(i) > 0 && (size_t)std::abs(i) <= size()); + assert_release(std::abs(i) > 0 && std::abs(i) <= size()); } } @@ -51,15 +41,6 @@ OctaSym OctaSym::operator*(const OctaSym& s) const assert_release(size() == s.size()); OctaSym a(*this); for(size_t i = 0 ; i < a.size() ; i++) - a[i] = isign(s[i])*(*this)[std::abs((int)s[i])-1]; + a[i] = _sign(s[i])*(*this)[std::abs((int)s[i])-1]; return a; -} - -IntervalVector OctaSym::operator()(const IntervalVector& x) const -{ - assert_release((size_t)x.size() == size()); - IntervalVector x_(size()); - for(size_t i = 0 ; i < size() ; i++) - x_[i] = sign((*this)[i])*x[std::abs((*this)[i])-1]; - return x_; } \ No newline at end of file diff --git a/src/core/actions/codac2_OctaSym.h b/src/core/actions/codac2_OctaSym.h index da695b88..a649a909 100644 --- a/src/core/actions/codac2_OctaSym.h +++ b/src/core/actions/codac2_OctaSym.h @@ -10,7 +10,7 @@ #pragma once #include -#include "codac2_Vector.h" +#include "codac2_matrices.h" #include "codac2_IntervalVector.h" #include "codac2_CtcWrapper.h" #include "codac2_template_tools.h" @@ -42,7 +42,20 @@ namespace codac2 OctaSym operator*(const OctaSym& s) const; - IntervalVector operator()(const IntervalVector& x) const; + int _sign(int a) const + { + return (a > 0) ? 1 : ((a < 0) ? -1 : 0); + } + + template + Mat operator()(const Mat& x) const + { + assert_release(x.size() == (Index)size()); + Mat x_(size()); + for(size_t i = 0 ; i < size() ; i++) + x_[i] = _sign((*this)[i])*x[std::abs((*this)[i])-1]; + return x_; + } template requires IsCtcBaseOrPtr diff --git a/src/core/contractors/codac2_Ctc.h b/src/core/contractors/codac2_Ctc.h index 4ca801a5..d34e8552 100644 --- a/src/core/contractors/codac2_Ctc.h +++ b/src/core/contractors/codac2_Ctc.h @@ -11,6 +11,7 @@ #include #include +#include "codac2_Index.h" #include "codac2_assert.h" namespace codac2 @@ -41,13 +42,13 @@ namespace codac2 using ContractedType = X; - CtcBase(size_t n) + CtcBase(Index n) : _n(n) { assert(n > 0); } - size_t size() const + Index size() const { return _n; } @@ -58,7 +59,7 @@ namespace codac2 protected: - const size_t _n; + const Index _n; }; template @@ -66,7 +67,7 @@ namespace codac2 { public: - Ctc(size_t n) + Ctc(Index n) : CtcBase(n) { } diff --git a/src/core/contractors/codac2_CtcAction.h b/src/core/contractors/codac2_CtcAction.h index 64905c69..96658a25 100644 --- a/src/core/contractors/codac2_CtcAction.h +++ b/src/core/contractors/codac2_CtcAction.h @@ -26,7 +26,7 @@ namespace codac2 CtcAction(const C& c, const OctaSym& a) : Ctc(a.size()), _ctc(c), _s(a), __s(a.invert()) { - assert_release(size_of(c) == a.size()); + assert_release(size_of(c) == (Index)a.size()); } void contract(IntervalVector& x) const; diff --git a/src/core/contractors/codac2_CtcCartProd.h b/src/core/contractors/codac2_CtcCartProd.h index 49ffe62a..f88e3323 100644 --- a/src/core/contractors/codac2_CtcCartProd.h +++ b/src/core/contractors/codac2_CtcCartProd.h @@ -23,7 +23,7 @@ namespace codac2 CtcCartProd(const Collection>& ctcs) : Ctc([ctcs] { - size_t n = 0; + Index n = 0; for(const auto& ci : ctcs) n += ci->size(); return n; @@ -46,7 +46,7 @@ namespace codac2 { assert_release(x.size() == this->size()); - size_t i = 0; + Index i = 0; for(const auto& ci : _ctcs) { IntervalVector xi = x.subvector(i,i+ci->size()-1); diff --git a/src/core/contractors/codac2_CtcCtcBoundary.cpp b/src/core/contractors/codac2_CtcCtcBoundary.cpp new file mode 100644 index 00000000..a291b813 --- /dev/null +++ b/src/core/contractors/codac2_CtcCtcBoundary.cpp @@ -0,0 +1,52 @@ +/** + * codac2_CtcCtcBoundary.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Benoit Desrochers + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_CtcCtcBoundary.h" + +using namespace std; +using namespace codac2; + +void CtcCtcBoundary::contract(IntervalVector& x) const +{ + assert_release(x.size() == this->size()); + + Index attempt_nb = 5; + IntervalVector prev_x(x); + _ctc_boundary.front().contract(x); + + for(const auto& b : prev_x.diff(x,false)) + { + if(b.is_empty()) + continue; + + Vector m = b.mid(); // first try: midpoint of the box + BoolInterval d; + Index k = 0; + + do + { + d = _inside_test(m); + if(d == BoolInterval::UNKNOWN) + m = b.rand(); // now, trying a random vector in the box + } while(d == BoolInterval::UNKNOWN && k++ < attempt_nb); + + switch(d) + { + case BoolInterval::TRUE: + case BoolInterval::UNKNOWN: + x |= b; + break; + case BoolInterval::FALSE: + break; + case BoolInterval::EMPTY: + assert(false && "BoolInterval::EMPTY should not happen"); + break; + } + } +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcCtcBoundary.h b/src/core/contractors/codac2_CtcCtcBoundary.h new file mode 100644 index 00000000..b22c3383 --- /dev/null +++ b/src/core/contractors/codac2_CtcCtcBoundary.h @@ -0,0 +1,38 @@ +/** + * \file codac2_CtcCtcBoundary.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Benoit Desrochers + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include "codac2_Ctc.h" +#include "codac2_IntervalVector.h" +#include "codac2_Collection.h" +#include "codac2_BoolInterval.h" +#include "codac2_template_tools.h" + +namespace codac2 +{ + class CtcCtcBoundary : public Ctc + { + public: + + template + requires IsCtcBaseOrPtr + CtcCtcBoundary(const C& ctc_boundary, const std::function& inside_test) + : Ctc(size_of(ctc_boundary)), _ctc_boundary(ctc_boundary), _inside_test(inside_test) + { } + + void contract(IntervalVector& x) const; + + protected: + + const Collection> _ctc_boundary; + const std::function _inside_test; + }; +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcEllipse.cpp b/src/core/contractors/codac2_CtcEllipse.cpp index 195de192..15993843 100644 --- a/src/core/contractors/codac2_CtcEllipse.cpp +++ b/src/core/contractors/codac2_CtcEllipse.cpp @@ -62,7 +62,7 @@ void CtcEllipse0::contract(IntervalVector& x) const } } -CtcEllipse::CtcEllipse(const Vector& q) +CtcEllipse::CtcEllipse(const IntervalVector& q) : Ctc(2), _q(q) { assert_release(q.size() == 6); @@ -76,7 +76,7 @@ void CtcEllipse::contract(IntervalVector& x) const | contract_ith({1,-2}, x) | contract_ith({-1, 2}, x); } -const Vector& CtcEllipse::q() const +const IntervalVector& CtcEllipse::q() const { return _q; } diff --git a/src/core/contractors/codac2_CtcEllipse.h b/src/core/contractors/codac2_CtcEllipse.h index 0e35b7ec..149cdb2f 100644 --- a/src/core/contractors/codac2_CtcEllipse.h +++ b/src/core/contractors/codac2_CtcEllipse.h @@ -30,14 +30,14 @@ namespace codac2 { public: - CtcEllipse(const Vector& q); + CtcEllipse(const IntervalVector& q); void contract(IntervalVector& x) const; - const Vector& q() const; + const IntervalVector& q() const; protected: IntervalVector contract_ith(const OctaSym& i, const IntervalVector& x) const; - const Vector _q; + const IntervalVector _q; }; } \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcEmpty.cpp b/src/core/contractors/codac2_CtcEmpty.cpp new file mode 100644 index 00000000..57718952 --- /dev/null +++ b/src/core/contractors/codac2_CtcEmpty.cpp @@ -0,0 +1,22 @@ +/** + * codac2_CtcEmpty.cp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_CtcEmpty.h" + +using namespace std; +using namespace codac2; + +CtcEmpty::CtcEmpty(Index n) + : Ctc(n) +{ } + +void CtcEmpty::contract(IntervalVector& x) const +{ + x.set_empty(); +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcEmpty.h b/src/core/contractors/codac2_CtcEmpty.h new file mode 100644 index 00000000..7f1484da --- /dev/null +++ b/src/core/contractors/codac2_CtcEmpty.h @@ -0,0 +1,25 @@ +/** + * \file codac2_CtcEmpty.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_CtcWrapper.h" +#include "codac2_IntervalVector.h" + +namespace codac2 +{ + class CtcEmpty : public Ctc + { + public: + + CtcEmpty(Index n); + + void contract(IntervalVector& x) const; + }; +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcFixpoint.h b/src/core/contractors/codac2_CtcFixpoint.h index d84ab33a..785693a4 100644 --- a/src/core/contractors/codac2_CtcFixpoint.h +++ b/src/core/contractors/codac2_CtcFixpoint.h @@ -2,7 +2,7 @@ * \file codac2_CtcFixpoint.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Luc Jaulin * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ diff --git a/src/core/contractors/codac2_CtcIdentity.cpp b/src/core/contractors/codac2_CtcIdentity.cpp new file mode 100644 index 00000000..0a3e95b4 --- /dev/null +++ b/src/core/contractors/codac2_CtcIdentity.cpp @@ -0,0 +1,20 @@ +/** + * codac2_CtcIdentity.cp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_CtcIdentity.h" + +using namespace std; +using namespace codac2; + +CtcIdentity::CtcIdentity(Index n) + : Ctc(n) +{ } + +void CtcIdentity::contract([[maybe_unused]] IntervalVector& x) const +{ } \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcIdentity.h b/src/core/contractors/codac2_CtcIdentity.h new file mode 100644 index 00000000..78d15d78 --- /dev/null +++ b/src/core/contractors/codac2_CtcIdentity.h @@ -0,0 +1,25 @@ +/** + * \file codac2_CtcIdentity.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_CtcWrapper.h" +#include "codac2_IntervalVector.h" + +namespace codac2 +{ + class CtcIdentity : public Ctc + { + public: + + CtcIdentity(Index n); + + void contract([[maybe_unused]] IntervalVector& x) const; + }; +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcInter.h b/src/core/contractors/codac2_CtcInter.h index 77e89d12..28fc0f95 100644 --- a/src/core/contractors/codac2_CtcInter.h +++ b/src/core/contractors/codac2_CtcInter.h @@ -21,6 +21,15 @@ namespace codac2 { public: + explicit CtcInter(Index n) + : Ctc,X>(n) + { + if constexpr(std::is_same_v) + { + assert(n == 1); + } + } + template requires (IsCtcBaseOrPtr && !std::is_same_v,C>) CtcInter(const C& c) diff --git a/src/core/contractors/codac2_CtcInverse.h b/src/core/contractors/codac2_CtcInverse.h index 91dde651..33b8365e 100644 --- a/src/core/contractors/codac2_CtcInverse.h +++ b/src/core/contractors/codac2_CtcInverse.h @@ -29,7 +29,10 @@ namespace codac2 requires IsCtcBaseOrPtr CtcInverse(const AnalyticFunction::Domain>& f, const C& ctc_y, bool with_centered_form = true, bool is_not_in = false) : _f(f), _ctc_y(ctc_y), _with_centered_form(with_centered_form), _is_not_in(is_not_in) - { } + { + assert_release([&]() { return f.output_size() == size_of(ctc_y); }() + && "CtcInverse: invalid dimension of image argument ('y' or 'ctc_y')"); + } CtcInverse(const AnalyticFunction::Domain>& f, const Y& y, bool with_centered_form = true, bool is_not_in = false) : CtcInverse(f, CtcWrapper_(y), with_centered_form, is_not_in) @@ -92,7 +95,7 @@ namespace codac2 X0 x_mid = X0(x_.mid()); assert(val_expr.a.size() == val_expr.m.size()); - IntervalVector fm({val_expr.a - val_expr.m}); + IntervalVector fm { val_expr.a - val_expr.m }; if constexpr(std::is_same_v) { diff --git a/src/core/contractors/codac2_CtcNot.h b/src/core/contractors/codac2_CtcNot.h index bf0c45b8..1972b1c3 100644 --- a/src/core/contractors/codac2_CtcNot.h +++ b/src/core/contractors/codac2_CtcNot.h @@ -26,9 +26,9 @@ namespace codac2 : Ctc(size_of(c)) { } - void contract(IntervalVector& x) const + void contract([[maybe_unused]] IntervalVector& x) const { - /* does nothing: no inner information */ + /* nothing can be done: no inner information */ } }; } \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcPolygon.cpp b/src/core/contractors/codac2_CtcPolygon.cpp new file mode 100644 index 00000000..e775b8d8 --- /dev/null +++ b/src/core/contractors/codac2_CtcPolygon.cpp @@ -0,0 +1,45 @@ +/** + * CtcPolygon.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Benoit Desrochers + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include "codac2_CtcPolygon.h" +#include "codac2_CtcUnion.h" +#include "codac2_CtcSegment.h" +#include "codac2_geometry.h" + +using namespace std; + +namespace codac2 +{ + CtcPolygon::CtcPolygon(const Polygon& p) + : CtcCtcBoundary( + + // Contractor on the boundary + [p] + { + CtcUnion ctc_segments(2); + for(const auto& edge_i : p.edges()) + ctc_segments |= CtcSegment(edge_i[0],edge_i[1]); + return ctc_segments; + }(), + + // Tests if a point of a box is inside the polygon + [p](const Vector& x) -> BoolInterval + { + assert_release(x.size() == 2); + return p.contains(x); + } + ) + { } + + void CtcPolygon::contract(IntervalVector& x) const + { + CtcCtcBoundary::contract(x); + } +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcPolygon.h b/src/core/contractors/codac2_CtcPolygon.h new file mode 100644 index 00000000..eeb632f8 --- /dev/null +++ b/src/core/contractors/codac2_CtcPolygon.h @@ -0,0 +1,25 @@ +/** + * \file codac2_CtcPolygon.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Benoit Desrochers + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_Polygon.h" +#include "codac2_CtcCtcBoundary.h" +#include "codac2_CtcUnion.h" + +namespace codac2 +{ + class CtcPolygon : public CtcCtcBoundary + { + public: + + CtcPolygon(const Polygon& p); + void contract(IntervalVector& x) const; + }; +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcProj.cpp b/src/core/contractors/codac2_CtcProj.cpp new file mode 100644 index 00000000..146ea1c5 --- /dev/null +++ b/src/core/contractors/codac2_CtcProj.cpp @@ -0,0 +1,57 @@ +/** + * codac2_CtcProj.cp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_CtcProj.h" + +using namespace std; +using namespace codac2; + +namespace codac2 +{ + void CtcProj::contract(IntervalVector& x) const + { + contract(x, _default_eps); + } + + void CtcProj::contract(IntervalVector& x, double eps) const + { + assert_release(eps > 0.); + assert_release(x.size() == this->size()); + + list l_stack { cart_prod_xy(x,_y) }; + x.set_empty(); + + // The stack allows to explore along the y-column to be projected, + // performing bisections along y if necesary + while(!l_stack.empty()) + { + auto w = l_stack.front(); // one box-guess in the projected column + l_stack.pop_front(); + + IntervalVector w_ctc(w); + _ctc.front().contract(w_ctc); + + // If the guess box may contain some values + if(!w_ctc.is_empty()) + { + // If the current guess w is not a leaf, proceed to a bisection of the guess + auto y = extract_y(w); + if(y.max_diam() > eps) + { + auto b = w.bisect(y_max_diam_index(y)); + l_stack.push_back(b.first); + l_stack.push_back(b.second); + } + + else + x |= extract_x(w_ctc); + } + } + } +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcProj.h b/src/core/contractors/codac2_CtcProj.h new file mode 100644 index 00000000..00dff8a3 --- /dev/null +++ b/src/core/contractors/codac2_CtcProj.h @@ -0,0 +1,48 @@ +/** + * \file codac2_CtcProj.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include "codac2_Collection.h" +#include "codac2_template_tools.h" +#include "codac2_ProjBase.h" + +namespace codac2 +{ + class CtcProj : public Ctc, protected ProjBase + { + public: + + template + requires IsCtcBaseOrPtr + CtcProj(const C& c, const std::vector& proj_indices, double default_eps = 0.01) + : CtcProj(c, proj_indices, IntervalVector(size_of(c)-proj_indices.size()), default_eps) + { } + + template + requires IsCtcBaseOrPtr + CtcProj(const C& c, const std::vector& proj_indices, const IntervalVector& y, double default_eps = 0.01) + : Ctc(proj_indices.size()), ProjBase(proj_indices,y,default_eps), _ctc(c) + { + assert_release(_y.size() == size_of(c)-(Index)_xi.size()); + assert_release(*min_element(_xi.begin(),_xi.end()) >= 0); + assert_release(*max_element(_xi.begin(),_xi.end()) < size_of(c)); + assert_release(size_of(c) >= (Index)_xi.size() && "cannot compute a projection of a set into a superset"); + assert_release(default_eps > 0.); + } + + void contract(IntervalVector& x) const; + void contract(IntervalVector& x, double eps) const; + + protected: + + const Collection> _ctc; + }; +} \ No newline at end of file diff --git a/src/core/contractors/codac2_CtcSegment.cpp b/src/core/contractors/codac2_CtcSegment.cpp index 84764630..6ec82cbd 100644 --- a/src/core/contractors/codac2_CtcSegment.cpp +++ b/src/core/contractors/codac2_CtcSegment.cpp @@ -9,7 +9,6 @@ #include "codac2_CtcSegment.h" #include "codac2_directed_ctc.h" -#include "codac2_arithmetic.h" using namespace std; using namespace codac2; diff --git a/src/core/contractors/codac2_CtcUnion.h b/src/core/contractors/codac2_CtcUnion.h index 2deff192..91dfdacc 100644 --- a/src/core/contractors/codac2_CtcUnion.h +++ b/src/core/contractors/codac2_CtcUnion.h @@ -21,7 +21,7 @@ namespace codac2 { public: - explicit CtcUnion(size_t n) + explicit CtcUnion(Index n) : Ctc,X>(n) { if constexpr(std::is_same_v) diff --git a/src/core/contractors/codac2_directed_ctc.cpp b/src/core/contractors/codac2_directed_ctc.cpp index b4132bc1..db25b48a 100644 --- a/src/core/contractors/codac2_directed_ctc.cpp +++ b/src/core/contractors/codac2_directed_ctc.cpp @@ -9,7 +9,6 @@ #include #include "codac2_directed_ctc.h" -#include "codac2_MatrixBase.h" #include "codac2_IntervalVector.h" #include "codac2_IntervalMatrix.h" @@ -33,7 +32,7 @@ using namespace codac2; }; } - void AddOp::bwd(const Interval& y, Interval& x1) + void AddOp::bwd([[maybe_unused]] const Interval& y, [[maybe_unused]] Interval& x1) { } IntervalVector AddOp::fwd(const IntervalVector& x1) @@ -51,7 +50,7 @@ using namespace codac2; }; } - void AddOp::bwd(const IntervalVector& y, IntervalVector& x1) + void AddOp::bwd([[maybe_unused]] const IntervalVector& y, [[maybe_unused]] IntervalVector& x1) { assert(y.size() == x1.size()); } @@ -71,7 +70,7 @@ using namespace codac2; }; } - void AddOp::bwd(const IntervalMatrix& y, IntervalMatrix& x1) + void AddOp::bwd([[maybe_unused]] const IntervalMatrix& y, [[maybe_unused]] IntervalMatrix& x1) { assert(y.size() == x1.size()); } @@ -108,7 +107,7 @@ using namespace codac2; VectorOpValue AddOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2) { - assert(x1.da.nb_rows() == x2.da.nb_rows() && x1.da.nb_cols() == x2.da.nb_cols()); + assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { fwd(x1.m, x2.m), fwd(x1.a, x2.a), @@ -120,7 +119,7 @@ using namespace codac2; void AddOp::bwd(const IntervalVector& y, IntervalVector& x1, IntervalVector& x2) { assert(y.size() == x1.size() && y.size() == x2.size()); - for(size_t i = 0 ; i < y.size() ; i++) + for(Index i = 0 ; i < y.size() ; i++) AddOp::bwd(y[i], x1[i], x2[i]); } @@ -143,8 +142,8 @@ using namespace codac2; void AddOp::bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2) { assert(y.size() == x1.size() && y.size() == x2.size()); - for(size_t i = 0 ; i < y.size() ; i++) - AddOp::bwd(*(y._e.data()+i), *(x1._e.data()+i), *(x2._e.data()+i)); + for(Index i = 0 ; i < y.size() ; i++) + AddOp::bwd(*(y.data()+i), *(x1.data()+i), *(x2.data()+i)); } @@ -189,7 +188,7 @@ using namespace codac2; void SubOp::bwd(const IntervalVector& y, IntervalVector& x1) { assert(y.size() == x1.size()); - for(size_t i = 0 ; i < y.size() ; i++) + for(Index i = 0 ; i < y.size() ; i++) bwd(y[i], x1[i]); } @@ -211,8 +210,8 @@ using namespace codac2; void SubOp::bwd(const IntervalMatrix& y, IntervalMatrix& x1) { assert(y.size() == x1.size()); - for(size_t i = 0 ; i < y.size() ; i++) - SubOp::bwd(*(y._e.data()+i), *(x1._e.data()+i)); + for(Index i = 0 ; i < y.size() ; i++) + SubOp::bwd(*(y.data()+i), *(x1.data()+i)); } @@ -225,7 +224,7 @@ using namespace codac2; ScalarOpValue SubOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) { - assert(x1.da.nb_rows() == x2.da.nb_rows() && x1.da.nb_cols() == x2.da.nb_cols()); + assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { fwd(x1.m, x2.m), fwd(x1.a, x2.a), @@ -247,7 +246,7 @@ using namespace codac2; VectorOpValue SubOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2) { - assert(x1.da.nb_rows() == x2.da.nb_rows() && x1.da.nb_cols() == x2.da.nb_cols()); + assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { fwd(x1.m, x2.m), fwd(x1.a, x2.a), @@ -259,7 +258,7 @@ using namespace codac2; void SubOp::bwd(const IntervalVector& y, IntervalVector& x1, IntervalVector& x2) { assert(y.size() == x1.size() && y.size() == x2.size()); - for(size_t i = 0 ; i < y.size() ; i++) + for(Index i = 0 ; i < y.size() ; i++) bwd(y[i], x1[i], x2[i]); } @@ -271,7 +270,7 @@ using namespace codac2; MatrixOpValue SubOp::fwd(const MatrixOpValue& x1, const MatrixOpValue& x2) { - assert(x1.a.nb_cols() == x2.a.nb_cols() && x1.a.nb_rows() == x2.a.nb_rows()); + assert(x1.a.cols() == x2.a.cols() && x1.a.rows() == x2.a.rows()); return { fwd(x1.m, x2.m), fwd(x1.a, x2.a), @@ -283,8 +282,8 @@ using namespace codac2; void SubOp::bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2) { assert(y.size() == x1.size() && y.size() == x2.size()); - for(size_t i = 0 ; i < y.size() ; i++) - SubOp::bwd(*(y._e.data()+i), *(x1._e.data()+i), *(x2._e.data()+i)); + for(Index i = 0 ; i < y.size() ; i++) + SubOp::bwd(*(y.data()+i), *(x1.data()+i), *(x2.data()+i)); } @@ -297,11 +296,11 @@ using namespace codac2; ScalarOpValue MulOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) { - assert(x1.da.nb_rows() == 1); - assert(x1.da.nb_rows() == x2.da.nb_rows() && x1.da.nb_cols() == x2.da.nb_cols()); + assert(x1.da.rows() == 1); + assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); - IntervalMatrix d(1,x1.da.nb_cols()); - for(size_t i = 0 ; i < d.size() ; i++) + IntervalMatrix d(1,x1.da.cols()); + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)*x2.a + x1.a*x2.da(0,i); return { @@ -324,13 +323,13 @@ using namespace codac2; VectorOpValue MulOp::fwd(const ScalarOpValue& x1, const VectorOpValue& x2) { - assert(x1.da.nb_rows() == 1); - assert(x1.da.nb_cols() == x2.da.nb_cols()); - assert(x2.a.size() == x2.da.nb_rows()); + assert(x1.da.rows() == 1); + assert(x1.da.cols() == x2.da.cols()); + assert(x2.a.size() == x2.da.rows()); - IntervalMatrix d(x2.da.nb_rows(),x2.da.nb_cols()); - for(size_t i = 0 ; i < d.nb_rows() ; i++) - for(size_t j = 0 ; j < d.nb_cols() ; j++) + IntervalMatrix d(x2.da.rows(),x2.da.cols()); + for(Index i = 0 ; i < d.rows() ; i++) + for(Index j = 0 ; j < d.cols() ; j++) d(i,j) = x1.da(0,j)*x2.a[i]+x1.a*x2.da(i,j); return { @@ -344,7 +343,7 @@ using namespace codac2; void MulOp::bwd(const IntervalVector& y, Interval& x1, IntervalVector& x2) { assert(y.size() == x2.size()); - for(size_t i = 0 ; i < x2.size() ; i++) + for(Index i = 0 ; i < x2.size() ; i++) bwd_mul(y[i], x1, x2[i]); } @@ -363,9 +362,51 @@ using namespace codac2; MulOp::bwd(y, x2, x1); } + Interval MulOp::fwd(const IntervalRow& x1, const IntervalVector& x2) + { + assert(x1.size() == x2.size()); + Interval s(0.); + for(Index i = 0 ; i < x1.size() ; i++) + s += x1[i]*x2[i]; + return s; + } + + //ScalarOpValue MulOp::fwd(const RowOpValue& x1, const VectorOpValue& x2) + //{ + // // RowOpValue not yet defined + //} + + void MulOp::bwd(const Interval& y, IntervalRow& x1, IntervalVector& x2) + { + assert(x1.size() == x2.size()); + + const Index n = x1.size(); + vector sums(n), prods(n); + + // Forward propagation + + for(Index i = 0 ; i < n ; i++) + { + prods[i] = x1[i]*x2[i]; + sums[i] = prods[i]; + if(i > 0) sums[i] += sums[i-1]; + } + + // Backward propagation + + sums[n-1] &= y; + + for(Index i = n-1 ; i >= 0 ; i--) + { + if(i > 0) AddOp::bwd(sums[i],sums[i-1],prods[i]); + else prods[0] &= sums[0]; + MulOp::bwd(prods[i],x1[i],x2[i]); + } + } + IntervalVector MulOp::fwd(const IntervalMatrix& x1, const IntervalVector& x2) { - assert(x1.nb_cols() == x2.size()); + assert(x1.cols() == x2.size()); return x1 * x2; } @@ -374,7 +415,7 @@ using namespace codac2; return { fwd(x1.a, /* <<----- x1.m */ x2.m), fwd(x1.a, x2.a), - IntervalMatrix::zeros(x1.a.nb_rows(),x1.a.nb_cols()), // todo + IntervalMatrix::zero(x1.a.rows(),x1.a.cols()), // todo x1.def_domain && x2.def_domain }; } @@ -382,20 +423,58 @@ using namespace codac2; #include "codac2_linear_ctc.h" #include "codac2_GaussJordan.h" + //#include "codac2_ibex.h" + void MulOp::bwd(const IntervalVector& y, IntervalMatrix& x1, IntervalVector& x2) { - assert(x1.nb_rows() == y.size()); - assert(x1.nb_cols() == x2.size()); + assert(x1.rows() == y.size()); + assert(x1.cols() == x2.size()); - /*if(x1.is_squared()) // not working for any x1 + /*if(x1.is_squared()) // not working for any squared x1 { CtcGaussElim ctc_ge; CtcLinearPrecond ctc_gep(ctc_ge); IntervalVector y_(y); ctc_gep.contract(x1,x2,y_); + }*/ + + if(x1.rows() > x1.cols()) + { + #if 0 // IBEX version + ibex::IntervalVector ibex_y(to_ibex(y)), ibex_x2(to_ibex(x2)); + ibex::IntervalMatrix ibex_x1(to_ibex(x1)); + ibex::bwd_mul(ibex_y, ibex_x1, ibex_x2, 0.05); + x1 &= to_codac(ibex_x1); + x2 &= to_codac(ibex_x2); + #else + + Index last_row = 0; + Index i = 0; + + do + { + double vol_x2 = x2.volume(); + IntervalRow row_i = x1.row(i); + MulOp::bwd(y[i],row_i,x2); + + if(row_i.is_empty()) + { + x1.set_empty(); + return; + } + + else + x1.row(i) = row_i; + + if(x2.volume()/vol_x2 < 0.98) + last_row = i; + i = (i+1)%y.size(); + } while(i != last_row); + + #endif } - else*/ + else { IntervalMatrix Q = gauss_jordan(x1.mid()); IntervalVector b_tilde = Q*y; @@ -403,20 +482,17 @@ using namespace codac2; for(int a = 0 ; a < 1 ; a++) { - for(size_t i = 0 ; i < x2.size() ; i++) + for(Index i = 0 ; i < x2.size() ; i++) { - for(size_t k = 0 ; k < b_tilde.size() ; k++) + for(Index k = 0 ; k < b_tilde.size() ; k++) { Interval u = b_tilde[k]; - for(size_t j = 0 ; j < x2.size() ; j++) + for(Index j = 0 ; j < x2.size() ; j++) if(i != j) u -= x2[j]*A_tilde(k,j); - if(A_tilde(k,i).contains(0.)) - continue; - - x2[i] &= u / A_tilde(k,i); + MulOp::bwd(u, x2[i], A_tilde(k,i)); } } } @@ -436,7 +512,7 @@ using namespace codac2; assert(x1.da.size() == x2.da.size()); IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = (x1.da(0,i)*x2.a-x1.a*x2.da(0,i))/sqr(x2.a); return { @@ -475,7 +551,7 @@ using namespace codac2; void DivOp::bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2) { assert(x1.size() == y.size()); - for(size_t i = 0 ; i < x1.size() ; i++) + for(Index i = 0 ; i < x1.size() ; i++) bwd_div(y[i], x1[i], x2); } @@ -490,7 +566,7 @@ using namespace codac2; ScalarOpValue PowOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x2.a*x1.da(0,i)*pow(x1.a,x2.a-1.); return { @@ -516,10 +592,10 @@ using namespace codac2; ScalarOpValue SqrOp::fwd(const ScalarOpValue& x1) { - assert(x1.da.nb_rows() == 1); + assert(x1.da.rows() == 1); - IntervalMatrix d(1,x1.da.nb_cols()); - for(size_t i = 0 ; i < d.size() ; i++) + IntervalMatrix d(1,x1.da.cols()); + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = 2.*x1.a*x1.da(0,i); return { @@ -546,7 +622,7 @@ using namespace codac2; ScalarOpValue SqrtOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)/(2.*sqrt(x1.a)); return { @@ -575,7 +651,7 @@ using namespace codac2; ScalarOpValue ExpOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)*exp(x1.a); return { @@ -602,7 +678,7 @@ using namespace codac2; ScalarOpValue LogOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)/x1.a; return { @@ -631,7 +707,7 @@ using namespace codac2; ScalarOpValue CosOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = -sin(x1.a)*x1.da(0,i); return { @@ -658,7 +734,7 @@ using namespace codac2; ScalarOpValue SinOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = cos(x1.a)*x1.da(0,i); return { @@ -685,7 +761,7 @@ using namespace codac2; ScalarOpValue TanOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)/sqr(cos(x1.a)); return { @@ -712,7 +788,7 @@ using namespace codac2; ScalarOpValue AcosOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = -x1.da(0,i)/sqrt(1.-sqr(x1.a)); return { @@ -741,7 +817,7 @@ using namespace codac2; ScalarOpValue AsinOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)/sqrt(1.-sqr(x1.a)); return { @@ -770,7 +846,7 @@ using namespace codac2; ScalarOpValue AtanOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)/(1.+sqr(x1.a)); return { @@ -796,11 +872,11 @@ using namespace codac2; ScalarOpValue Atan2Op::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) { - assert(x1.da.nb_rows() == 1); - assert(x1.da.nb_rows() == x2.da.nb_rows() && x1.da.nb_cols() == x2.da.nb_cols()); + assert(x1.da.rows() == 1); + assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); - IntervalMatrix d(1,x1.da.nb_cols()); - for(size_t i = 0 ; i < d.size() ; i++) + IntervalMatrix d(1,x1.da.cols()); + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = (-x1.a*x2.da(0,i)/(sqr(x2.a)+sqr(x1.a)))+(x2.a*x1.da(0,i)/(sqr(x2.a)+sqr(x1.a))); return { @@ -828,7 +904,7 @@ using namespace codac2; ScalarOpValue CoshOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = sinh(x1.a)*x1.da(0,i); return { @@ -855,7 +931,7 @@ using namespace codac2; ScalarOpValue SinhOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = cosh(x1.a)*x1.da(0,i); return { @@ -882,7 +958,7 @@ using namespace codac2; ScalarOpValue TanhOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)/sqr(cosh(x1.a)); return { @@ -909,7 +985,7 @@ using namespace codac2; ScalarOpValue AbsOp::fwd(const ScalarOpValue& x1) { IntervalMatrix d(1,x1.da.size()); - for(size_t i = 0 ; i < d.size() ; i++) + for(Index i = 0 ; i < d.size() ; i++) d(0,i) = (x1.a/abs(x1.a))*x1.da(0,i); return { @@ -928,15 +1004,15 @@ using namespace codac2; // ComponentOp - Interval ComponentOp::fwd(const IntervalVector& x1, size_t i) + Interval ComponentOp::fwd(const IntervalVector& x1, Index i) { assert(i >= 0 && i < x1.size()); return x1[i]; } - ScalarOpValue ComponentOp::fwd(const VectorOpValue& x1, size_t i) + ScalarOpValue ComponentOp::fwd(const VectorOpValue& x1, Index i) { - assert(i >= 0 && i < x1.a.nb_rows()); + assert(i >= 0 && i < x1.a.rows()); return { fwd(x1.m,i), fwd(x1.a,i), @@ -945,7 +1021,7 @@ using namespace codac2; }; } - void ComponentOp::bwd(const Interval& y, IntervalVector& x1, size_t i) + void ComponentOp::bwd(const Interval& y, IntervalVector& x1, Index i) { assert(i >= 0 && i < x1.size()); x1[i] &= y; @@ -954,38 +1030,38 @@ using namespace codac2; // SubvectorOp - IntervalVector SubvectorOp::fwd(const IntervalVector& x1, size_t i, size_t j) + IntervalVector SubvectorOp::fwd(const IntervalVector& x1, Index i, Index j) { assert(i >= 0 && i < x1.size() && j >= i && j < x1.size()); return x1.subvector(i,j); } - VectorOpValue SubvectorOp::fwd(const VectorOpValue& x1, size_t i, size_t j) + VectorOpValue SubvectorOp::fwd(const VectorOpValue& x1, Index i, Index j) { - assert(i >= 0 && i < x1.a.nb_rows() && j >= i && j < x1.a.nb_rows()); + assert(i >= 0 && i < x1.a.rows() && j >= i && j < x1.a.rows()); return { fwd(x1.m,i,j), fwd(x1.a,i,j), - x1.da.block(i,0,j-i+1,x1.da.nb_cols()), + x1.da.block(i,0,j-i+1,x1.da.cols()), x1.def_domain }; } - void SubvectorOp::bwd(const IntervalVector& y, IntervalVector& x1, size_t i, size_t j) + void SubvectorOp::bwd(const IntervalVector& y, IntervalVector& x1, Index i, Index j) { assert(i >= 0 && i < x1.size() && j >= i && j < x1.size()); assert(j-i < y.size()); - for(size_t k = 0 ; k < j-i+1 ; k++) + for(Index k = 0 ; k < j-i+1 ; k++) x1[i+k] &= y[k]; } // MatrixOp - void MatrixOp::fwd_i(IntervalMatrix& m, const IntervalVector& x, size_t i) + void MatrixOp::fwd_i(IntervalMatrix& m, const IntervalVector& x, Index i) { - assert(i >= 0 && i < m.nb_cols()); - m.resize(x.size(),m.nb_cols()); + assert(i >= 0 && i < m.cols()); + m.resize(x.size(),m.cols()); m.col(i) = x; } @@ -997,12 +1073,12 @@ using namespace codac2; Interval DetOp::fwd(const IntervalMatrix& x) { assert_release(x.is_squared() && "can only compute determinants for a square matrix"); - assert_release((x.nb_rows() == 1 || x.nb_rows() == 2) && "determinant not yet computable for n×n matrices, n>2"); + assert_release((x.rows() == 1 || x.rows() == 2) && "determinant not yet computable for n×n matrices, n>2"); - if(x.nb_rows() == 1) // 1×1 matrix + if(x.rows() == 1) // 1×1 matrix return x(0,0); - else if(x.nb_rows() == 2) // 2×2 matrix + else if(x.rows() == 2) // 2×2 matrix return x(0,0)*x(1,1)-x(0,1)*x(1,0); else @@ -1022,12 +1098,12 @@ using namespace codac2; void DetOp::bwd(const Interval& y, IntervalMatrix& x) { assert_release(x.is_squared() && "can only compute determinants for a square matrix"); - assert_release((x.nb_rows() == 1 || x.nb_rows() == 2) && "determinant not yet computable for n×n matrices, n>2"); + assert_release((x.rows() == 1 || x.rows() == 2) && "determinant not yet computable for n×n matrices, n>2"); - if(x.nb_rows() == 1) // 1×1 matrix + if(x.rows() == 1) // 1×1 matrix x(0,0) &= y; - else if(x.nb_rows() == 2) // 2×2 matrix + else if(x.rows() == 2) // 2×2 matrix { Interval z1 = x(0,0)*x(1,1), z2 = x(1,0)*x(0,1); SubOp::bwd(y, z1, z2); @@ -1046,14 +1122,21 @@ using namespace codac2; Interval DetOp::fwd(const IntervalVector& x1, const IntervalVector& x2) { assert_release(x1.size() == 2 && x2.size() == 2 && "determinant only computable for pairs of 2d vectors"); - return DetOp::fwd(IntervalMatrix(x1,x2)); + IntervalMatrix m(2,2); + m.col(0) = x1; m.col(1) = x2; + return DetOp::fwd(m); } ScalarOpValue DetOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2) { + IntervalMatrix m(2,2); + m.col(0) = x1.m; m.col(1) = x2.m; + IntervalMatrix a(2,2); + a.col(0) = x1.a; a.col(1) = x2.a; + return { - fwd(IntervalMatrix(x1.m,x2.m)), - fwd(IntervalMatrix(x1.a,x2.a)), + fwd(m), + fwd(a), IntervalMatrix(0,0), // not supported yet for auto diff x1.def_domain && x2.def_domain }; @@ -1074,14 +1157,21 @@ using namespace codac2; Interval DetOp::fwd(const IntervalVector& x1, const IntervalVector& x2, const IntervalVector& x3) { assert_release(x1.size() == 3 && x2.size() == 3 && x3.size() == 3 && "determinant only computable for triplet of 3d vectors"); - return DetOp::fwd(IntervalMatrix(x1,x2,x3)); + IntervalMatrix m(3,3); + m.col(0) = x1; m.col(1) = x2; m.col(2) = x3; + return DetOp::fwd(m); } ScalarOpValue DetOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2, const VectorOpValue& x3) { + IntervalMatrix m(3,3); + m.col(0) = x1.m; m.col(1) = x2.m; m.col(2) = x3.m; + IntervalMatrix a(3,3); + a.col(0) = x1.a; a.col(1) = x2.a; a.col(2) = x3.a; + return { - fwd(IntervalMatrix(x1.m,x2.m,x3.m)), - fwd(IntervalMatrix(x1.a,x2.a,x3.a)), + fwd(m), + fwd(a), IntervalMatrix(0,0), // not supported yet for auto diff x1.def_domain && x2.def_domain && x3.def_domain }; @@ -1090,7 +1180,10 @@ using namespace codac2; void DetOp::bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2, IntervalVector& x3) { assert_release(x1.size() == 3 && x2.size() == 3 && x3.size() == 3 && "determinant only computable for triplet of 3d vectors"); - IntervalMatrix m(x1,x2,x3); + + IntervalMatrix m(3,3); + m.col(0) = x1; m.col(1) = x2; m.col(2) = x3; + DetOp::bwd(y,m); x1 &= m.col(0); x2 &= m.col(1); diff --git a/src/core/contractors/codac2_directed_ctc.h b/src/core/contractors/codac2_directed_ctc.h index 4dc4f0c9..4b9ad460 100644 --- a/src/core/contractors/codac2_directed_ctc.h +++ b/src/core/contractors/codac2_directed_ctc.h @@ -11,8 +11,8 @@ #include #include "codac2_analytic_values.h" -#include "codac2_arithmetic.h" #include "codac2_template_tools.h" +#include "codac2_IntervalRow.h" namespace codac2 { @@ -88,6 +88,10 @@ namespace codac2 static VectorOpValue fwd(const VectorOpValue& x1, const ScalarOpValue& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2); + static Interval fwd(const IntervalRow& x1, const IntervalVector& x2); + //static ScalarOpValue fwd(const RowOpValue& x1, const VectorOpValue& x2); // RowOpValue not yet defined + static void bwd(const Interval& y, IntervalRow& x1, IntervalVector& x2); + static IntervalVector fwd(const IntervalMatrix& x1, const IntervalVector& x2); static VectorOpValue fwd(const MatrixOpValue& x1, const VectorOpValue& x2); static void bwd(const IntervalVector& y, IntervalMatrix& x1, IntervalVector& x2); @@ -218,16 +222,16 @@ namespace codac2 struct ComponentOp { - static Interval fwd(const IntervalVector& x1, size_t i); - static ScalarOpValue fwd(const VectorOpValue& x1, size_t i); - static void bwd(const Interval& y, IntervalVector& x1, size_t i); + static Interval fwd(const IntervalVector& x1, Index i); + static ScalarOpValue fwd(const VectorOpValue& x1, Index i); + static void bwd(const Interval& y, IntervalVector& x1, Index i); }; struct SubvectorOp { - static IntervalVector fwd(const IntervalVector& x1, size_t i, size_t j); - static VectorOpValue fwd(const VectorOpValue& x1, size_t i, size_t j); - static void bwd(const IntervalVector& y, IntervalVector& x1, size_t i, size_t j); + static IntervalVector fwd(const IntervalVector& x1, Index i, Index j); + static VectorOpValue fwd(const VectorOpValue& x1, Index i, Index j); + static void bwd(const IntervalVector& y, IntervalVector& x1, Index i, Index j); }; struct VectorOp @@ -243,8 +247,8 @@ namespace codac2 requires (std::is_base_of_v && ...) static VectorOpValue fwd(const X&... x) { - IntervalMatrix d(sizeof...(X),std::get<0>(std::tie(x...)).da.nb_cols()); - size_t i = 0; + IntervalMatrix d(sizeof...(X),std::get<0>(std::tie(x...)).da.cols()); + Index i = 0; ((d.row(i++) = x.da), ...); bool def_domain = true; @@ -262,14 +266,14 @@ namespace codac2 requires (std::is_base_of_v && ...) static void bwd(const IntervalVector& y, X&... x) { - size_t i = 0; + Index i = 0; ((x &= y[i++]), ...); } }; struct MatrixOp { - static void fwd_i(IntervalMatrix& m, const IntervalVector& x, size_t i); + static void fwd_i(IntervalMatrix& m, const IntervalVector& x, Index i); template requires (std::is_base_of_v && ...) @@ -277,7 +281,7 @@ namespace codac2 { throw std::runtime_error("MatrixOp not fully implemented yet"); IntervalMatrix m(1, sizeof...(X)); - size_t i = 0; + Index i = 0; (MatrixOp::fwd_i(m, x, i++), ...); return m; } @@ -300,7 +304,7 @@ namespace codac2 static void bwd(const IntervalMatrix& y, X&... x) { throw std::runtime_error("MatrixOp not fully implemented yet"); - size_t i = 0; + Index i = 0; ((x &= y.col(i++)), ...); } }; diff --git a/src/core/contractors/codac2_linear_ctc.cpp b/src/core/contractors/codac2_linear_ctc.cpp index 69842be5..30415f1c 100644 --- a/src/core/contractors/codac2_linear_ctc.cpp +++ b/src/core/contractors/codac2_linear_ctc.cpp @@ -15,29 +15,29 @@ using namespace codac2; void CtcGaussElim::contract(IntervalMatrix& A, IntervalVector& x, IntervalVector& b) const { - assert_release(A.is_squared() && A.nb_rows() == x.size() && A.nb_rows() == b.size()); + assert_release(A.is_squared() && A.rows() == x.size() && A.rows() == b.size()); IntervalMatrix A_ = A; IntervalVector b_ = b; - size_t n = A_.nb_rows(); - for(size_t i = 0 ; i < n ; i++) + Index n = A_.rows(); + for(Index i = 0 ; i < n ; i++) if(A_(i,i).contains(0.)) return; - for(size_t i = 0 ; i < n-1 ; i++) - for(size_t j = i+1 ; j < n ; j++) + for(Index i = 0 ; i < n-1 ; i++) + for(Index j = i+1 ; j < n ; j++) { Interval aj = A_(j,i)/A_(i,i); b_[j] -= aj*b_[i]; - for(size_t k = i+1 ; k < n ; k++) + for(Index k = i+1 ; k < n ; k++) A_(j,k) -= aj*A_(i,k); } for(int i = n-1 ; i >= 0 ; i--) { Interval sum = 0.; - for(size_t j = i+1 ; j < n ; j++) + for(Index j = i+1 ; j < n ; j++) sum += A_(i,j)*x[j]; x[i] &= (b_[i]-sum)/A_(i,i); } @@ -45,10 +45,10 @@ void CtcGaussElim::contract(IntervalMatrix& A, IntervalVector& x, IntervalVector void CtcGaussSeidel::contract(IntervalMatrix& A, IntervalVector& x, IntervalVector& b) const { - assert_release(A.is_squared() && A.nb_rows() == x.size() && A.nb_rows() == b.size()); + assert_release(A.is_squared() && A.rows() == x.size() && A.rows() == b.size()); auto ext_diag = A; - for(size_t i = 0 ; i < A.nb_rows() ; i++) + for(Index i = 0 ; i < A.rows() ; i++) ext_diag(i,i) = 0.; - x &= IntervalVector(A._e.diagonal().asDiagonal().inverse()*(b._e-ext_diag._e*x._e)); + x &= IntervalVector(A.diagonal().asDiagonal().inverse()*(b-ext_diag*x)); } \ No newline at end of file diff --git a/src/core/contractors/codac2_linear_ctc.h b/src/core/contractors/codac2_linear_ctc.h index f1c96f36..a402706e 100644 --- a/src/core/contractors/codac2_linear_ctc.h +++ b/src/core/contractors/codac2_linear_ctc.h @@ -11,9 +11,11 @@ #pragma once #include -#include "codac2_arithmetic.h" #include "codac2_Collection.h" #include "codac2_template_tools.h" +#include "codac2_Matrix.h" +#include "codac2_IntervalVector.h" +#include "codac2_IntervalMatrix.h" namespace codac2 { @@ -177,17 +179,17 @@ namespace codac2 */ void contract(IntervalMatrix& A, IntervalVector& x, IntervalVector& b) const { - assert_release(A.is_squared() && A.nb_rows() == x.size() && A.nb_rows() == b.size()); + assert_release(A.is_squared() && A.rows() == x.size() && A.rows() == b.size()); - auto A0 = A.mid(); - auto A0_inv = A0._e.inverse(); - IntervalMatrix Ap(A0_inv.template cast()*A._e); - IntervalVector bp(A0_inv.template cast()*b._e); + IntervalMatrix A0 = A.mid(); + IntervalMatrix A0_inv = A.mid().inverse().template cast(); + IntervalMatrix Ap = A0_inv*A; + IntervalVector bp = A0_inv*b; _ctc_no_precond.front().contract(Ap,x,bp); - b &= IntervalVector(A0._e.template cast()*bp._e); - A &= IntervalMatrix(A0._e.template cast()*Ap._e); + b &= A0*bp; + A &= A0*Ap; } virtual std::shared_ptr copy() const diff --git a/src/core/domains/codac2_Domain.h b/src/core/domains/codac2_Domain.h index b9192964..65ec2d38 100644 --- a/src/core/domains/codac2_Domain.h +++ b/src/core/domains/codac2_Domain.h @@ -36,6 +36,8 @@ namespace codac2 virtual V lb() const = 0; virtual V ub() const = 0; virtual V mid() const = 0; + virtual V mag() const = 0; + virtual V mig() const = 0; virtual V rad() const = 0; virtual V diam() const = 0; virtual double volume() const = 0; @@ -56,4 +58,4 @@ namespace codac2 virtual bool is_strict_superset(const T& x) const = 0; }; -} \ No newline at end of file +} diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 04d0afe7..f7102e3a 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -7,25 +7,27 @@ * \license GNU Lesser General Public License (LGPL) */ -#include #include "codac2_Ellipsoid.h" #include "codac2_template_tools.h" +#include "codac2_Inversion.h" +#include using namespace std; -using namespace codac2; +using codac2::Vector; namespace codac2 { - Ellipsoid::Ellipsoid(size_t n) - : mu(Vector(n)), G(Matrix(n, n)) { + Ellipsoid::Ellipsoid(Index n) + : mu(Vector::zero(n)), G(Matrix::zero(n, n)) { assert_release(n > 0); } Ellipsoid::Ellipsoid(const Vector &mu_, const Matrix &G_) : mu(mu_), G(G_) { - assert_release(mu_.size() == G_.nb_cols() && G_.is_squared()); + assert_release(mu_.size() == G_.cols() && G_.is_squared()); } - size_t Ellipsoid::size() const { + Index Ellipsoid::size() const { + assert(mu.size() == G.cols() && G.is_squared()); return mu.size(); } @@ -33,14 +35,14 @@ namespace codac2 { { auto xi = Vector::random(this->size()); double rand_norm = ((double) std::rand() / (RAND_MAX)); - return this->mu._e + this->G._e * xi._e / xi._e.norm() * rand_norm; + return this->mu + this->G * xi / xi.norm() * rand_norm; } IntervalVector Ellipsoid::hull_box() const { IntervalVector hull(size()); - for(size_t i=0; i< size(); i++){ - double m = G._e.col(i).norm(); + for(Index i=0; i< size(); i++){ + double m = G.col(i).norm(); hull[i] = Interval(-m, m); } return hull; @@ -48,25 +50,25 @@ namespace codac2 { BoolInterval Ellipsoid::is_concentric_subset(const Ellipsoid& e) const { - size_t n = size(); + Index n = size(); assert_release(n == e.size()); - if((mu._e - e.mu._e).norm() > 1e-10) // check if the centers are the same + if((mu - e.mu).norm() > 1e-10) // check if the centers are the same return BoolInterval::FALSE; // not concentric auto I = Matrix::eye(n,n); - auto G2_inv = e.G._e.inverse(); - IntervalMatrix D(I._e - G._e.transpose() * G2_inv.transpose() * G2_inv * G._e); + auto G2_inv = e.G.inverse(); + IntervalMatrix D(I - G.transpose() * G2_inv.transpose() * G2_inv * G); // cholesky decomposition of D = L*L^T IntervalMatrix L(n,n); // matrix of the Cholesky decomposition - for (size_t j = 0; j < n; j++) // for every column + for (Index j = 0; j < n; j++) // for every column { // diagonal element Interval s = 0.; - for (size_t k = 0; k < j; k++) + for (Index k = 0; k < j; k++) s += L(j, k) * L(j, k); Interval u = D(j, j) - s; if (u.lb() < 0) { @@ -75,11 +77,11 @@ namespace codac2 { L(j,j) = sqrt(u); // then the rest of the column - for (size_t i = j + 1; isize()); - assert( (v._e.transpose()*u._e).norm() == 0); // u & v orthogonal + assert_release( d.size() == v.size()); + assert_release( d.size() == u.size()); + assert_release( d.size() == this->size()); + assert_release( (v.transpose()*u).norm() == 0); // u & v orthogonal // Normalized Projection matrix // the plane (d,u,v) is also the affine plan {x|x=d+Tt} with T = [u,v] @@ -102,127 +104,121 @@ namespace codac2 { T.col(0) = v/v.norm(); T.col(1) = u/u.norm(); - auto TTG = T._e.transpose() * this->G._e; - Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); - Matrix U(bdcsvd.matrixU()); - Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); - this->G = U._e * E._e; - this->mu = T._e.transpose() * (d._e + T._e * T._e.transpose() * (this->mu._e - d._e)); + auto TTG = T.transpose() * this->G; + Eigen::BDCSVD bdcsvd(TTG); + auto U = bdcsvd.matrixU(); + auto E = bdcsvd.singularValues().asDiagonal(); + + return { + T.transpose() * (d + T * T.transpose() * (this->mu - d)), + U * E + }; } Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2) { assert_release(e1.size() == e2.size()); - //if(e1.is_unbounded() || e2.is_unbounded()) - // return Ellipsoid(e1.size()); - - //if(e1.is_empty() || e2.is_empty()) - // return Ellipsoid::empty(e1.size()); - - auto Q1 = e1.G._e * e1.G._e.transpose(); - auto Q2 = e2.G._e * e2.G._e.transpose(); + auto Q1 = e1.G * e1.G.transpose(); + auto Q2 = e2.G * e2.G.transpose(); double beta = std::sqrt(Q1.trace() / Q2.trace()); return { - e1.mu._e + e2.mu._e, // mu + e1.mu + e2.mu, // mu ((1. + (1. / beta)) * Q1 + (1. + beta) * Q2).sqrt() // G }; } Ellipsoid unreliable_linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { assert_release(A.is_squared()); - assert_release(e.size() == A.nb_cols()); - assert_release(b.size() == A.nb_rows()); + assert_release(e.size() == A.cols()); + assert_release(b.size() == A.rows()); return { - A._e * e.mu._e + b._e, // mu - A._e * e.G._e // G + A * e.mu + b, // mu + A * e.G // G }; } Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { - size_t n = e.size(); + Index n = e.size(); assert_release(A.is_squared()); - assert_release(n == A.nb_cols()); + assert_release(n == A.cols()); assert_release(n == b.size()); Ellipsoid e_res = unreliable_linear_mapping(e, A, b); - auto e_mu_ = e.mu._e.template cast(); - auto e_res_mu_ = e_res.mu._e.template cast(); - auto e_res_G_ = e_res.G._e.template cast(); - auto e_G_ = e.G._e.template cast(); - auto A_ = A._e.template cast(); - auto b_ = b._e.template cast(); - IntervalVector unit_box_(n, {-1,1}); + auto e_mu_ = e.mu.template cast(); + auto e_res_mu_ = e_res.mu.template cast(); + auto e_res_G_ = e_res.G.template cast(); + auto e_G_ = e.G.template cast(); + auto A_ = A.template cast(); + auto b_ = b.template cast(); + IntervalVector unit_box_ = IntervalVector::constant(n, {-1,1}); // compute rounding error as a small box auto mu_res_guaranteed = A_ * e_mu_ + b_; auto G_res_guaranteed = A_ * e_G_; auto error_box_ = mu_res_guaranteed - e_res_mu_ + - (G_res_guaranteed - e_res_G_) * unit_box_._e; + (G_res_guaranteed - e_res_G_) * unit_box_; double rho = error_box_.norm().ub(); // max radius of error_box - Ellipsoid elli_error(Vector::zeros(n), + Ellipsoid elli_error(Vector::zero(n), Matrix::eye(n,n) * rho); // = rho*unit_ball return e_res + elli_error; } Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig, const Vector& q) { - size_t n = G.nb_cols(); + Index n = G.cols(); assert(G.is_squared() && J.is_squared() && J_box.is_squared()); - assert(n == J.nb_cols() && n == J_box.nb_cols() && n == q.size()); + assert(n == J.cols() && n == J_box.cols() && n == q.size()); - Matrix JG = J * G; // note: reliability may be lost here! - IntervalMatrix G_(G); - IntervalMatrix JG_ = IntervalMatrix(JG); - IntervalVector unit_box(G.nb_rows(), Interval(-1, 1)); + auto JG = J * G; // note: reliability may be lost here! + auto G_ = G.template cast(); + IntervalVector unit_box = IntervalVector::constant(G.rows(), {-1,1}); // normal case - IntervalMatrix I_ = IntervalMatrix(Eigen::MatrixXd::Identity(G.nb_rows(),G.nb_cols())); - IntervalMatrix JG_inv_(JG._e.inverse()); // non rigourous inversion + IntervalMatrix I_ = IntervalMatrix::eye(G.rows(),G.cols()); + IntervalMatrix JG_inv_ = inverse_enclosure(JG); // rigourous inversion Matrix M(JG); - auto W = JG_inv_._e; - auto Z = I_._e; + auto W = JG_inv_; + auto Z = I_; // check for singularities - if(std::abs(JG._e.determinant()) < trig[0]) + if(std::abs(JG.determinant()) < trig[0]) { /* degenerated case from * Louedec, M., Jaulin, L., & Viel, C. (2024). * "Outer enclosures of nonlinear mapping with degenerate ellipsoids." * IFAC ACNDC June 2024*/ assert(trig.size() == 2); - assert(q.size() == G.nb_rows()); + assert(q.size() == G.rows()); // SVD decomposition of JG = U*E*V.T - Eigen::BDCSVD bdcsvd(JG._e,Eigen::ComputeFullU); - IntervalMatrix U_(bdcsvd.matrixU()); // which is also the right part - Vector Sv(bdcsvd.singularValues()); // vectors of singular values + Eigen::BDCSVD bdcsvd(JG); + auto U_ = bdcsvd.matrixU().template cast(); // which is also the right part + auto Sv = bdcsvd.singularValues(); // vectors of singular values // select new singular values - int dim = G.nb_rows(); - IntervalVector s_box(U_._e.transpose()*J_box._e*G_._e*unit_box._e); - IntervalMatrix S_(Eigen::MatrixXd::Zero(dim,dim)); // diagonal matrix of the new singular value - IntervalMatrix S_pinv_(Eigen::MatrixXd::Zero(dim,dim)); // pseudo inverse of S - for(int i=0;itrig[1]){ // normal size singular values S_(i,i) = Interval(Sv[i]); - S_pinv_(i,i) = 1/S_(i,i); }else{ // for very small singular values (0 included) use s_box - double val = s_box[i].ub(); - S_(i,i) = Interval(q[i]*val); - S_pinv_(i,i)=1/S_(i,i); + S_(i,i) = Interval(q[i])*s_box[i].ub(); } + S_pinv_(i,i) = 1./S_(i,i); } M = (U_*S_).mid(); - W = S_pinv_._e*U_._e.transpose(); - Z = W*JG_._e; + W = S_pinv_*U_.transpose(); + Z = W*JG.template cast(); } - auto b_box = (W * J_box._e * G_._e - Z) * unit_box._e; + auto b_box = (W * J_box * G_ - Z) * unit_box; double rho = b_box.norm().ub(); // max radius of b_box return (1 + rho) * M; } @@ -252,7 +248,7 @@ namespace codac2 { ostream& operator<<(ostream& os, const Ellipsoid& e) { - os << "Ellipsoid:\n" + os << "Ellipsoid " << e.size() << "d:\n" << " mu=" << e.mu << "\n" << " G=\n" << e.G; return os; diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index f2003619..a7ac9b3a 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -11,6 +11,7 @@ #include "codac2_Matrix.h" #include "codac2_Vector.h" +#include "codac2_IntervalVector.h" #include "codac2_AnalyticFunction.h" #include "codac2_BoolInterval.h" @@ -47,7 +48,7 @@ namespace codac2 * * \param n number of dimensions */ - Ellipsoid(size_t n); + Ellipsoid(Index n); /** * \brief Create an ellipsoid from a center and a shape matrix @@ -62,7 +63,7 @@ namespace codac2 * * \return number of dimensions */ - size_t size() const; + Index size() const; /** * \brief Return a random vector inside this ellipsoid @@ -95,8 +96,9 @@ namespace codac2 * \param d a point on the plane * \param v a vector of the plane * \param u a other vector of the plane, orthogonal to v + * \return the projected 2d ellipsoid */ - void projection2D(const Vector& d, const Vector& v, const Vector& u); + Ellipsoid proj_2d(const Vector& d, const Vector& v, const Vector& u) const; public: diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp index 85eca735..f14d3f2c 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp @@ -7,62 +7,77 @@ * \license GNU Lesser General Public License (LGPL) */ +#include "codac2_Ellipsoid_utils.h" #include #include -#include "codac2_Ellipsoid_utils.h" using namespace std; -using namespace codac2; +using codac2::Matrix; +using codac2::Vector; +using codac2::BoolInterval; namespace codac2 { - Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q) + Matrix solve_discrete_lyapunov(const Matrix& A, const Matrix& Q) { // implementation of the scipy solver for the discrete lyapunov equation (real matrix only) // works well under dimension 10 // https://github.com/scipy/scipy/blob/v1.14.1/scipy/linalg/_solvers.py#L235-L323 // Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0` - assert(a.nb_rows() == a.nb_cols()); - assert(a.nb_rows() == q.nb_rows()); - assert(a.nb_cols() == q.nb_cols()); + assert(A.is_squared() && Q.is_squared()); + assert(A.size() == Q.size()); - Eigen::MatrixXd lhs = Eigen::KroneckerProduct(a._e, a._e); - lhs = Eigen::MatrixXd::Identity(lhs.rows(),lhs.cols()) - lhs; - Eigen::MatrixXd x = lhs.colPivHouseholderQr().solve((Eigen::VectorXd)q._e.reshaped()); - return Matrix(x.reshaped(q.nb_rows(),q.nb_cols())); + Matrix lhs = Eigen::KroneckerProduct(A,A); + lhs = Matrix::eye(lhs.rows(),lhs.cols()) - lhs; + Matrix x = lhs.colPivHouseholderQr().solve((Vector)Q.reshaped()); + return Matrix(x.reshaped(Q.rows(),Q.cols())); } - BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) + BoolInterval stability_analysis(const AnalyticFunction &f, unsigned int alpha_max, Ellipsoid &e, Ellipsoid &e_out, bool verbose) { assert_release(f.args().size() == 1 && "f must have only one arg"); // get the Jacobian of f at the origin - int n = f.input_size(); + Index n = f.input_size(); Vector origin(Eigen::VectorXd::Zero(n)); Matrix J = f.diff(IntervalVector(origin)).mid(); // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J - Matrix P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! - Matrix G0((P._e.inverse()).sqrt()); - int alpha = 0; + auto P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! + auto G0 = P.inverse().sqrt(); + unsigned int alpha = 0; + + if(verbose) + cout << "Stability analysis:" << endl; while(alpha <= alpha_max) { - e = Ellipsoid(origin, std::pow(10,-alpha) * G0); + e = Ellipsoid(origin, std::pow(10.,-(int)alpha) * G0); e_out = nonlinear_mapping(e,f); - cout << "\nwith alpha = " << alpha << endl; - cout << "e is\n" << e << endl; - cout << "e_out is\n" << e_out << endl; + + if(verbose) + { + cout << "\t with alpha = " << alpha << endl; + cout << "\t e is\n" << e << endl; + cout << "\t e_out is\n" << e_out << endl; + } if(e_out.is_concentric_subset(e) == BoolInterval::TRUE) { - cout << "The system is stable" << endl; - cout << "Domain of attraction :\n" << e_out << endl; + if(verbose) + { + cout << "\t The system is stable" << endl; + cout << "\t Domain of attraction :\n" << e_out << endl; + } return BoolInterval::TRUE; } + alpha++; } - cout << "The method is not able to conclude on the stability" << endl; + + if(verbose) + cout << "\t The method is not able to conclude on the stability" << endl; + return BoolInterval::UNKNOWN; } } \ No newline at end of file diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h index 48265836..45259423 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h @@ -20,16 +20,17 @@ namespace codac2 * \param alpha_max ... * \param e ... * \param e_out ... + * \param verbose ... * \return ... */ - BoolInterval stability_analysis(const AnalyticFunction& f, int alpha_max, Ellipsoid& e, Ellipsoid& e_out); + BoolInterval stability_analysis(const AnalyticFunction& f, unsigned int alpha_max, Ellipsoid& e, Ellipsoid& e_out, bool verbose = false); /** * \brief ... * - * \param a ... - * \param q ... + * \param A ... + * \param Q ... * \return ... */ - Matrix solve_discrete_lyapunov(const Matrix& a, const Matrix& q); + Matrix solve_discrete_lyapunov(const Matrix& A, const Matrix& Q); } \ No newline at end of file diff --git a/src/core/domains/interval/codac2_Interval.cpp b/src/core/domains/interval/codac2_Interval.cpp deleted file mode 100644 index 1edde677..00000000 --- a/src/core/domains/interval/codac2_Interval.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/** - * codac2_Interval.cpp - * - * This class reuses several functions developed for ibex::Interval. - * The original IBEX code is encapsulated in Codac for allowing inheritance - * to Codac classes and also for documentation, binding, and independency purposes. - * See ibex::Interval (IBEX lib, main author: Gilles Chabert) - * https://ibex-lib.readthedocs.io - * - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Gilles Chabert, Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include -#include -#include "codac2_Interval.h" -#include "codac2_assert.h" - -using namespace std; - -namespace codac2 -{ - Interval::Interval() - : ibex::Interval() - { } - - Interval::Interval(double a) - : ibex::Interval(a) - { } - - Interval::Interval(double a, double b) - : ibex::Interval(a,b) - { } - - Interval::Interval(const Interval& x) - : ibex::Interval(x) - { } - - Interval::Interval(array array) - : ibex::Interval(array) - { } - - Interval::Interval(array array) - : ibex::Interval(array) - { } - - Interval::Interval(std::initializer_list l) - : Interval() - { - init_from_list(l); - } - - Interval& Interval::init(const Interval& x) - { - *this = x; - return *this; - } - - Interval& Interval::init_from_list(const std::list& l) - { - assert_release((l.size() == 1 || l.size() == 2) - && "'Interval' can only be defined by one or two 'double' values."); - *this = Interval(*l.begin(),*std::prev(l.end())); - return *this; - } - - Interval& Interval::operator=(const Interval& x) - { - ibex::Interval::operator=(x); - return *this; - } - - bool Interval::operator==(const Interval& x) const - { - return ibex::Interval::operator==(x); - } - - bool Interval::operator!=(const Interval& x) const - { - return ibex::Interval::operator!=(x); - } - - double Interval::lb() const - { - return ibex::Interval::lb(); - } - - double Interval::ub() const - { - return ibex::Interval::ub(); - } - - double Interval::mid() const - { - return ibex::Interval::mid(); - } - - double Interval::rand() const - { - if(is_empty()) - return std::numeric_limits::quiet_NaN(); - - double a = max(next_float(-oo),lb()); - double b = min(previous_float(oo),ub()); - return a + (((double)std::rand())/(double)RAND_MAX)*(b-a); - } - - double Interval::rad() const - { - return ibex::Interval::rad(); - } - - double Interval::diam() const - { - return ibex::Interval::diam(); - } - - double Interval::volume() const - { - return ibex::Interval::diam(); - } - - size_t Interval::size() const - { - return 1; - } - - void Interval::set_empty() - { - ibex::Interval::set_empty(); - } - - bool Interval::is_empty() const - { - return ibex::Interval::is_empty(); - } - - bool Interval::contains(const double& x) const - { - return ibex::Interval::contains(x); - } - - bool Interval::interior_contains(const double& x) const - { - return ibex::Interval::interior_contains(x); - } - - bool Interval::is_unbounded() const - { - return ibex::Interval::is_unbounded(); - } - - bool Interval::is_degenerated() const - { - return ibex::Interval::is_degenerated(); - } - - bool Interval::intersects(const Interval &x) const - { - return ibex::Interval::intersects(x); - } - - bool Interval::is_disjoint(const Interval& x) const - { - return ibex::Interval::is_disjoint(x); - } - - bool Interval::overlaps(const Interval& x) const - { - return ibex::Interval::overlaps(x); - } - - bool Interval::is_subset(const Interval& x) const - { - return ibex::Interval::is_subset(x); - } - - bool Interval::is_strict_subset(const Interval& x) const - { - return ibex::Interval::is_strict_subset(x); - } - - bool Interval::is_interior_subset(const Interval& x) const - { - return ibex::Interval::is_interior_subset(x); - } - - bool Interval::is_strict_interior_subset(const Interval& x) const - { - return ibex::Interval::is_strict_interior_subset(x); - } - - bool Interval::is_superset(const Interval& x) const - { - return ibex::Interval::is_superset(x); - } - - bool Interval::is_strict_superset(const Interval& x) const - { - return ibex::Interval::is_strict_superset(x); - } - - Interval& Interval::inflate(const double& rad) - { - ibex::Interval::inflate(rad); - return *this; - } - - bool Interval::is_bisectable() const - { - return ibex::Interval::is_bisectable(); - } - - pair Interval::bisect(float ratio) const - { - assert_release(Interval(0,1).interior_contains(ratio)); - auto p = ibex::Interval::bisect(ratio); - return { p.first, p.second }; - } - - vector Interval::complementary(bool compactness) const - { - if(is_empty() || (compactness && is_degenerated())) - return { {-oo,oo} }; - - vector l; - - if(lb() > -oo) - l.push_back({-oo,lb()}); - - if(ub() < oo) - l.push_back({ub(),oo}); - - return l; - } - - vector Interval::diff(const Interval& y, bool compactness) const - { - if(compactness && is_degenerated()) - { - if(is_empty() || y.contains(lb())) - return {}; - else - return { *this }; - } - - vector l; - for(const auto& li : y.complementary(compactness)) - { - Interval inter = li & *this; - if(!inter.is_degenerated()) - l.push_back(inter); - } - - return l; - } - - Interval& Interval::operator|=(const Interval& x) - { - ibex::Interval::operator|=(x); - return *this; - } - - Interval& Interval::operator&=(const Interval& x) - { - ibex::Interval::operator&=(x); - return *this; - } - - Interval& Interval::operator+=(double x) - { - ibex::Interval::operator+=(x); - return *this; - } - - Interval& Interval::operator+=(const Interval& x) - { - ibex::Interval::operator+=(x); - return *this; - } - - Interval Interval::operator-() const - { - return 0.-*this; - } - - Interval& Interval::operator-=(double x) - { - ibex::Interval::operator-=(x); - return *this; - } - - Interval& Interval::operator-=(const Interval& x) - { - ibex::Interval::operator-=(x); - return *this; - } - - Interval& Interval::operator*=(double x) - { - ibex::Interval::operator*=(x); - return *this; - } - - Interval& Interval::operator*=(const Interval& x) - { - ibex::Interval::operator*=(x); - return *this; - } - - Interval& Interval::operator/=(double x) - { - ibex::Interval::operator/=(x); - return *this; - } - - Interval& Interval::operator/=(const Interval& x) - { - ibex::Interval::operator/=(x); - return *this; - } - - Interval Interval::empty() - { - return ibex::Interval::empty_set(); - } - - Interval Interval::zero() - { - return ibex::Interval::zero(); - } - - Interval Interval::zeros() - { - return ibex::Interval::zero(); - } - - Interval Interval::one() - { - return ibex::Interval::one(); - } - - Interval Interval::ones() - { - return ibex::Interval::one(); - } - - Interval Interval::half_pi() - { - return ibex::Interval::half_pi(); - } - - Interval Interval::pi() - { - return ibex::Interval::pi(); - } - - Interval Interval::two_pi() - { - return ibex::Interval::two_pi(); - } - - ostream& operator<<(ostream& os, const Interval& x) - { - ibex::operator<<(os,x); - return os; - } - - Interval::Interval(const ibex::Interval& x) - : ibex::Interval(x) - { } - - Interval operator""_i(long double x) - { - return Interval(x); - } - -} // namespace codac \ No newline at end of file diff --git a/src/core/domains/interval/codac2_Interval.h b/src/core/domains/interval/codac2_Interval.h index e416f2d0..87822395 100644 --- a/src/core/domains/interval/codac2_Interval.h +++ b/src/core/domains/interval/codac2_Interval.h @@ -19,7 +19,9 @@ #include #include #include +#include "codac2_Index.h" #include "codac2_Domain.h" +#include "codac2_assert.h" namespace codac2 { @@ -163,6 +165,25 @@ namespace codac2 */ double mid() const; + /** + * \brief Returns the magnitude of this + * i.e. max(|lower bound|, |upper bound|). + * + * \return the magnitude of the interval + */ + double mag() const; + + /** + * \brief Returns the mignitude of this + * + * +(lower bound) if lower_bound > 0 + * -(upper bound) if upper_bound < 0 + * 0 otherwise. + * + * \return the mignitude of the interval + */ + double mig() const; + /** * \brief Returns a random value inside the interval * @@ -206,7 +227,7 @@ namespace codac2 * * \return 1 */ - size_t size() const; + Index size() const; /** * \brief Sets this interval to the empty set @@ -491,44 +512,60 @@ namespace codac2 * * \return an empty set */ - static Interval empty(); + static Interval empty() + { + return ibex::Interval::empty_set(); + } /** * \brief Provides an interval for \f$[0]\f$ * * \return an interval containing \f$0\f$ */ - static Interval zero(); - static Interval zeros(); + static Interval zero() + { + return ibex::Interval::zero(); + } /** * \brief Provides an interval for \f$[1]\f$ * * \return an interval containing \f$1\f$ */ - static Interval one(); - static Interval ones(); + static Interval one() + { + return ibex::Interval::one(); + } /** * \brief Provides an interval for \f$[\frac{\pi}{2}]\f$ * * \return an interval containing \f$\frac{\pi}{2}\f$ */ - static Interval half_pi(); + static Interval half_pi() + { + return ibex::Interval::half_pi(); + } /** * \brief Provides an interval for \f$[\pi]\f$ * * \return an interval containing \f$\pi\f$ */ - static Interval pi(); + static Interval pi() + { + return ibex::Interval::pi(); + } /** * \brief Provides an interval for \f$[2\pi]\f$ * * \return an interval containing \f$2\pi\f$ */ - static Interval two_pi(); + static Interval two_pi() + { + return ibex::Interval::two_pi(); + } friend std::ostream& operator<<(std::ostream& os, const Interval& x); @@ -545,88 +582,88 @@ namespace codac2 friend Interval f(const Interval&, double); \ friend Interval f(const Interval&, const Interval&); \ - _dec_friend_interval_arithm_op(operator&); - _dec_friend_interval_arithm_op(operator|); - _dec_friend_interval_arithm_op(operator+); - _dec_friend_interval_arithm_op(operator-); - _dec_friend_interval_arithm_op(operator*); - _dec_friend_interval_arithm_op(operator/); + _dec_friend_interval_arithm_op(operator&) + _dec_friend_interval_arithm_op(operator|) + _dec_friend_interval_arithm_op(operator+) + _dec_friend_interval_arithm_op(operator-) + _dec_friend_interval_arithm_op(operator*) + _dec_friend_interval_arithm_op(operator/) #define _dec_friend_interval_unary_op(f) \ friend Interval f(const Interval&); \ - _dec_friend_interval_unary_op(sqr); - _dec_friend_interval_unary_op(sqrt); - _dec_friend_interval_unary_op(exp); - _dec_friend_interval_unary_op(log); - _dec_friend_interval_unary_op(cos); - _dec_friend_interval_unary_op(sin); - _dec_friend_interval_unary_op(tan); - _dec_friend_interval_unary_op(acos); - _dec_friend_interval_unary_op(asin); - _dec_friend_interval_unary_op(atan); - _dec_friend_interval_unary_op(cosh); - _dec_friend_interval_unary_op(sinh); - _dec_friend_interval_unary_op(tanh); - _dec_friend_interval_unary_op(acosh); - _dec_friend_interval_unary_op(asinh); - _dec_friend_interval_unary_op(atanh); - _dec_friend_interval_unary_op(abs); - _dec_friend_interval_unary_op(sign); - _dec_friend_interval_unary_op(integer); - _dec_friend_interval_unary_op(floor); - _dec_friend_interval_unary_op(ceil); + _dec_friend_interval_unary_op(sqr) + _dec_friend_interval_unary_op(sqrt) + _dec_friend_interval_unary_op(exp) + _dec_friend_interval_unary_op(log) + _dec_friend_interval_unary_op(cos) + _dec_friend_interval_unary_op(sin) + _dec_friend_interval_unary_op(tan) + _dec_friend_interval_unary_op(acos) + _dec_friend_interval_unary_op(asin) + _dec_friend_interval_unary_op(atan) + _dec_friend_interval_unary_op(cosh) + _dec_friend_interval_unary_op(sinh) + _dec_friend_interval_unary_op(tanh) + _dec_friend_interval_unary_op(acosh) + _dec_friend_interval_unary_op(asinh) + _dec_friend_interval_unary_op(atanh) + _dec_friend_interval_unary_op(abs) + _dec_friend_interval_unary_op(sign) + _dec_friend_interval_unary_op(integer) + _dec_friend_interval_unary_op(floor) + _dec_friend_interval_unary_op(ceil) #define _dec_friend_interval_binary_op(f) \ friend Interval f(const Interval&, const Interval&); \ - _dec_friend_interval_binary_op(max); - _dec_friend_interval_binary_op(min); - _dec_friend_interval_binary_op(atan2); + _dec_friend_interval_binary_op(max) + _dec_friend_interval_binary_op(min) + _dec_friend_interval_binary_op(atan2) friend Interval pow(const Interval&, int); friend Interval pow(const Interval&, double); - _dec_friend_interval_binary_op(pow); + _dec_friend_interval_binary_op(pow) friend Interval root(const Interval&, int); #define _dec_friend_interval_unary_bwd(f) \ friend void f(const Interval&, Interval&); \ - _dec_friend_interval_unary_bwd(bwd_sqr); - _dec_friend_interval_unary_bwd(bwd_sqrt); - _dec_friend_interval_unary_bwd(bwd_exp); - _dec_friend_interval_unary_bwd(bwd_log); - _dec_friend_interval_unary_bwd(bwd_cos); - _dec_friend_interval_unary_bwd(bwd_sin); - _dec_friend_interval_unary_bwd(bwd_tan); - _dec_friend_interval_unary_bwd(bwd_acos); - _dec_friend_interval_unary_bwd(bwd_asin); - _dec_friend_interval_unary_bwd(bwd_atan); - _dec_friend_interval_unary_bwd(bwd_cosh); - _dec_friend_interval_unary_bwd(bwd_sinh); - _dec_friend_interval_unary_bwd(bwd_tanh); - _dec_friend_interval_unary_bwd(bwd_acosh); - _dec_friend_interval_unary_bwd(bwd_asinh); - _dec_friend_interval_unary_bwd(bwd_atanh); - _dec_friend_interval_unary_bwd(bwd_abs); - _dec_friend_interval_unary_bwd(bwd_sign); - _dec_friend_interval_unary_bwd(bwd_floor); - _dec_friend_interval_unary_bwd(bwd_ceil); - _dec_friend_interval_unary_bwd(bwd_saw); + _dec_friend_interval_unary_bwd(bwd_sqr) + _dec_friend_interval_unary_bwd(bwd_sqrt) + _dec_friend_interval_unary_bwd(bwd_exp) + _dec_friend_interval_unary_bwd(bwd_log) + _dec_friend_interval_unary_bwd(bwd_cos) + _dec_friend_interval_unary_bwd(bwd_sin) + _dec_friend_interval_unary_bwd(bwd_tan) + _dec_friend_interval_unary_bwd(bwd_acos) + _dec_friend_interval_unary_bwd(bwd_asin) + _dec_friend_interval_unary_bwd(bwd_atan) + _dec_friend_interval_unary_bwd(bwd_cosh) + _dec_friend_interval_unary_bwd(bwd_sinh) + _dec_friend_interval_unary_bwd(bwd_tanh) + _dec_friend_interval_unary_bwd(bwd_acosh) + _dec_friend_interval_unary_bwd(bwd_asinh) + _dec_friend_interval_unary_bwd(bwd_atanh) + _dec_friend_interval_unary_bwd(bwd_abs) + _dec_friend_interval_unary_bwd(bwd_sign) + _dec_friend_interval_unary_bwd(bwd_floor) + _dec_friend_interval_unary_bwd(bwd_ceil) + _dec_friend_interval_unary_bwd(bwd_saw) #define _dec_friend_interval_binary_bwd(f) \ friend void f(const Interval&, Interval&, Interval&); \ - _dec_friend_interval_binary_bwd(bwd_add); - _dec_friend_interval_binary_bwd(bwd_sub); - _dec_friend_interval_binary_bwd(bwd_mul); - _dec_friend_interval_binary_bwd(bwd_div); - _dec_friend_interval_binary_bwd(bwd_pow); - _dec_friend_interval_binary_bwd(bwd_min); - _dec_friend_interval_binary_bwd(bwd_max); - _dec_friend_interval_binary_bwd(bwd_atan2); + _dec_friend_interval_binary_bwd(bwd_add) + _dec_friend_interval_binary_bwd(bwd_sub) + _dec_friend_interval_binary_bwd(bwd_mul) + _dec_friend_interval_binary_bwd(bwd_div) + _dec_friend_interval_binary_bwd(bwd_pow) + _dec_friend_interval_binary_bwd(bwd_min) + _dec_friend_interval_binary_bwd(bwd_max) + _dec_friend_interval_binary_bwd(bwd_atan2) friend void bwd_pow(const Interval&, Interval&, int); friend void bwd_root(const Interval&, Interval&, int); @@ -659,4 +696,378 @@ namespace codac2 { return ibex::next_float(x); } +} + +// Inline functions + +namespace codac2 +{ + inline Interval::Interval() + : ibex::Interval() + { } + + inline Interval::Interval(double a) + : ibex::Interval(a) + { } + + inline Interval::Interval(double a, double b) + : ibex::Interval(a,b) + { } + + inline Interval::Interval(const Interval& x) + : ibex::Interval(x) + { } + + inline Interval::Interval(std::array array) + : ibex::Interval(array) + { } + + inline Interval::Interval(std::array array) + : ibex::Interval(array) + { } + + inline Interval::Interval(std::initializer_list l) + : Interval() + { + init_from_list(l); + } + + inline Interval& Interval::init(const Interval& x) + { + *this = x; + return *this; + } + + inline Interval& Interval::init_from_list(const std::list& l) + { + assert_release((l.size() == 1 || l.size() == 2) + && "'Interval' can only be defined by one or two 'double' values."); + *this = Interval(*l.begin(),*std::prev(l.end())); + return *this; + } + + inline Interval& Interval::operator=(const Interval& x) + { + ibex::Interval::operator=(x); + return *this; + } + + inline bool Interval::operator==(const Interval& x) const + { + return ibex::Interval::operator==(x); + } + + inline bool Interval::operator!=(const Interval& x) const + { + return ibex::Interval::operator!=(x); + } + + inline double Interval::lb() const + { + return ibex::Interval::lb(); + } + + inline double Interval::ub() const + { + return ibex::Interval::ub(); + } + + inline double Interval::mid() const + { + return ibex::Interval::mid(); + } + + inline double Interval::mag() const + { + return ibex::Interval::mag(); + } + + inline double Interval::mig() const + { + return ibex::Interval::mig(); + } + + inline double Interval::rand() const + { + if(is_empty()) + return std::numeric_limits::quiet_NaN(); + + double a = std::max(next_float(-oo),lb()); + double b = std::min(previous_float(oo),ub()); + double r = a + (((double)std::rand())/(double)RAND_MAX)*(b-a); + // The above operation may result in a floating point outside the bounds, + // due to floating-point errors. Such possible error is corrected below: + return std::max(lb(),std::min(r,ub())); + } + + inline double Interval::rad() const + { + return ibex::Interval::rad(); + } + + inline double Interval::diam() const + { + return ibex::Interval::diam(); + } + + inline double Interval::volume() const + { + return ibex::Interval::diam(); + } + + inline Index Interval::size() const + { + return 1; + } + + inline void Interval::set_empty() + { + ibex::Interval::set_empty(); + } + + inline bool Interval::is_empty() const + { + return ibex::Interval::is_empty(); + } + + inline bool Interval::contains(const double& x) const + { + return ibex::Interval::contains(x); + } + + inline bool Interval::interior_contains(const double& x) const + { + return ibex::Interval::interior_contains(x); + } + + inline bool Interval::is_unbounded() const + { + return ibex::Interval::is_unbounded(); + } + + inline bool Interval::is_degenerated() const + { + return ibex::Interval::is_degenerated(); + } + + inline bool Interval::intersects(const Interval &x) const + { + return ibex::Interval::intersects(x); + } + + inline bool Interval::is_disjoint(const Interval& x) const + { + return ibex::Interval::is_disjoint(x); + } + + inline bool Interval::overlaps(const Interval& x) const + { + return ibex::Interval::overlaps(x); + } + + inline bool Interval::is_subset(const Interval& x) const + { + return ibex::Interval::is_subset(x); + } + + inline bool Interval::is_strict_subset(const Interval& x) const + { + return ibex::Interval::is_strict_subset(x); + } + + inline bool Interval::is_interior_subset(const Interval& x) const + { + return ibex::Interval::is_interior_subset(x); + } + + inline bool Interval::is_strict_interior_subset(const Interval& x) const + { + return ibex::Interval::is_strict_interior_subset(x); + } + + inline bool Interval::is_superset(const Interval& x) const + { + return ibex::Interval::is_superset(x); + } + + inline bool Interval::is_strict_superset(const Interval& x) const + { + return ibex::Interval::is_strict_superset(x); + } + + inline Interval& Interval::inflate(const double& rad) + { + ibex::Interval::inflate(rad); + return *this; + } + + inline bool Interval::is_bisectable() const + { + return ibex::Interval::is_bisectable(); + } + + inline std::pair Interval::bisect(float ratio) const + { + assert_release(Interval(0,1).interior_contains(ratio)); + auto p = ibex::Interval::bisect(ratio); + return { p.first, p.second }; + } + + inline std::vector Interval::complementary(bool compactness) const + { + if(is_empty() || (compactness && is_degenerated())) + return { {-oo,oo} }; + + std::vector l; + + if(lb() > -oo) + l.push_back({-oo,lb()}); + + if(ub() < oo) + l.push_back({ub(),oo}); + + return l; + } + + inline std::vector Interval::diff(const Interval& y, bool compactness) const + { + if(compactness && is_degenerated()) + { + if(is_empty() || y.contains(lb())) + return {}; + else + return { *this }; + } + + std::vector l; + for(const auto& li : y.complementary(compactness)) + { + Interval inter = li & *this; + if(!inter.is_degenerated()) + l.push_back(inter); + } + + return l; + } + + inline Interval& Interval::operator|=(const Interval& x) + { + ibex::Interval::operator|=(x); + return *this; + } + + inline Interval& Interval::operator&=(const Interval& x) + { + ibex::Interval::operator&=(x); + return *this; + } + + inline Interval& Interval::operator+=(double x) + { + ibex::Interval::operator+=(x); + return *this; + } + + inline Interval& Interval::operator+=(const Interval& x) + { + ibex::Interval::operator+=(x); + return *this; + } + + inline Interval Interval::operator-() const + { + return 0.-*this; + } + + inline Interval& Interval::operator-=(double x) + { + ibex::Interval::operator-=(x); + return *this; + } + + inline Interval& Interval::operator-=(const Interval& x) + { + ibex::Interval::operator-=(x); + return *this; + } + + inline Interval& Interval::operator*=(double x) + { + ibex::Interval::operator*=(x); + return *this; + } + + inline Interval& Interval::operator*=(const Interval& x) + { + ibex::Interval::operator*=(x); + return *this; + } + + inline Interval& Interval::operator/=(double x) + { + ibex::Interval::operator/=(x); + return *this; + } + + inline Interval& Interval::operator/=(const Interval& x) + { + ibex::Interval::operator/=(x); + return *this; + } + + /*static inline Interval Interval::empty() + { + return ibex::Interval::empty_set(); + } + + static inline Interval Interval::zero() + { + return ibex::Interval::zero(); + } + + static inline Interval Interval::zeros() + { + return ibex::Interval::zero(); + } + + static inline Interval Interval::one() + { + return ibex::Interval::one(); + } + + static inline Interval Interval::ones() + { + return ibex::Interval::one(); + } + + static inline Interval Interval::half_pi() + { + return ibex::Interval::half_pi(); + } + + static inline Interval Interval::pi() + { + return ibex::Interval::pi(); + } + + static inline Interval Interval::two_pi() + { + return ibex::Interval::two_pi(); + }*/ + + inline std::ostream& operator<<(std::ostream& os, const Interval& x) + { + gaol::interval::precision(os.precision()); + ibex::operator<<(os,x); + return os; + } + + inline Interval::Interval(const ibex::Interval& x) + : ibex::Interval(x) + { } + + inline Interval operator""_i(long double x) + { + return Interval(x); + } } \ No newline at end of file diff --git a/src/core/domains/interval/codac2_IntervalMatrix.cpp b/src/core/domains/interval/codac2_IntervalMatrix.cpp deleted file mode 100644 index 368e08ea..00000000 --- a/src/core/domains/interval/codac2_IntervalMatrix.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - * codac2_IntervalMatrix.cpp - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include "codac2_IntervalMatrix.h" -#include "codac2_IntervalVector.h" - -using namespace std; -using namespace codac2; - -namespace codac2 -{ - IntervalMatrix::IntervalMatrix(size_t r, size_t c) - : IntervalMatrix(r,c,Interval()) - { - assert_release(r >= 0 && c >= 0); - } - - IntervalMatrix::IntervalMatrix(size_t r, size_t c, const Interval& x) - : MatrixBase(r,c,x), - IntervalMatrixBase(r,c,x) - { - assert_release(r >= 0 && c >= 0); - } - - IntervalMatrix::IntervalMatrix(const Matrix& x) - : MatrixBase(x._e.template cast()), - IntervalMatrixBase(x._e.template cast()) - { } - - IntervalMatrix::IntervalMatrix(const Matrix& lb, const Matrix& ub) - : MatrixBase(lb._e.template cast()), - IntervalMatrixBase(lb._e.template cast()) - { - assert_release(lb.size() == ub.size()); - *this |= ub; - } - - IntervalMatrix::IntervalMatrix(size_t r, size_t c, const double bounds[][2]) - : MatrixBase(r,c), - IntervalMatrixBase(r,c,bounds) - { - assert_release(r >= 0 && c >= 0); - } - - IntervalMatrix::IntervalMatrix(std::initializer_list> l) - : MatrixBase(l), - IntervalMatrixBase(l) - { - assert_release(!std::empty(l)); - } - - IntervalMatrix::IntervalMatrix(const MatrixBase& x) - : IntervalMatrix(x._e.template cast()) - { } - - IntervalMatrix::IntervalMatrix(const MatrixBase& x) - : MatrixBase(x._e), - IntervalMatrixBase(x._e) - { } - - IntervalMatrix::IntervalMatrix(const IntervalVector& x) - : IntervalMatrix(x._e) - { } - - IntervalMatrix IntervalMatrix::transpose() const - { - return this->_e.transpose(); - } - - IntervalMatrix IntervalMatrix::diag_matrix() const - { - return _e.diagonal().asDiagonal().toDenseMatrix(); - } - - bool operator==(const IntervalMatrix& x1, const IntervalMatrix& x2) - { - // ^ This overload allows automatic cast for Matrix == IntervalMatrix comparisons - return (IntervalMatrixBase)x1 == (IntervalMatrixBase)x2; - } - - IntervalMatrix IntervalMatrix::empty(size_t r, size_t c) - { - assert_release(r >= 0 && c >= 0); - return IntervalMatrix(r,c,Interval::empty()); - } -} \ No newline at end of file diff --git a/src/core/domains/interval/codac2_IntervalMatrix.h b/src/core/domains/interval/codac2_IntervalMatrix.h index 0f10c61c..a1fea32a 100644 --- a/src/core/domains/interval/codac2_IntervalMatrix.h +++ b/src/core/domains/interval/codac2_IntervalMatrix.h @@ -1,147 +1,30 @@ /** * \file codac2_IntervalMatrix.h - * - * This class reuses some of the functions developed for ibex::IntervalMatrix. - * The original IBEX code is revised in modern C++ and adapted to the template - * structure proposed in Codac, based on the Eigen library. - * See ibex::IntervalMatrix (IBEX lib, author: Gilles Chabert) - * * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou, Gilles Chabert + * \author Simon Rohou * \copyright Copyright 2023 Codac Team * \license GNU Lesser General Public License (LGPL) */ #pragma once -#include "codac2_assert.h" -#include "codac2_Matrix.h" -#include "codac2_IntervalMatrixBase.h" -#include "codac2_IntervalVector.h" +#include "codac2_matrices.h" +#include "codac2_Vector.h" namespace codac2 { - class IntervalVector; - - class IntervalMatrix : public IntervalMatrixBase - { - public: - - explicit IntervalMatrix(size_t r, size_t c); - - explicit IntervalMatrix(size_t r, size_t c, const Interval& x); - - IntervalMatrix(const Matrix& x); - - explicit IntervalMatrix(const Matrix& lb, const Matrix& ub); - - explicit IntervalMatrix(size_t r, size_t c, const double bounds[][2]); - - IntervalMatrix(std::initializer_list> l); - - template - requires (std::is_same_v && ...) - IntervalMatrix(const IV&... x) - : MatrixBase(sizeof...(IV), std::get<0>(std::tie(x...)).size()), - IntervalMatrixBase(sizeof...(IV), std::get<0>(std::tie(x...)).size()) - { - size_t i = 0; - ((this->row(i++) = x), ...); - assert(i == nb_rows()); - } - - IntervalMatrix(const MatrixBase& x); - - IntervalMatrix(const MatrixBase& x); - - IntervalMatrix(const IntervalVector& x); - - template - IntervalMatrix(const MatrixBaseBlock& x) - : IntervalMatrix(x.eval()) - { } - - template - IntervalMatrix(const Eigen::MatrixBase& x) - : MatrixBase(x.template cast()), - IntervalMatrixBase(x.template cast()) - { } - - IntervalMatrix transpose() const; - - IntervalMatrix diag_matrix() const; - - friend bool operator==(const IntervalMatrix& x1, const IntervalMatrix& x2); - - static IntervalMatrix empty(size_t r, size_t c); - - // Operators - - IntervalMatrix& operator+=(const IntervalMatrix& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e += x._e; - return *this; - } - - template - IntervalMatrix& operator+=(const MatrixBaseBlock& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e += eigen(x).template cast(); - return *this; - } - - IntervalMatrix& operator-=(const IntervalMatrix& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e -= x._e; - return *this; - } - - template - IntervalMatrix& operator-=(const MatrixBaseBlock& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e -= eigen(x).template cast(); - return *this; - } - - IntervalMatrix& operator*=(const Interval& x) - { - this->_e *= x; - return *this; - } - - IntervalMatrix& operator*=(const IntervalMatrix& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e *= x._e; - return *this; - } - - template - IntervalMatrix& operator*=(const MatrixBaseBlock& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e *= eigen(x).template cast(); - return *this; - } - - IntervalMatrix& operator/=(const Interval& x) - { - this->_e /= x; - return *this; - } - }; + using IntervalMatrix = Eigen::Matrix; inline std::ostream& operator<<(std::ostream& os, const IntervalMatrix& x) { if(x.is_empty()) - return os << "( empty matrix )"; + return os << "[ empty " << x.rows() << "x" << x.cols() << " mat ]"; else - return os << (const MatrixBase&)x; + { + os << x.format(codac_matrix_fmt()); + return os; + } } } \ No newline at end of file diff --git a/src/core/domains/interval/codac2_IntervalMatrixBase.h b/src/core/domains/interval/codac2_IntervalMatrixBase.h deleted file mode 100644 index 2d47d717..00000000 --- a/src/core/domains/interval/codac2_IntervalMatrixBase.h +++ /dev/null @@ -1,507 +0,0 @@ -/** - * \file codac2_IntervalMatrixBase.h - * - * This class reuses some of the functions developed for ibex::IntervalMatrixBase. - * The original IBEX code is revised in modern C++ and adapted to the template - * structure proposed in Codac, based on the Eigen library. - * See ibex::IntervalMatrixBase (IBEX lib, author: Gilles Chabert) - * - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou, Gilles Chabert - * \copyright Copyright 2023 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include "codac2_assert.h" -#include "codac2_MatrixBase.h" -#include "codac2_Domain.h" - -namespace codac2 -{ - class IntervalMatrix; - - template - class IntervalMatrixBase : virtual public MatrixBase, public DomainInterface - { - public: - - explicit IntervalMatrixBase(size_t r, size_t c) - : MatrixBase(r,c) - { } - - explicit IntervalMatrixBase(size_t r, size_t c, const Interval& x) - : MatrixBase(r,c,x) - { } - - explicit IntervalMatrixBase(size_t r, size_t c, const double bounds[][2]) - : MatrixBase(r,c) - { - size_t k = 0; - for(size_t i = 0 ; i < this->nb_rows() ; i++) - for(size_t j = 0 ; j < this->nb_cols() ; j++) - { - (*this)(i,j) = Interval(bounds[k][0],bounds[k][1]); - k++; - } - assert(k == this->size()); - } - - IntervalMatrixBase(std::initializer_list> l) - : MatrixBase(l) - { } - - template - IntervalMatrixBase(const Eigen::MatrixBase& x) - : MatrixBase(x) - { } - - double volume() const - { - if(is_empty()) - return 0.; - - double v = 0.; - for(size_t i = 0 ; i < this->size() ; i++) - { - if((this->_e.data()+i)->is_unbounded()) return oo; - if((this->_e.data()+i)->is_degenerated()) return 0.; - v += std::log((this->_e.data()+i)->diam()); - } - return std::exp(v); - } - - bool is_empty() const - { - for(size_t i = 0 ; i < this->size() ; i++) - if((this->_e.data()+i)->is_empty()) - return true; - return false; - } - - void set_empty() - { - this->init(Interval::empty()); - } - - #define degenerate_mat(op) \ - V op(this->nb_rows(),this->nb_cols()); \ - \ - if(is_empty()) \ - op.init(std::numeric_limits::quiet_NaN()); \ - \ - else \ - { \ - for(size_t i = 0 ; i < this->size() ; i++) \ - *(op._e.data()+i) = (this->_e.data()+i)->op(); \ - } \ - \ - return op; \ - - V lb() const - { - degenerate_mat(lb); - } - - V ub() const - { - degenerate_mat(ub); - } - - V mid() const - { - degenerate_mat(mid); - } - - V rand() const - { - srand(time(NULL)); - degenerate_mat(rand); - } - - V rad() const - { - degenerate_mat(rad); - } - - V diam() const - { - degenerate_mat(diam); - } - - double min_diam() const - { - return (this->_e.data()+extr_diam_index(true))->diam(); - } - - double max_diam() const - { - return (this->_e.data()+extr_diam_index(false))->diam(); - } - - size_t min_diam_index() const - { - return extr_diam_index(true); - } - - size_t max_diam_index() const - { - return extr_diam_index(false); - } - - size_t extr_diam_index(bool min) const - { - // This code originates from the ibex-lib - // See: ibex_TemplateVector.h - // Author: Gilles Chabert - - double d = min ? oo : -1; // -1 to be sure that even a 0-diameter interval can be selected - int selected_index = -1; - bool unbounded = false; - assert_release(!is_empty() && "Diameter of an empty IntervalVector is undefined"); - - size_t i; - - for(i = 0 ; i < this->size() ; i++) - { - if((this->_e.data()+i)->is_unbounded()) - { - unbounded = true; - if(!min) break; - } - else - { - double w = (this->_e.data()+i)->diam(); - if(min ? wd) - { - selected_index = i; - d = w; - } - } - } - - if(min && selected_index == -1) - { - assert(unbounded); - // the selected interval is the first one. - i = 0; - } - - // The unbounded intervals are not considered if we look for the minimal diameter - // and some bounded intervals have been found (selected_index!=-1) - if(unbounded && (!min || selected_index == -1)) - { - double pt = min ? -oo : oo; // keep the point less/most distant from +oo (we normalize if the lower bound is -oo) - selected_index = i; - - for(; i < this->size() ; i++) - { - if((this->_e.data()+i)->lb() == -oo) - { - if((this->_e.data()+i)->ub() == oo) - if(!min) - { - selected_index = i; - break; - } - - if((min && (-(this->_e.data()+i)->ub() > pt)) || (!min && (-(this->_e.data()+i)->ub() < pt))) - { - selected_index = i; - pt = -(this->_e.data()+i)->ub(); - } - } - - else if((this->_e.data()+i)->ub() == oo) - if((min && ((this->_e.data()+i)->lb() > pt)) || (!min && ((this->_e.data()+i)->lb() < pt))) - { - selected_index = i; - pt = (this->_e.data()+i)->lb(); - } - } - } - - return selected_index; - } - - bool contains(const V& x) const - { - assert_release(x.size() == this->size()); - - if(is_empty()) - return false; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->contains(*(x._e.data()+i))) - return false; - - return true; - } - - bool interior_contains(const V& x) const - { - assert_release(x.size() == this->size()); - - if(is_empty()) - return false; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->interior_contains(*(x._e.data()+i))) - return false; - - return true; - } - - bool is_unbounded() const - { - if(is_empty()) return false; - for(size_t i = 0 ; i < this->size() ; i++) - if((this->_e.data()+i)->is_unbounded()) - return true; - return false; - } - - bool is_degenerated() const - { - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->is_degenerated()) - return false; - return true; - } - - bool is_flat() const - { - if(is_empty()) return true; - for(size_t i = 0 ; i < this->size() ; i++) - if((this->_e.data()+i)->is_degenerated()) // don't use diam() because of roundoff - return true; - return false; - } - - bool intersects(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return false; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->intersects(*(x._e.data()+i))) - return false; - - return true; - } - - bool is_disjoint(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return true; - - for(size_t i = 0 ; i < this->size() ; i++) - if((this->_e.data()+i)->is_disjoint(*(x._e.data()+i))) - return true; - - return false; - } - - bool overlaps(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return false; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->overlaps(*(x._e.data()+i))) - return false; - - return true; - } - - bool is_subset(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return true; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->is_subset(*(x._e.data()+i))) - return false; - - return true; - } - - bool is_strict_subset(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return true; - - if(!is_subset(x)) - return false; - - for(size_t i = 0 ; i < this->size() ; i++) - if((this->_e.data()+i)->is_strict_subset(*(x._e.data()+i))) - return true; - - return false; - } - - bool is_interior_subset(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return true; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->is_interior_subset(*(x._e.data()+i))) - return false; - - return true; - } - - bool is_strict_interior_subset(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return true; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(this->_e.data()+i)->is_strict_interior_subset(*(x._e.data()+i))) - return false; - - return true; - } - - bool is_superset(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return false; - - for(size_t i = 0 ; i < this->size() ; i++) - if(!(x._e.data()+i)->is_subset(*(this->_e.data()+i))) - return false; - - return true; - } - - bool is_strict_superset(const S& x) const - { - assert_release(this->size() == x.size()); - - if(is_empty()) - return false; - - if(!is_superset(x)) - return false; - - for(size_t i = 0 ; i < this->size() ; i++) - if((x._e.data()+i)->is_strict_subset(*(this->_e.data()+i))) - return true; - - return false; - } - - bool is_bisectable() const - { - for(size_t i = 0 ; i < this->size() ; i++) - if((this->_e.data()+i)->is_bisectable()) - return true; - return false; - } - - S& inflate(double r) - { - assert_release(r >= 0.); - - for(size_t i = 0 ; i < this->size() ; i++) - (this->_e.data()+i)->inflate(r); - return static_cast(*this); - } - - S& inflate(const V& r) - { - assert_release(this->size() == r.size()); - assert_release(r.min_coeff() >= 0.); - - for(size_t i = 0 ; i < this->size() ; i++) - (this->_e.data()+i)->inflate(*(r._e.data()+i)); - return static_cast(*this); - } - - S& operator&=(const S& x) - { - assert_release(this->size() == x.size()); - - if(x.is_empty()) - { - set_empty(); - return static_cast(*this); - } - - for(size_t i = 0 ; i < this->size() ; i++) - *(this->_e.data()+i) &= *(x._e.data()+i); - return static_cast(*this); - } - - S& operator|=(const S& x) - { - assert_release(this->size() == x.size()); - - if(x.is_empty()) - return static_cast(*this); - - for(size_t i = 0 ; i < this->size() ; i++) - *(this->_e.data()+i) |= *(x._e.data()+i); - return static_cast(*this); - } - - S operator&(const S& x) const - { - auto y = *this; - return y &= x; - } - - S operator|(const S& x) const - { - auto y = *this; - return y |= x; - } - - friend bool operator==(const IntervalMatrixBase& x1, const IntervalMatrixBase& x2) - { - if(x1.is_empty() || x2.is_empty()) - return x1.is_empty() && x2.is_empty() && x1.size() == x2.size(); - - return (MatrixBase)x1 == (MatrixBase)x2; - } - - std::pair bisect(size_t i, float ratio = 0.49) const - { - assert_release(i >= 0 && i < this->size()); - assert_release((this->_e.data()+i)->is_bisectable()); - assert_release(Interval(0,1).interior_contains(ratio)); - - auto p = std::make_pair(*this,*this); - auto pi = (this->_e.data()+i)->bisect(ratio); - *(p.first._e.data()+i) = pi.first; - *(p.second._e.data()+i) = pi.second; - return p; - } - - std::pair bisect_largest(float ratio = 0.49) const - { - return bisect(max_diam_index(), ratio); - } - }; -} \ No newline at end of file diff --git a/src/core/domains/interval/codac2_IntervalRow.h b/src/core/domains/interval/codac2_IntervalRow.h new file mode 100644 index 00000000..632b0c42 --- /dev/null +++ b/src/core/domains/interval/codac2_IntervalRow.h @@ -0,0 +1,29 @@ +/** + * \file codac2_IntervalRow.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_matrices.h" + +namespace codac2 +{ + using IntervalRow = Eigen::Matrix; + + inline std::ostream& operator<<(std::ostream& os, const IntervalRow& x) + { + if(x.is_empty()) + return os << "[ empty row ]"; + + else + { + os << x.format(codac_row_fmt()); + return os; + } + } +} \ No newline at end of file diff --git a/src/core/domains/interval/codac2_IntervalVector.cpp b/src/core/domains/interval/codac2_IntervalVector.cpp deleted file mode 100644 index 8d1cef0b..00000000 --- a/src/core/domains/interval/codac2_IntervalVector.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/** - * codac2_IntervalVector.cpp - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include "codac2_IntervalVector.h" - -using namespace std; -using namespace codac2; - -namespace codac2 -{ - IntervalVector::IntervalVector(size_t n) - : IntervalVector(n,Interval()) - { - assert_release(n >= 0); - } - - IntervalVector::IntervalVector(size_t n, const Interval& x) - : MatrixBase(n,1,x), - IntervalMatrixBase(n,1), - VectorBase(n) - { - assert_release(n >= 0); - } - - IntervalVector::IntervalVector(size_t n, const double bounds[][2]) - : MatrixBase(n,1), - IntervalMatrixBase(n,1,bounds), - VectorBase(n) - { - assert_release(n >= 0); - } - - IntervalVector::IntervalVector(const Vector& x) - : MatrixBase(x._e.template cast()), - IntervalMatrixBase(x.size(),1), - VectorBase(x.size()) - { } - - IntervalVector::IntervalVector(const Vector& lb, const Vector& ub) - : MatrixBase(lb._e.template cast()), - IntervalMatrixBase(lb.size(),1), - VectorBase(lb.size()) - { - assert_release(lb.size() == ub.size()); - *this |= ub; - } - - IntervalVector::IntervalVector(initializer_list l) - : MatrixBase(l.size(),1), - IntervalMatrixBase(l.size(),1), - VectorBase(l) - { - assert_release(!std::empty(l)); - } - - IntervalVector::IntervalVector(const MatrixBase& x) - : IntervalVector(x._e.template cast()) - { } - - IntervalVector::IntervalVector(const MatrixBase& x) - : IntervalVector(x._e) - { } - - bool operator==(const IntervalVector& x1, const IntervalVector& x2) - { - // ^ This overload allows automatic cast for Vector == IntervalVector comparisons - return (IntervalMatrixBase)x1 == (IntervalMatrixBase)x2; - } - - list IntervalVector::complementary() const - { - return IntervalVector(this->size()).diff(*this); - } - - list IntervalVector::diff(const IntervalVector& y, bool compactness) const - { - // This code originates from the ibex-lib - // See: ibex_TemplateVector.h - // Author: Gilles Chabert - // It has been revised with modern C++ and templated types - - const size_t n = this->size(); - assert_release(y.size() == n); - - if(y == *this) - return { }; - - IntervalVector x = *this; - IntervalVector z = x & y; - - if(z.is_empty()) - { - if(x.is_empty()) return { }; - else return { x }; - } - - else - { - // Check if in one dimension y is flat and x not, - // in which case the diff returns also x directly - if(compactness) - for(size_t i = 0 ; i < n ; i++) - if(z[i].is_degenerated() && !x[i].is_degenerated()) - { - if(x.is_empty()) return { }; - else return { x }; - } - } - - list l; - - for(size_t var = 0 ; var < n ; var++) - { - Interval c1, c2; - - for(const auto& ci : x[var].diff(y[var], compactness)) - { - assert(!ci.is_empty()); - - IntervalVector v(n); - for(size_t i = 0 ; i < var ; i++) - v[i] = x[i]; - v[var] = ci; - for(size_t i = var+1 ; i < n ; i++) - v[i] = x[i]; - if(!v.is_empty()) - l.push_back(v); - } - - x[var] = z[var]; - } - - return l; - } - - IntervalVector IntervalVector::empty(size_t n) - { - assert_release(n >= 0); - return IntervalVector(n,Interval::empty()); - } - - ostream& operator<<(ostream& os, const IntervalVector& x) - { - if(x.is_empty()) - return os << "( empty vector )"; - - else - return os << (const VectorBase&)x; - } -} \ No newline at end of file diff --git a/src/core/domains/interval/codac2_IntervalVector.h b/src/core/domains/interval/codac2_IntervalVector.h index ae336a74..b05ac04b 100644 --- a/src/core/domains/interval/codac2_IntervalVector.h +++ b/src/core/domains/interval/codac2_IntervalVector.h @@ -1,110 +1,26 @@ /** * \file codac2_IntervalVector.h - * - * This class reuses some of the functions developed for ibex::IntervalVector. - * The original IBEX code is revised in modern C++ and adapted to the template - * structure proposed in Codac, based on the Eigen library. - * See ibex::IntervalVector (IBEX lib, author: Gilles Chabert) - * * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou, Gilles Chabert + * \author Simon Rohou * \copyright Copyright 2023 Codac Team * \license GNU Lesser General Public License (LGPL) */ #pragma once -#include "codac2_assert.h" +#include "codac2_matrices.h" #include "codac2_Vector.h" -#include "codac2_IntervalMatrixBase.h" -#include "codac2_VectorBase.h" -#include "codac2_IntervalMatrix.h" namespace codac2 { - class IntervalVector : public IntervalMatrixBase, public VectorBase - { - public: - - explicit IntervalVector(size_t n); - - explicit IntervalVector(size_t n, const Interval& x); - - explicit IntervalVector(size_t n, const double bounds[][2]); - - IntervalVector(const Vector& x); - - explicit IntervalVector(const Vector& lb, const Vector& ub); - - IntervalVector(std::initializer_list l); - - IntervalVector(const MatrixBase& x); - - IntervalVector(const MatrixBase& x); - - template - IntervalVector(const Eigen::MatrixBase& x) - : MatrixBase(x.template cast()), - IntervalMatrixBase(x.template cast()), - VectorBase(x.template cast()) - { - assert_release(x.cols() == 1); - } - - template - IntervalVector(const MatrixBaseBlock& x) - : IntervalVector(x.eval()) - { - assert_release(x._q == 1); // column block only - } - - Interval& operator()(size_t i, size_t j) = delete; - const Interval& operator()(size_t i, size_t j) const = delete; - - friend bool operator==(const IntervalVector& x1, const IntervalVector& x2); - - std::list complementary() const; - - std::list diff(const IntervalVector& y, bool compactness = true) const; - - static IntervalVector empty(size_t n); - - // Operators - - IntervalVector& operator+=(const IntervalVector& x) - { - assert_release(this->size() == x.size()); - this->_e += x._e; - return *this; - } - - IntervalVector& operator-=(const IntervalVector& x) - { - assert_release(this->size() == x.size()); - this->_e -= x._e; - return *this; - } - - IntervalVector& operator*=(const Interval& x) - { - this->_e *= x; - return *this; - } - - IntervalVector& operator/=(const Interval& x) - { - this->_e /= x; - return *this; - } - }; - - std::ostream& operator<<(std::ostream& os, const IntervalVector& x); - + using IntervalVector = Eigen::Matrix; inline IntervalVector to_IntervalVector(const Interval& x) { - return IntervalVector(1,x); + IntervalVector a(1); + a[0] = x; + return a; } inline IntervalVector to_IntervalVector(const IntervalVector& x) @@ -112,19 +28,25 @@ namespace codac2 return x; } + inline IntervalVector to_IntervalVector(const Vector& x) + { + return x.template cast(); + } + template - requires ((std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) && ...) + requires ((std::is_same_v || std::is_same_v || std::is_same_v + || std::is_same_v || std::is_same_v) && ...) inline IntervalVector cart_prod(const X&... x) { std::vector v_x; ((v_x.push_back(to_IntervalVector(x))), ...); - size_t n = 0; + Index n = 0; for(const auto& xi : v_x) n += xi.size(); IntervalVector x_(n); - size_t i = 0; + Index i = 0; for(const auto& xi : v_x) { x_.put(i, xi); @@ -133,12 +55,15 @@ namespace codac2 return x_; } - inline IntervalVector hull(const std::list& l) + inline std::ostream& operator<<(std::ostream& os, const IntervalVector& x) { - assert_release(!l.empty()); - IntervalVector h(l.front()); - for(const auto& li : l) - h |= li; - return h; + if(x.is_empty()) + return os << "[ empty vector ]"; + + else + { + os << x.format(codac_vector_fmt()); + return os; + } } } \ No newline at end of file diff --git a/src/core/domains/interval/codac2_Interval_operations.cpp b/src/core/domains/interval/codac2_Interval_operations.cpp index 9af5818a..8b1ce5ac 100644 --- a/src/core/domains/interval/codac2_Interval_operations.cpp +++ b/src/core/domains/interval/codac2_Interval_operations.cpp @@ -21,245 +21,13 @@ using namespace std; namespace codac2 { - const Interval& operator+(const Interval& x) + Interval operator-(double x, const Interval& y) { - return x; + return ibex::operator-(x, y); } - #define interval_arithm_op(f) \ - Interval f(const Interval& x, const Interval& y) \ - { \ - return ibex::f(x, y); \ - } \ - Interval f(double x, const Interval& y) \ - { \ - return ibex::f(x, y); \ - } \ - Interval f(const Interval& x, double y) \ - { \ - return ibex::f(x, y); \ - } \ - - interval_arithm_op(operator&) - interval_arithm_op(operator|) - interval_arithm_op(operator+) - interval_arithm_op(operator-) - interval_arithm_op(operator*) - interval_arithm_op(operator/) - - #define unary_interval_op(f) \ - Interval f(const Interval& x) \ - { \ - return ibex::f(x); \ - } \ - - #define binary_interval_op(f) \ - Interval f(const Interval& x, const Interval& y) \ - { \ - return ibex::f(x, y); \ - } \ - - unary_interval_op(sqr) - unary_interval_op(sqrt) - - Interval pow(const Interval& x, int n) - { - return ibex::pow(x, n); - } - - Interval pow(const Interval& x, double d) - { - return ibex::pow(x, d); - } - - binary_interval_op(pow) - - Interval root(const Interval& x, int n) - { - return ibex::root(x, n); - } - - unary_interval_op(exp) - unary_interval_op(log) - unary_interval_op(cos) - unary_interval_op(sin) - unary_interval_op(tan) - unary_interval_op(acos) - unary_interval_op(asin) - unary_interval_op(atan) - binary_interval_op(atan2) - unary_interval_op(cosh) - unary_interval_op(sinh) - unary_interval_op(tanh) - unary_interval_op(acosh) - unary_interval_op(asinh) - unary_interval_op(atanh) - unary_interval_op(abs) - binary_interval_op(min) - binary_interval_op(max) - unary_interval_op(sign) - unary_interval_op(integer) - unary_interval_op(floor) - unary_interval_op(ceil) - - void bwd_add(const Interval& y, Interval& x1, Interval& x2) - { - ibex::bwd_add(y,x1,x2); - } - - void bwd_sub(const Interval& y, Interval& x1, Interval& x2) - { - ibex::bwd_sub(y,x1,x2); - } - - void bwd_mul(const Interval& y, Interval& x1, Interval& x2) - { - ibex::bwd_mul(y,x1,x2); - } - - void bwd_div(const Interval& y, Interval& x1, Interval& x2) - { - ibex::bwd_div(y,x1,x2); - } - - void bwd_sqr(const Interval& y, Interval& x) - { - ibex::bwd_sqr(y,x); - } - - void bwd_sqrt(const Interval& y, Interval& x) - { - ibex::bwd_sqrt(y,x); - } - - void bwd_pow(const Interval& y, Interval& x, int p) - { - ibex::bwd_pow(y,p,x); - } - - void bwd_pow(const Interval& y, Interval& x, Interval& p) - { - assert(p.is_degenerated() && "bwd_power(y,x1,x2) (with x1 and x2 intervals) not implemented yet with Gaol"); - ibex::bwd_pow(y,p.mid(),x); - } - - void bwd_root(const Interval& y, Interval& x, int p) - { - ibex::bwd_root(y,p,x); - } - - void bwd_exp(const Interval& y, Interval& x) - { - ibex::bwd_exp(y,x); - } - - void bwd_log(const Interval& y, Interval& x) - { - ibex::bwd_log(y,x); - } - - void bwd_cos(const Interval& y, Interval& x) - { - ibex::bwd_cos(y,x); - } - - void bwd_sin(const Interval& y, Interval& x) - { - ibex::bwd_sin(y,x); - } - - void bwd_tan(const Interval& y, Interval& x) - { - ibex::bwd_tan(y,x); - } - - void bwd_acos(const Interval& y, Interval& x) - { - ibex::bwd_acos(y,x); - } - - void bwd_asin(const Interval& y, Interval& x) - { - ibex::bwd_asin(y,x); - } - - void bwd_atan(const Interval& y, Interval& x) - { - ibex::bwd_atan(y,x); - } - - void bwd_atan2(const Interval& y, Interval& x1, Interval& x2) - { - ibex::bwd_atan2(y,x1,x2); - } - - void bwd_cosh(const Interval& y, Interval& x) - { - ibex::bwd_cosh(y,x); - } - - void bwd_sinh(const Interval& y, Interval& x) - { - ibex::bwd_sinh(y,x); - } - - void bwd_tanh(const Interval& y, Interval& x) - { - ibex::bwd_tanh(y,x); - } - - void bwd_acosh(const Interval& y, Interval& x) - { - ibex::bwd_acosh(y,x); - } - - void bwd_asinh(const Interval& y, Interval& x) - { - ibex::bwd_asinh(y,x); - } - - void bwd_atanh(const Interval& y, Interval& x) - { - ibex::bwd_atanh(y,x); - } - - void bwd_abs(const Interval& y, Interval& x) - { - ibex::bwd_abs(y,x); - } - - void bwd_min(const Interval& y, Interval& x1, Interval& x2) - { - ibex::bwd_min(y,x1,x2); - } - - void bwd_max(const Interval& y, Interval& x1, Interval& x2) - { - ibex::bwd_max(y,x1,x2); - } - - void bwd_sign(const Interval& y, Interval& x) - { - ibex::bwd_sign(y,x); - } - - void bwd_floor(const Interval& y, Interval& x) - { - ibex::bwd_floor(y,x); - } - - void bwd_ceil(const Interval& y, Interval& x) - { - ibex::bwd_ceil(y,x); - } - - void bwd_saw(const Interval& y, Interval& x) - { - ibex::bwd_saw(y,x); - } - - void bwd_imod(Interval& x, Interval& y, double p) + Interval operator-(const Interval& x, double y) { - ibex::bwd_imod(x,y,p); + return ibex::operator-(x, y); } -} // namespace codac \ No newline at end of file +} \ No newline at end of file diff --git a/src/core/domains/interval/codac2_Interval_operations.h b/src/core/domains/interval/codac2_Interval_operations.h index 10cb3094..3a27fd10 100644 --- a/src/core/domains/interval/codac2_Interval_operations.h +++ b/src/core/domains/interval/codac2_Interval_operations.h @@ -29,7 +29,10 @@ namespace codac2 * \param y interval value * \return intersection result */ - Interval operator&(const Interval& x, const Interval& y); + inline Interval operator&(const Interval& x, const Interval& y) + { + return ibex::operator&(x,y); + } /** * \brief Returns the squared-union of two intervals: \f$[x]\sqcup[y]\f$ @@ -40,7 +43,10 @@ namespace codac2 * \param y interval value * \return squared-union result */ - Interval operator|(const Interval& x, const Interval& y); + inline Interval operator|(const Interval& x, const Interval& y) + { + return ibex::operator|(x,y); + } /** * \brief Returns this @@ -50,7 +56,10 @@ namespace codac2 * \param x interval value * \return the same interval */ - const Interval& operator+(const Interval& x); + inline const Interval& operator+(const Interval& x) + { + return x; + } /** * \brief Returns \f$[x]+y\f$ with \f$y\in\mathbb{R}\f$ @@ -59,7 +68,10 @@ namespace codac2 * \param y real value * \return the addition result */ - Interval operator+(const Interval& x, double y); + inline Interval operator+(const Interval& x, double y) + { + return ibex::operator+(x,y); + } /** * \brief Returns \f$x+[y]\f$ with \f$x\in\mathbb{R}\f$ @@ -68,7 +80,10 @@ namespace codac2 * \param y interval value * \return the addition result */ - Interval operator+(double x, const Interval& y); + inline Interval operator+(double x, const Interval& y) + { + return ibex::operator+(x,y); + } /** * \brief Returns \f$[x]+[y]\f$ @@ -77,7 +92,10 @@ namespace codac2 * \param y interval value * \return the addition result */ - Interval operator+(const Interval& x, const Interval& y); + inline Interval operator+(const Interval& x, const Interval& y) + { + return ibex::operator+(x,y); + } /** * \brief Returns \f$[x]-y\f$ with \f$y\in\mathbb{R}\f$ @@ -104,7 +122,10 @@ namespace codac2 * \param y interval value * \return the substraction result */ - Interval operator-(const Interval& x, const Interval& y); + inline Interval operator-(const Interval& x, const Interval& y) + { + return ibex::operator-(x, y); + } /** * \brief Returns \f$[x]*y\f$ with \f$y\in\mathbb{R}\f$ @@ -113,7 +134,10 @@ namespace codac2 * \param y real value * \return the multiplication result */ - Interval operator*(const Interval& x, double y); + inline Interval operator*(const Interval& x, double y) + { + return ibex::operator*(x,y); + } /** * \brief Returns \f$x*[y]\f$ with \f$x\in\mathbb{R}\f$ @@ -122,7 +146,10 @@ namespace codac2 * \param y interval value * \return the multiplication result */ - Interval operator*(double x, const Interval& y); + inline Interval operator*(double x, const Interval& y) + { + return ibex::operator*(x,y); + } /** * \brief Returns \f$[x]*[y]\f$ @@ -131,7 +158,10 @@ namespace codac2 * \param y interval value * \return the multiplication result */ - Interval operator*(const Interval& x, const Interval& y); + inline Interval operator*(const Interval& x, const Interval& y) + { + return ibex::operator*(x,y); + } /** * \brief Returns \f$[x]/y\f$ with \f$y\in\mathbb{R}\f$ @@ -140,7 +170,10 @@ namespace codac2 * \param y real value * \return the division result */ - Interval operator/(const Interval& x, double y); + inline Interval operator/(const Interval& x, double y) + { + return ibex::operator/(x,y); + } /** * \brief Returns \f$x/[y]\f$ with \f$x\in\mathbb{R}\f$ @@ -149,7 +182,10 @@ namespace codac2 * \param y interval value * \return the division result */ - Interval operator/(double x, const Interval& y); + inline Interval operator/(double x, const Interval& y) + { + return ibex::operator/(x,y); + } /** * \brief Returns \f$[x]/[y]\f$ @@ -158,7 +194,10 @@ namespace codac2 * \param y interval value * \return the division result */ - Interval operator/(const Interval& x, const Interval& y); + inline Interval operator/(const Interval& x, const Interval& y) + { + return ibex::operator/(x,y); + } /** * \brief Returns \f$[x]^2\f$ @@ -166,7 +205,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval sqr(const Interval& x); + inline Interval sqr(const Interval& x) + { + return ibex::sqr(x); + } /** * \brief Returns \f$\sqrt{[x]}\f$ @@ -174,7 +216,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval sqrt(const Interval& x); + inline Interval sqrt(const Interval& x) + { + return ibex::sqrt(x); + } /** * \brief Returns \f$[x]^n\f$, \f$n\in\mathbb{Z}\f$ @@ -183,7 +228,10 @@ namespace codac2 * \param n integer power value * \return the operation result */ - Interval pow(const Interval& x, int n); + inline Interval pow(const Interval& x, int n) + { + return ibex::pow(x,n); + } /** * \brief Returns \f$[x]^d\f$, \f$d\in\mathbb{R}\f$ @@ -192,7 +240,10 @@ namespace codac2 * \param d real power value * \return the operation result */ - Interval pow(const Interval& x, double d); + inline Interval pow(const Interval& x, double d) + { + return ibex::pow(x,d); + } /** * \brief Returns \f$[x]^{[y]}\f$, \f$y\in\mathbb{IR}\f$ @@ -201,7 +252,10 @@ namespace codac2 * \param y interval power value * \return the operation result */ - Interval pow(const Interval& x, const Interval& y); + inline Interval pow(const Interval& x, const Interval& y) + { + return ibex::pow(x,y); + } /** * \brief Returns the n-th root: \f$\sqrt[n]{[x]}\f$ @@ -210,7 +264,10 @@ namespace codac2 * \param n integer root * \return the operation result */ - Interval root(const Interval& x, int n); + inline Interval root(const Interval& x, int n) + { + return ibex::root(x,n); + } /** * \brief Returns \f$\exp([x])\f$ @@ -218,7 +275,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval exp(const Interval& x); + inline Interval exp(const Interval& x) + { + return ibex::exp(x); + } /** * \brief Returns \f$\log([x])\f$ @@ -226,7 +286,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval log(const Interval& x); + inline Interval log(const Interval& x) + { + return ibex::log(x); + } /** * \brief Returns \f$\cos([x])\f$ @@ -234,7 +297,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval cos(const Interval& x); + inline Interval cos(const Interval& x) + { + return ibex::cos(x); + } /** * \brief Returns \f$\sin([x])\f$ @@ -242,7 +308,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval sin(const Interval& x); + inline Interval sin(const Interval& x) + { + return ibex::sin(x); + } /** * \brief Returns \f$\tan([x])\f$ @@ -250,7 +319,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval tan(const Interval& x); + inline Interval tan(const Interval& x) + { + return ibex::tan(x); + } /** * \brief Returns \f$\acos([x])\f$ @@ -258,7 +330,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval acos(const Interval& x); + inline Interval acos(const Interval& x) + { + return ibex::acos(x); + } /** * \brief Returns \f$\asin([x])\f$ @@ -266,7 +341,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval asin(const Interval& x); + inline Interval asin(const Interval& x) + { + return ibex::asin(x); + } /** * \brief Returns \f$\atan([x])\f$ @@ -274,7 +352,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval atan(const Interval& x); + inline Interval atan(const Interval& x) + { + return ibex::atan(x); + } /** * \brief Returns \f$\mathrm{arctan2}([y],[x])\f$ @@ -283,7 +364,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval atan2(const Interval& y, const Interval& x); + inline Interval atan2(const Interval& y, const Interval& x) + { + return ibex::atan2(y,x); + } /** * \brief Returns \f$\cosh([x])\f$ @@ -291,7 +375,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval cosh(const Interval& x); + inline Interval cosh(const Interval& x) + { + return ibex::cosh(x); + } /** * \brief Returns \f$\sinh([x])\f$ @@ -299,7 +386,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval sinh(const Interval& x); + inline Interval sinh(const Interval& x) + { + return ibex::sinh(x); + } /** * \brief Returns \f$\tanh([x])\f$ @@ -307,7 +397,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval tanh(const Interval& x); + inline Interval tanh(const Interval& x) + { + return ibex::tanh(x); + } /** * \brief Returns \f$\acosh([x])\f$ @@ -315,7 +408,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval acosh(const Interval& x); + inline Interval acosh(const Interval& x) + { + return ibex::acosh(x); + } /** * \brief Returns \f$\asinh([x])\f$ @@ -323,7 +419,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval asinh(const Interval& x); + inline Interval asinh(const Interval& x) + { + return ibex::asinh(x); + } /** * \brief Returns \f$\atanh([x])\f$ @@ -331,7 +430,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval atanh(const Interval& x); + inline Interval atanh(const Interval& x) + { + return ibex::atanh(x); + } /** * \brief Returns \f$\mid[x]\mid = \left\{\mid x \mid, x\in[x]\right\}\f$ @@ -339,7 +441,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval abs(const Interval& x); + inline Interval abs(const Interval& x) + { + return ibex::abs(x); + } /** * \brief Returns \f$\min([x],[y])=\left\{\min(x,y), x\in[x], y\in[y]\right\}\f$ @@ -348,7 +453,10 @@ namespace codac2 * \param y interval value * \return the operation result */ - Interval min(const Interval& x, const Interval& y); + inline Interval min(const Interval& x, const Interval& y) + { + return ibex::min(x,y); + } /** * \brief Returns \f$\max([x],[y])=\left\{\max(x,y), x\in[x], y\in[y]\right\}\f$ @@ -357,7 +465,10 @@ namespace codac2 * \param y interval value * \return the operation result */ - Interval max(const Interval& x, const Interval& y); + inline Interval max(const Interval& x, const Interval& y) + { + return ibex::max(x,y); + } /** * \brief Returns \f$\sign([x])=\left[\left\{\sign(x), x\in[x]\right\}\right]\f$ @@ -367,7 +478,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval sign(const Interval& x); + inline Interval sign(const Interval& x) + { + return ibex::sign(x); + } /** * \brief Returns the largest integer interval included in \f$[x]\f$ @@ -375,7 +489,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval integer(const Interval& x); + inline Interval integer(const Interval& x) + { + return ibex::integer(x); + } /** * \brief Returns floor of \f$[x]\f$ @@ -383,7 +500,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval floor(const Interval& x); + inline Interval floor(const Interval& x) + { + return ibex::floor(x); + } /** * \brief Returns ceil of \f$[x]\f$ @@ -391,7 +511,10 @@ namespace codac2 * \param x interval value * \return the operation result */ - Interval ceil(const Interval& x); + inline Interval ceil(const Interval& x) + { + return ibex::ceil(x); + } /** * \brief Computes the backward (reverse) addition @@ -403,7 +526,10 @@ namespace codac2 * \param x1 prior value for \f$[x_1]\f$, may be contracted * \param x2 prior value for \f$[x_2]\f$, may be contracted */ - void bwd_add(const Interval& y, Interval& x1, Interval& x2); + inline void bwd_add(const Interval& y, Interval& x1, Interval& x2) + { + ibex::bwd_add(y,x1,x2); + } /** * \brief Computes the backward (reverse) substraction @@ -415,7 +541,10 @@ namespace codac2 * \param x1 prior value for \f$[x_1]\f$, may be contracted * \param x2 prior value for \f$[x_2]\f$, may be contracted */ - void bwd_sub(const Interval& y, Interval& x1, Interval& x2); + inline void bwd_sub(const Interval& y, Interval& x1, Interval& x2) + { + ibex::bwd_sub(y,x1,x2); + } /** * \brief Computes the backward (reverse) multiplication @@ -427,7 +556,10 @@ namespace codac2 * \param x1 prior value for \f$[x_1]\f$, may be contracted * \param x2 prior value for \f$[x_2]\f$, may be contracted */ - void bwd_mul(const Interval& y, Interval& x1, Interval& x2); + inline void bwd_mul(const Interval& y, Interval& x1, Interval& x2) + { + ibex::bwd_mul(y,x1,x2); + } /** * \brief Computes the backward (reverse) division @@ -439,7 +571,10 @@ namespace codac2 * \param x1 prior value for \f$[x_1]\f$, may be contracted * \param x2 prior value for \f$[x_2]\f$, may be contracted */ - void bwd_div(const Interval& y, Interval& x1, Interval& x2); + inline void bwd_div(const Interval& y, Interval& x1, Interval& x2) + { + ibex::bwd_div(y,x1,x2); + } /** * \brief Computes the backward (reverse) squared operation @@ -450,7 +585,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_sqr(const Interval& y, Interval& x); + inline void bwd_sqr(const Interval& y, Interval& x) + { + ibex::bwd_sqr(y,x); + } /** * \brief Computes the backward (reverse) squared-root operation @@ -461,7 +599,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_sqrt(const Interval& y, Interval& x); + inline void bwd_sqrt(const Interval& y, Interval& x) + { + ibex::bwd_sqrt(y,x); + } /** * \brief Computes the backward (reverse) power operation @@ -473,7 +614,10 @@ namespace codac2 * \param x prior value for \f$[x]\f$, may be contracted * \param p power integer value */ - void bwd_pow(const Interval& y, Interval& x, int p); + inline void bwd_pow(const Interval& y, Interval& x, int p) + { + ibex::bwd_pow(y,p,x); + } /** * \brief Computes the backward (reverse) power operation @@ -485,7 +629,11 @@ namespace codac2 * \param x prior value for \f$[x]\f$, may be contracted * \param p prior value for \f$[p]\f$, may be contracted */ - void bwd_pow(const Interval& y, Interval& x, Interval& p); + inline void bwd_pow(const Interval& y, Interval& x, Interval& p) + { + assert(p.is_degenerated() && "bwd_power(y,x1,x2) (with x1 and x2 intervals) not implemented yet with Gaol"); + ibex::bwd_pow(y,p.mid(),x); + } /** * \brief Computes the backward (reverse) root operation @@ -497,7 +645,10 @@ namespace codac2 * \param x prior value for \f$[x]\f$, may be contracted * \param p root integer value */ - void bwd_root(const Interval& y, Interval& x, int p); + inline void bwd_root(const Interval& y, Interval& x, int p) + { + ibex::bwd_root(y,p,x); + } /** * \brief Computes the backward (reverse) exponential operation @@ -508,7 +659,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_exp(const Interval& y, Interval& x); + inline void bwd_exp(const Interval& y, Interval& x) + { + ibex::bwd_exp(y,x); + } /** * \brief Computes the backward (reverse) logarithmic operation @@ -519,7 +673,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_log(const Interval& y, Interval& x); + inline void bwd_log(const Interval& y, Interval& x) + { + ibex::bwd_log(y,x); + } /** * \brief Computes the backward (reverse) cosine operation @@ -530,7 +687,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_cos(const Interval& y, Interval& x); + inline void bwd_cos(const Interval& y, Interval& x) + { + ibex::bwd_cos(y,x); + } /** * \brief Computes the backward (reverse) sine operation @@ -541,7 +701,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_sin(const Interval& y, Interval& x); + inline void bwd_sin(const Interval& y, Interval& x) + { + ibex::bwd_sin(y,x); + } /** * \brief Computes the backward (reverse) tangent operation @@ -552,7 +715,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_tan(const Interval& y, Interval& x); + inline void bwd_tan(const Interval& y, Interval& x) + { + ibex::bwd_tan(y,x); + } /** * \brief Computes the backward (reverse) arccos operation @@ -563,7 +729,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_acos(const Interval& y, Interval& x); + inline void bwd_acos(const Interval& y, Interval& x) + { + ibex::bwd_acos(y,x); + } /** * \brief Computes the backward (reverse) arcsin operation @@ -574,7 +743,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_asin(const Interval& y, Interval& x); + inline void bwd_asin(const Interval& y, Interval& x) + { + ibex::bwd_asin(y,x); + } /** * \brief Computes the backward (reverse) arctan operation @@ -585,7 +757,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_atan(const Interval& y, Interval& x); + inline void bwd_atan(const Interval& y, Interval& x) + { + ibex::bwd_atan(y,x); + } /** * \brief Computes the backward (reverse) arctan2 operation @@ -597,7 +772,10 @@ namespace codac2 * \param x1 prior value for \f$[x_1]\f$, may be contracted * \param x2 prior value for \f$[x_2]\f$, may be contracted */ - void bwd_atan2(const Interval& y, Interval& x1, Interval& x2); + inline void bwd_atan2(const Interval& y, Interval& x1, Interval& x2) + { + ibex::bwd_atan2(y,x1,x2); + } /** * \brief Computes the backward (reverse) hyperbolic cosine operation @@ -608,7 +786,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_cosh(const Interval& y, Interval& x); + inline void bwd_cosh(const Interval& y, Interval& x) + { + ibex::bwd_cosh(y,x); + } /** * \brief Computes the backward (reverse) hyperbolic sine operation @@ -619,7 +800,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_sinh(const Interval& y, Interval& x); + inline void bwd_sinh(const Interval& y, Interval& x) + { + ibex::bwd_sinh(y,x); + } /** * \brief Computes the backward (reverse) hyperbolic tangent operation @@ -630,7 +814,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_tanh(const Interval& y, Interval& x); + inline void bwd_tanh(const Interval& y, Interval& x) + { + ibex::bwd_tanh(y,x); + } /** * \brief Computes the backward (reverse) hyperbolic arccos operation @@ -641,7 +828,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_acosh(const Interval& y, Interval& x); + inline void bwd_acosh(const Interval& y, Interval& x) + { + ibex::bwd_acosh(y,x); + } /** * \brief Computes the backward (reverse) hyperbolic arcsin operation @@ -652,7 +842,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_asinh(const Interval& y, Interval& x); + inline void bwd_asinh(const Interval& y, Interval& x) + { + ibex::bwd_asinh(y,x); + } /** * \brief Computes the backward (reverse) hyperbolic arctan operation @@ -663,7 +856,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_atanh(const Interval& y, Interval& x); + inline void bwd_atanh(const Interval& y, Interval& x) + { + ibex::bwd_atanh(y,x); + } /** * \brief Computes the backward (reverse) absolute-value operation @@ -674,7 +870,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_abs(const Interval& y, Interval& x); + inline void bwd_abs(const Interval& y, Interval& x) + { + ibex::bwd_abs(y,x); + } /** * \brief Computes the backward (reverse) of the max operation @@ -686,7 +885,10 @@ namespace codac2 * \param x1 prior value for \f$[x_1]\f$, may be contracted * \param x2 prior value for \f$[x_2]\f$, may be contracted */ - void bwd_min(const Interval& y, Interval& x1, Interval& x2); + inline void bwd_min(const Interval& y, Interval& x1, Interval& x2) + { + ibex::bwd_min(y,x1,x2); + } /** * \brief Computes the backward (reverse) of the min operation @@ -698,7 +900,10 @@ namespace codac2 * \param x1 prior value for \f$[x_1]\f$, may be contracted * \param x2 prior value for \f$[x_2]\f$, may be contracted */ - void bwd_max(const Interval& y, Interval& x1, Interval& x2); + inline void bwd_max(const Interval& y, Interval& x1, Interval& x2) + { + ibex::bwd_max(y,x1,x2); + } /** * \brief Computes the backward (reverse) sign operation @@ -709,7 +914,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_sign(const Interval& y, Interval& x); + inline void bwd_sign(const Interval& y, Interval& x) + { + ibex::bwd_sign(y,x); + } /** * \brief Computes the backward (reverse) floor operation @@ -720,7 +928,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_floor(const Interval& y, Interval& x); + inline void bwd_floor(const Interval& y, Interval& x) + { + ibex::bwd_floor(y,x); + } /** * \brief Computes the backward (reverse) ceil operation @@ -731,7 +942,10 @@ namespace codac2 * \param y interval value (result of the forward operation) * \param x prior value for \f$[x]\f$, may be contracted */ - void bwd_ceil(const Interval& y, Interval& x); + inline void bwd_ceil(const Interval& y, Interval& x) + { + ibex::bwd_ceil(y,x); + } /** * \brief Contract \f$[x_1]\f$ and \f$[x_2]\f$ w.r.t. the fact that they are equivalent modulo the period \f$p\f$ @@ -740,6 +954,9 @@ namespace codac2 * \param x2 prior value for \f$[x_2]\f$, may be contracted * \param p period value */ - void bwd_imod(Interval& x1, Interval& x2, double p); + inline void bwd_imod(Interval& x1, Interval& x2, double p) + { + ibex::bwd_imod(x1,x2,p); + } } \ No newline at end of file diff --git a/src/core/domains/paving/codac2_Paving.cpp b/src/core/domains/paving/codac2_Paving.cpp index 4b810b0c..f7eb538d 100644 --- a/src/core/domains/paving/codac2_Paving.cpp +++ b/src/core/domains/paving/codac2_Paving.cpp @@ -17,7 +17,7 @@ namespace codac2 { // PavingOut class - PavingOut::PavingOut(size_t n) + PavingOut::PavingOut(Index n) : Paving(n) { assert_release(n > 0); @@ -77,7 +77,7 @@ namespace codac2 // PavingInOut class - PavingInOut::PavingInOut(size_t n) + PavingInOut::PavingInOut(Index n) : Paving(n) { assert_release(n > 0); diff --git a/src/core/domains/paving/codac2_Paving.h b/src/core/domains/paving/codac2_Paving.h index 210bcedd..27ba92fa 100644 --- a/src/core/domains/paving/codac2_Paving.h +++ b/src/core/domains/paving/codac2_Paving.h @@ -32,7 +32,7 @@ namespace codac2 using NodeValue_ = std::function(Node_)>; using ConnectedSubset_ = Subpaving

; - Paving(size_t n) + Paving(Index n) : Paving(IntervalVector(n)) { assert_release(n > 0); @@ -42,7 +42,7 @@ namespace codac2 : _tree(std::make_shared>(*static_cast(this), x)) { } - size_t size() const + Index size() const { return std::get<0>(_tree->boxes()).size(); } @@ -85,7 +85,7 @@ namespace codac2 std::list connected_subsets(const IntervalVector& x0, const NodeValue_& node_value) const { std::list l_boxes = intersecting_boxes(x0, node_value); - size_t nb_boxes = l_boxes.size(); + [[maybe_unused]] Index nb_boxes = l_boxes.size(); std::list l_subsets; while(!l_boxes.empty()) @@ -115,7 +115,7 @@ namespace codac2 } assert(l_boxes.empty() && "all the nodes should have been visited"); - assert([&]() -> bool { size_t s = 0; for(const auto& si : l_subsets) s += si.size(); return s == nb_boxes; } () + assert([&]() -> bool { Index s = 0; for(const auto& si : l_subsets) s += si.size(); return s == nb_boxes; } () && "the total number of boxes should match the sum of number of boxes of each subset"); return l_subsets; @@ -141,7 +141,7 @@ namespace codac2 { public: - PavingOut(size_t n); + PavingOut(Index n); PavingOut(const IntervalVector& x); std::list connected_subsets(const PavingOut::NodeValue_& node_value = PavingOut::outer) const; @@ -158,7 +158,7 @@ namespace codac2 { public: - PavingInOut(size_t n); + PavingInOut(Index n); PavingInOut(const IntervalVector& x); std::list connected_subsets(const PavingInOut::NodeValue_& node_value = PavingInOut::outer) const; diff --git a/src/core/domains/paving/codac2_Subpaving.h b/src/core/domains/paving/codac2_Subpaving.h index 9fd794d6..1aeedcf6 100644 --- a/src/core/domains/paving/codac2_Subpaving.h +++ b/src/core/domains/paving/codac2_Subpaving.h @@ -114,7 +114,7 @@ namespace codac2 assert_release(!l.empty()); assert_release(l.front().size() == 2 && "only 2d contours can be sorted"); - const size_t nl = l.size(); + const Index nl = l.size(); Vector current_pt = l.front().ub(), first_pt = current_pt; std::list s { l.front() }; diff --git a/src/core/functions/analytic/codac2_AnalyticExpr.h b/src/core/functions/analytic/codac2_AnalyticExpr.h index b1187ffc..134d62a2 100644 --- a/src/core/functions/analytic/codac2_AnalyticExpr.h +++ b/src/core/functions/analytic/codac2_AnalyticExpr.h @@ -28,7 +28,7 @@ namespace codac2 AnalyticExpr& operator=(const AnalyticExpr& x) = delete; - virtual T fwd_eval(ValuesMap& v, size_t total_input_size) const = 0; + virtual T fwd_eval(ValuesMap& v, Index total_input_size) const = 0; virtual void bwd_eval(ValuesMap& v) const = 0; T init_value(ValuesMap& v, const T& x) const @@ -77,7 +77,7 @@ namespace codac2 return OperationExprBase...>::replace_expr(old_expr_id, new_expr); } - Y fwd_eval(ValuesMap& v, size_t total_input_size) const + Y fwd_eval(ValuesMap& v, Index total_input_size) const { return std::apply( [this,&v,total_input_size](auto &&... x) @@ -120,7 +120,7 @@ namespace codac2 { public: - AnalyticOperationExpr(const std::shared_ptr>& x1, size_t i) + AnalyticOperationExpr(const std::shared_ptr>& x1, Index i) : OperationExprBase>(x1), _i(i) { } @@ -138,7 +138,7 @@ namespace codac2 return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - ScalarOpValue fwd_eval(ValuesMap& v, size_t total_input_size) const + ScalarOpValue fwd_eval(ValuesMap& v, Index total_input_size) const { return AnalyticExpr::init_value( v, ComponentOp::fwd(std::get<0>(this->_x)->fwd_eval(v, total_input_size), _i)); @@ -157,7 +157,7 @@ namespace codac2 protected: - const size_t _i; + const Index _i; }; template<> @@ -165,7 +165,7 @@ namespace codac2 { public: - AnalyticOperationExpr(const std::shared_ptr>& x1, size_t i, size_t j) + AnalyticOperationExpr(const std::shared_ptr>& x1, Index i, Index j) : OperationExprBase>(x1), _i(i), _j(j) { } @@ -183,7 +183,7 @@ namespace codac2 return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - VectorOpValue fwd_eval(ValuesMap& v, size_t total_input_size) const + VectorOpValue fwd_eval(ValuesMap& v, Index total_input_size) const { return AnalyticExpr::init_value( v, SubvectorOp::fwd(std::get<0>(this->_x)->fwd_eval(v, total_input_size), _i, _j)); @@ -202,6 +202,6 @@ namespace codac2 protected: - const size_t _i, _j; + const Index _i, _j; }; } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index 0ec6f37e..b5a45a14 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -112,7 +112,27 @@ namespace codac2 return eval_(x...).da; } - friend std::ostream& operator<<(std::ostream& os, const AnalyticFunction& f) + Index output_size() const + { + if constexpr(std::is_same_v) + return 1; + + else if constexpr(std::is_same_v) + { + // A dump evaluation is performed to estimate the dimension + // of the image of this function. A natural evaluation is assumed + // to be faster. + return natural_eval(IntervalVector(this->input_size())).size(); + } + + else + { + assert_release(false && "unable to estimate output size"); + return 0; + } + } + + friend std::ostream& operator<<(std::ostream& os, [[maybe_unused]] const AnalyticFunction& f) { if constexpr(std::is_same_v) os << "scalar function"; @@ -127,18 +147,18 @@ namespace codac2 friend class CtcInverse; template - void add_value_to_arg_map(ValuesMap& v, const D& x, size_t i) const + void add_value_to_arg_map(ValuesMap& v, const D& x, Index i) const { - assert(i >= 0 && i < this->args().size()); + assert(i >= 0 && i < (Index)this->args().size()); assert_release(size_of(x) == this->args()[i]->size() && "provided arguments do not match function inputs"); - IntervalMatrix d = IntervalMatrix::zeros(size_of(x), this->args().total_size()); + IntervalMatrix d = IntervalMatrix::zero(size_of(x), this->args().total_size()); - size_t p = 0, j = 0; + Index p = 0, j = 0; for( ; j < i ; j++) p += this->args()[j]->size(); - for(size_t k = p ; k < p+size_of(x) ; k++) + for(Index k = p ; k < p+size_of(x) ; k++) d(k-p,k) = 1.; using D_DOMAIN = typename Wrapper::Domain; @@ -150,12 +170,12 @@ namespace codac2 template void fill_from_args(ValuesMap& v, const Args&... x) const { - size_t i = 0; + Index i = 0; (add_value_to_arg_map(v, x, i++), ...); } template - void intersect_value_from_arg_map(const ValuesMap& v, D& x, size_t i) const + void intersect_value_from_arg_map(const ValuesMap& v, D& x, Index i) const { assert(v.find(this->args()[i]->unique_id()) != v.end() && "argument cannot be found"); x &= std::dynamic_pointer_cast::Domain>(v.at(this->args()[i]->unique_id()))->a; @@ -164,7 +184,7 @@ namespace codac2 template void intersect_from_args(const ValuesMap& v, Args&... x) const { - size_t i = 0; + Index i = 0; (intersect_value_from_arg_map(v, x, i++), ...); } @@ -186,7 +206,7 @@ namespace codac2 template void check_valid_inputs(const Args&... x) const { - size_t n = 0; + [[maybe_unused]] Index n = 0; ((n += size_of(x)), ...); assert_release(this->_args.total_size() == n && diff --git a/src/core/functions/analytic/codac2_analytic_constants.h b/src/core/functions/analytic/codac2_analytic_constants.h index 08b143d1..11af1d00 100644 --- a/src/core/functions/analytic/codac2_analytic_constants.h +++ b/src/core/functions/analytic/codac2_analytic_constants.h @@ -9,6 +9,8 @@ #pragma once +#include "codac2_Index.h" + namespace codac2 { template @@ -27,14 +29,14 @@ namespace codac2 return std::make_shared>(*this); } - T fwd_eval(ValuesMap& v, size_t total_input_size) const + T fwd_eval(ValuesMap& v, Index total_input_size) const { return AnalyticExpr::init_value(v, T( // the mid is not considered for const values in centered form expression: _x, _x, // the derivative of a const value is zero: - IntervalMatrix::zeros(_x.size(),total_input_size), + IntervalMatrix::zero(_x.size(),total_input_size), // the definition domain is necesarily met at this point: true )); @@ -45,10 +47,10 @@ namespace codac2 AnalyticExpr::value(v).a &= _x; } - void replace_expr(const ExprID& old_expr_id, const std::shared_ptr& new_expr) + void replace_expr([[maybe_unused]] const ExprID& old_expr_id, [[maybe_unused]] const std::shared_ptr& new_expr) { } - virtual bool belongs_to_args_list(const FunctionArgsList& args) const + virtual bool belongs_to_args_list([[maybe_unused]] const FunctionArgsList& args) const { return true; } diff --git a/src/core/functions/analytic/codac2_analytic_values.h b/src/core/functions/analytic/codac2_analytic_values.h index d0021c0e..98c09504 100644 --- a/src/core/functions/analytic/codac2_analytic_values.h +++ b/src/core/functions/analytic/codac2_analytic_values.h @@ -10,6 +10,8 @@ #pragma once #include +#include +#include #include #include @@ -59,7 +61,7 @@ namespace codac2 }; template<> - struct Wrapper { + struct Wrapper { using Domain = ScalarOpValue; }; diff --git a/src/core/functions/analytic/codac2_analytic_variables.h b/src/core/functions/analytic/codac2_analytic_variables.h index 7897629d..3ea24a07 100644 --- a/src/core/functions/analytic/codac2_analytic_variables.h +++ b/src/core/functions/analytic/codac2_analytic_variables.h @@ -28,15 +28,15 @@ namespace codac2 return AnalyticExpr::unique_id(); } - T fwd_eval(ValuesMap& v, size_t total_input_size) const + T fwd_eval(ValuesMap& v, [[maybe_unused]] Index total_input_size) const { return AnalyticExpr::value(v); } - void bwd_eval(ValuesMap& v) const + void bwd_eval([[maybe_unused]] ValuesMap& v) const { } - void replace_expr(const ExprID& old_expr_id, const std::shared_ptr& new_expr) + void replace_expr([[maybe_unused]] const ExprID& old_expr_id, [[maybe_unused]] const std::shared_ptr& new_expr) { } operator std::shared_ptr>() const @@ -74,7 +74,7 @@ namespace codac2 return std::make_shared(*this); } - size_t size() const + Index size() const { return 1; } @@ -89,7 +89,7 @@ namespace codac2 { public: - explicit VectorVar(size_t n) + explicit VectorVar(Index n) : _n(n) { assert_release(n > 0); @@ -109,19 +109,19 @@ namespace codac2 return std::make_shared(*this); } - size_t size() const + Index size() const { return _n; } - std::shared_ptr> operator[](size_t i) const + std::shared_ptr> operator[](Index i) const { assert_release(i >= 0 && i < _n); return std::make_shared>( std::dynamic_pointer_cast>(this->copy()), i); } - std::shared_ptr> subvector(size_t i, size_t j) const + std::shared_ptr> subvector(Index i, Index j) const { assert_release(i >= 0 && i < _n && j >= i && j < _n); return std::make_shared>( @@ -130,6 +130,6 @@ namespace codac2 protected: - size_t _n; + Index _n; }; } \ No newline at end of file diff --git a/src/core/functions/codac2_ExprBase.cpp b/src/core/functions/codac2_ExprBase.cpp index 2a9a2997..a4ecbbb6 100644 --- a/src/core/functions/codac2_ExprBase.cpp +++ b/src/core/functions/codac2_ExprBase.cpp @@ -12,7 +12,7 @@ using namespace std; using namespace codac2; -size_t ExprID::_id_counter = 0; +Index ExprID::_id_counter = 0; ExprID::ExprID() : _id(ExprID::_id_counter) @@ -20,7 +20,7 @@ ExprID::ExprID() ExprID::_id_counter ++; } -size_t ExprID::id() const +Index ExprID::id() const { return _id; } diff --git a/src/core/functions/codac2_ExprBase.h b/src/core/functions/codac2_ExprBase.h index e3c82df1..8ae3045d 100644 --- a/src/core/functions/codac2_ExprBase.h +++ b/src/core/functions/codac2_ExprBase.h @@ -26,14 +26,14 @@ namespace codac2 ExprID(); ExprID(const ExprID& i) = default; - size_t id() const; + Index id() const; bool operator==(const ExprID& i) const; bool operator<(const ExprID& i) const; protected: - const size_t _id; - static size_t _id_counter; + const Index _id; + static Index _id_counter; }; class ExprBase : public std::enable_shared_from_this diff --git a/src/core/functions/codac2_FunctionArgsList.h b/src/core/functions/codac2_FunctionArgsList.h index cb6a2262..8377bbe3 100644 --- a/src/core/functions/codac2_FunctionArgsList.h +++ b/src/core/functions/codac2_FunctionArgsList.h @@ -22,9 +22,11 @@ namespace codac2 { } FunctionArgsList(const FunctionArgsList& args) + : std::vector>(args.size()) { + size_t i = 0; for(const auto& arg : args) - push_back(arg->arg_copy()); + (*this)[i++] = arg->arg_copy(); } FunctionArgsList(const std::vector>& args) @@ -39,9 +41,9 @@ namespace codac2 push_back(arg.get().arg_copy()); } - size_t total_size() const + Index total_size() const { - size_t n = 0; + Index n = 0; for(const auto& ai : *this) n += ai->size(); return n; diff --git a/src/core/functions/codac2_FunctionBase.h b/src/core/functions/codac2_FunctionBase.h index dfd22800..f3d4fd42 100644 --- a/src/core/functions/codac2_FunctionBase.h +++ b/src/core/functions/codac2_FunctionBase.h @@ -70,7 +70,7 @@ namespace codac2 return std::dynamic_pointer_cast(expr_copy); } - size_t input_size() const + Index input_size() const { return this->_args.total_size(); } diff --git a/src/core/functions/codac2_VarBase.h b/src/core/functions/codac2_VarBase.h index 42eb06cd..c39b3931 100644 --- a/src/core/functions/codac2_VarBase.h +++ b/src/core/functions/codac2_VarBase.h @@ -20,6 +20,6 @@ namespace codac2 virtual const ExprID& unique_id() const = 0; virtual std::shared_ptr arg_copy() const = 0; virtual ~VarBase() = default; - virtual size_t size() const = 0; + virtual Index size() const = 0; }; } \ No newline at end of file diff --git a/src/core/functions/set/codac2_SetExpr.h b/src/core/functions/set/codac2_SetExpr.h index 71625b7f..3f0e548f 100644 --- a/src/core/functions/set/codac2_SetExpr.h +++ b/src/core/functions/set/codac2_SetExpr.h @@ -94,11 +94,11 @@ namespace codac2 { public: - SetOperationExpr(std::shared_ptr x, const std::vector& proj_indices, double eps) + SetOperationExpr(std::shared_ptr x, const std::vector& proj_indices, double eps) : OperationExprBase(x), _proj_indices(proj_indices), _y(nullptr), _eps(eps) { } - SetOperationExpr(std::shared_ptr x, const std::vector& proj_indices, const IntervalVector& y, double eps) + SetOperationExpr(std::shared_ptr x, const std::vector& proj_indices, const IntervalVector& y, double eps) : OperationExprBase(x), _proj_indices(proj_indices), _y(std::make_shared(y)), _eps(eps) { } @@ -137,7 +137,7 @@ namespace codac2 protected: - const std::vector _proj_indices; + const std::vector _proj_indices; const std::shared_ptr _y; const double _eps; }; diff --git a/src/core/functions/set/codac2_SetFunction.h b/src/core/functions/set/codac2_SetFunction.h index b3de1819..d01167a3 100644 --- a/src/core/functions/set/codac2_SetFunction.h +++ b/src/core/functions/set/codac2_SetFunction.h @@ -37,7 +37,7 @@ namespace codac2 auto create_ctc(const Args&... x) { std::vector>> ref_x(sizeof...(Args)); - size_t i = 0; + Index i = 0; ((ref_x[i++] = create_arg_ctc_copy(x)), ...); assert_release(args().size() == ref_x.size() && "Invalid arguments: wrong number of input arguments"); @@ -48,7 +48,7 @@ namespace codac2 auto create_sep(const Args&... x) { std::vector> ref_x(sizeof...(Args)); - size_t i = 0; + Index i = 0; ((ref_x[i++] = create_arg_sep_copy(x)), ...); assert_release(args().size() == ref_x.size() && "Invalid arguments: wrong number of input arguments"); @@ -59,7 +59,7 @@ namespace codac2 std::shared_ptr operator()(const X&... x) const { auto expr_copy = expr()->copy(); - size_t i = 0; + Index i = 0; (expr_copy->replace_expr(_args[i++]->unique_id(), this->__get_copy(x)), ...); assert_release(i == this->args().size() && "Invalid arguments: wrong number of input arguments"); diff --git a/src/core/functions/set/codac2_set_operations.h b/src/core/functions/set/codac2_set_operations.h index bb9b9308..e8dc14f6 100644 --- a/src/core/functions/set/codac2_set_operations.h +++ b/src/core/functions/set/codac2_set_operations.h @@ -55,13 +55,13 @@ namespace codac2 } inline SetExpr_ptr - proj(const SetExpr_ptr& x1, const std::vector& proj_indices, double eps = 0.01) + proj(const SetExpr_ptr& x1, const std::vector& proj_indices, double eps = 0.01) { return std::make_shared>(x1,proj_indices,eps); } inline SetExpr_ptr - proj(const SetExpr_ptr& x1, const std::vector& proj_indices, const IntervalVector& y, double eps = 0.01) + proj(const SetExpr_ptr& x1, const std::vector& proj_indices, const IntervalVector& y, double eps = 0.01) { return std::make_shared>(x1,proj_indices,y,eps); } diff --git a/src/core/functions/set/codac2_set_operators.h b/src/core/functions/set/codac2_set_operators.h index d5f964f4..8a400b4c 100644 --- a/src/core/functions/set/codac2_set_operators.h +++ b/src/core/functions/set/codac2_set_operators.h @@ -56,24 +56,24 @@ namespace codac2 struct ProjSetOp { - static std::shared_ptr> create_ctc(const std::shared_ptr>& s1, const std::vector& proj_indices, double eps) + static std::shared_ptr> create_ctc(const std::shared_ptr>& s1, const std::vector& proj_indices, double eps) { throw std::logic_error("CtcProj not yet available"); return nullptr; } - static std::shared_ptr> create_ctc(const std::shared_ptr>& s1, const std::vector& proj_indices, const IntervalVector& y, double eps) + static std::shared_ptr> create_ctc(const std::shared_ptr>& s1, const std::vector& proj_indices, const IntervalVector& y, double eps) { throw std::logic_error("CtcProj not yet available"); return nullptr; } - static std::shared_ptr create_sep(const std::shared_ptr& s1, const std::vector& proj_indices, double eps) + static std::shared_ptr create_sep(const std::shared_ptr& s1, const std::vector& proj_indices, double eps) { return std::make_shared(s1,proj_indices,eps); } - static std::shared_ptr create_sep(const std::shared_ptr& s1, const std::vector& proj_indices, const IntervalVector& y, double eps) + static std::shared_ptr create_sep(const std::shared_ptr& s1, const std::vector& proj_indices, const IntervalVector& y, double eps) { return std::make_shared(s1,proj_indices,y,eps); } diff --git a/src/core/functions/set/codac2_set_variables.h b/src/core/functions/set/codac2_set_variables.h index d978a3a3..c630b14c 100644 --- a/src/core/functions/set/codac2_set_variables.h +++ b/src/core/functions/set/codac2_set_variables.h @@ -19,7 +19,7 @@ namespace codac2 { public: - explicit SetVar(size_t n) + explicit SetVar(Index n) : _n(n) { } @@ -38,7 +38,7 @@ namespace codac2 return std::make_shared(*this); } - size_t size() const + Index size() const { return _n; } @@ -61,7 +61,7 @@ namespace codac2 std::shared_ptr> create_ctc(const FunctionArgsList& args, const std::vector>>& x) const { - for(size_t i = 0 ; i < args.size() ; i++) + for(Index i = 0 ; i < args.size() ; i++) if(args[i]->unique_id() == unique_id()) return x[i]; assert(false); @@ -70,7 +70,7 @@ namespace codac2 std::shared_ptr create_sep(const FunctionArgsList& args, const std::vector>& x) const { - for(size_t i = 0 ; i < args.size() ; i++) + for(Index i = 0 ; i < args.size() ; i++) if(args[i]->unique_id() == unique_id()) return x[i]; assert(false); @@ -79,6 +79,6 @@ namespace codac2 protected: - size_t _n; + Index _n; }; } \ No newline at end of file diff --git a/src/core/geometry/codac2_Polygon.cpp b/src/core/geometry/codac2_Polygon.cpp index 69927ef3..0892f1a4 100644 --- a/src/core/geometry/codac2_Polygon.cpp +++ b/src/core/geometry/codac2_Polygon.cpp @@ -27,7 +27,7 @@ namespace codac2 assert_release(vertices.size() > 1); vector edges; - size_t i = 0; + Index i = 0; for(const auto& vi : vertices) { assert_release(vi.size() == 2); @@ -63,7 +63,7 @@ namespace codac2 { assert_release(p.size() == 2); - size_t i = 0; + Index i = 0; Edge transect { Vector({next_float(-oo),p[1]}), p }; for(const auto& edge_k : _edges) diff --git a/src/core/matrices/codac2_GaussJordan.cpp b/src/core/matrices/codac2_GaussJordan.cpp index f40ec787..1a61da6d 100644 --- a/src/core/matrices/codac2_GaussJordan.cpp +++ b/src/core/matrices/codac2_GaussJordan.cpp @@ -2,7 +2,7 @@ * codac2_GaussJordan.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Luc Jaulin, Simon Rohou, Damien Massé * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -13,17 +13,15 @@ using namespace std; namespace codac2 { - typedef Eigen::Matrix Mat; - - Mat rising(const Mat& R_, const Mat& U_, const Mat& A) + Matrix rising(const Matrix& R_, const Matrix& U_, const Matrix& A) { - Mat R = R_, U = U_; - size_t n = A.rows(), m = A.cols(); - size_t p = m-n; + Matrix R = R_, U = U_; + Index n = A.rows(), m = A.cols(); + Index p = m-n; - for(int i = n-1 ; i > 0 ; i--) + for(Index i = n-1 ; i > 0 ; i--) { - Mat K = U(i,i+p)*Mat::Identity(n,n); + Matrix K = U(i,i+p)*Matrix::Identity(n,n); K.block(0,i,i,1) = -U.block(0,i+p,i,1); R = K*R; U = R*A; @@ -32,28 +30,31 @@ namespace codac2 return R; } - Mat precond(const Mat& P, const Mat& L, const Mat& U) + Matrix precond(const Matrix& P, const Matrix& L, const Matrix& U) { - Mat A = P.inverse()*L*U; - Mat R = (P.inverse()*L).inverse(); + auto P_inv = P.inverse(); + Matrix A = P_inv*(L*U); + Matrix R = (P_inv*L).inverse(); return rising(R,U,A); } Matrix gauss_jordan(const Matrix& A) { - size_t n = A.nb_rows(), m = A.nb_cols(); - Eigen::FullPivLU lu(A._e); + Index n = A.rows(), m = A.cols(); + Eigen::FullPivLU lu(A); - Mat L = Mat::Identity(n,n); + Matrix L = Matrix::Identity(n,n); if(std::pow(L.determinant(),2) < 1e-5) { - cout << "[Matrix gauss_jordan(const Matrix& A)] -> eye matrix" << endl; + cout << "[Matrix gauss_jordan(const Matrix& A)] -> eye Matrix" << endl; return Matrix::eye(n,n); } - L.block(0,0,n,m).triangularView() = lu.matrixLU(); - Mat P = lu.permutationP(); - Mat U = lu.matrixLU().triangularView(); + L.block(0,0,n,std::min(m,n)).triangularView() = + lu.matrixLU().block(0,0,n,std::min(m,n)); + + Matrix P = lu.permutationP(); + Matrix U = lu.matrixLU().triangularView(); return precond(P,L,U); } diff --git a/src/core/matrices/codac2_GaussJordan.h b/src/core/matrices/codac2_GaussJordan.h index 3b5ced65..4db601ba 100644 --- a/src/core/matrices/codac2_GaussJordan.h +++ b/src/core/matrices/codac2_GaussJordan.h @@ -2,7 +2,7 @@ * \file codac2_GaussJordan.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Luc Jaulin, Simon Rohou, Damien Massé * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -10,11 +10,12 @@ #pragma once #include -#include "codac2_eigen.h" #include "codac2_Matrix.h" namespace codac2 { // Gauss Jordan band diagonalization preconditioning Matrix gauss_jordan(const Matrix& A); + + // From https://www.ensta-bretagne.fr/jaulin/centered.html } \ No newline at end of file diff --git a/src/core/matrices/codac2_Inversion.cpp b/src/core/matrices/codac2_Inversion.cpp new file mode 100644 index 00000000..568d68c2 --- /dev/null +++ b/src/core/matrices/codac2_Inversion.cpp @@ -0,0 +1,74 @@ +/** + * \file codac2_Inversion.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Damien Massé + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include "codac2_Inversion.h" +#include "codac2_Matrix.h" +#include "codac2_IntervalMatrix.h" + +using namespace std; + +namespace codac2 +{ + IntervalMatrix infinite_sum_enclosure(const IntervalMatrix& A, double &mrad) { + assert_release(A.is_squared()); + Index N = A.rows(); + + Matrix B = A.mag(); + + // modified Floyd algorithm + for (Index k=0;k0.0 && B(k,r)0.0 && B(r,k)=1.0) { + mrad=oo; + res(r,c)=Interval(); + } else { + Interval sumprod=1.0/(1.0-sum); + if (sumprod.ub()>mrad) mrad=sumprod.ub(); + res(r,c)=(v*B(r,c))*sumprod; + } + } + } + return res; + } + + IntervalMatrix inverse_enclosure(const IntervalMatrix &A) { + assert_release(A.is_squared()); + Index N=A.rows(); + return inverse_correction(A, + (A.mid()).fullPivLu().solve(Matrix::Identity(N,N))); + } +} diff --git a/src/core/matrices/codac2_Inversion.h b/src/core/matrices/codac2_Inversion.h new file mode 100644 index 00000000..eca2c2ba --- /dev/null +++ b/src/core/matrices/codac2_Inversion.h @@ -0,0 +1,115 @@ +/** + * \file codac2_Inversion.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Damien Massé + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include "codac2_Matrix.h" +#include "codac2_IntervalMatrix.h" + +namespace codac2 +{ + enum LeftOrRightInv { LEFT_INV, RIGHT_INV }; + + /** \brief Compute an upper bound of A+A^2+A^3+..., with A a matrix of intervals + * as an "error term" (use only bounds on coefficients) + * + * The function also returns mrad, which gives an idea of the “magnification” of + * the matrix during calculation (in particular, if mrad = oo, then the inversion + * calculation (e.g., performed by Eigen) has somehow failed and some coefficients + * of the output interval matrix are [-oo,+oo]). + * + * \pre A is a square matrix + * + * \param A a matrix of intervals (supposed around 0) + * \param mrad the maximum radius of the result added (output argument) + * \return the enclosure. May include (-oo,oo) + */ + IntervalMatrix infinite_sum_enclosure(const IntervalMatrix& A, double &mrad); + + /** \brief Correct the approximate inverse of a matrix + * + * \pre A and B are square matrices + * + * \tparam O if LEFT_INV, use the inverse of BA (otherwise use the inverse of AB, + * left inverse is normally better) + * \param A a matrix expression + * \param B a (almost punctual) approximation of its inverse, + * \return the enclosure + */ + template + inline IntervalMatrix inverse_correction(const Eigen::MatrixBase& A, const Eigen::MatrixBase& B) + { + assert_release(A.is_squared()); + assert_release(B.is_squared()); + + auto A_ = A.template cast(); + auto B_ = B.template cast(); + + Index N = A_.rows(); + assert_release(N==B_.rows()); + + auto Id = IntervalMatrix::Identity(N,N); + auto erMat = [&]() { if constexpr(O == LEFT_INV) return -B_*A_+Id; else return -A_*B_+Id; }(); + + double mrad=0.0; + IntervalMatrix E = infinite_sum_enclosure(erMat,mrad); + IntervalMatrix Ep = Id+erMat*(Id+E); + /* one could use several iterations here, either + using mrad, or directly */ + + auto res = (O == LEFT_INV) ? IntervalMatrix(Ep*B_) : IntervalMatrix(B_*Ep); + + // We want the presence of non-invertible matrices to + // result in coefficients of the form [-oo,+oo]. + if (mrad==oo) { + for (Index c=0;c + inline IntervalMatrix inverse_enclosure(const Eigen::MatrixBase& A) + { + assert_release(A.is_squared()); + Index N=A.rows(); + return inverse_correction(A, + A.fullPivLu().solve(Matrix::Identity(N,N))); + } + + + /** \brief Enclosure of the inverse of a matrix of intervals + * + * \pre A is a square matrix + * + * \param A a matrix of intervals + * \return the enclosure. Can have (-oo,oo) coefficients if the + * inversion "failed" + */ + IntervalMatrix inverse_enclosure(const IntervalMatrix &A); +} diff --git a/src/core/matrices/codac2_Matrix.cpp b/src/core/matrices/codac2_Matrix.cpp deleted file mode 100644 index 5a82c244..00000000 --- a/src/core/matrices/codac2_Matrix.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/** - * codac2_Matrix.cpp - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include "codac2_Vector.h" -#include "codac2_Matrix.h" -#include "codac2_IntervalVector.h" -#include "codac2_IntervalMatrix.h" - -using namespace std; -using namespace codac2; - -namespace codac2 -{ - Matrix::Matrix(size_t r, size_t c) - : Matrix(r,c,0.) - { - assert_release(r >= 0 && c >= 0); - } - - Matrix::Matrix(size_t r, size_t c, double x) - : MatrixBase(r,c,x) - { - assert_release(r >= 0 && c >= 0); - } - - Matrix::Matrix(size_t r, size_t c, const double values[]) - : MatrixBase(r,c,values) - { - assert_release(r >= 0 && c >= 0); - } - - Matrix::Matrix(std::initializer_list> l) - : MatrixBase(l) - { - assert_release(!std::empty(l)); - } - - Matrix::Matrix(const MatrixBase& x) - : Matrix(x._e) - { } - - Matrix::Matrix(const Vector& x) - : Matrix(x._e) - { } - - - Matrix Matrix::transpose() const - { - return this->_e.transpose(); - } - - Matrix Matrix::diag_matrix() const - { - return this->_e.diagonal().asDiagonal().toDenseMatrix(); - } - - Matrix Matrix::inverse() const - { - return this->_e.inverse(); - } -} \ No newline at end of file diff --git a/src/core/matrices/codac2_Matrix.h b/src/core/matrices/codac2_Matrix.h index 87d82e22..164acf34 100644 --- a/src/core/matrices/codac2_Matrix.h +++ b/src/core/matrices/codac2_Matrix.h @@ -2,111 +2,22 @@ * \file codac2_Matrix.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou, Gilles Chabert + * \author Simon Rohou * \copyright Copyright 2023 Codac Team * \license GNU Lesser General Public License (LGPL) */ #pragma once -#include "codac2_assert.h" -#include "codac2_MatrixBase.h" +#include "codac2_matrices.h" namespace codac2 { - class Vector; - class IntervalVector; - class IntervalMatrix; + using Matrix = Eigen::Matrix; - class Matrix : public MatrixBase + inline std::ostream& operator<<(std::ostream& os, const Matrix& x) { - public: - - explicit Matrix(size_t r, size_t c); - - explicit Matrix(size_t r, size_t c, double x); - - explicit Matrix(size_t r, size_t c, const double values[]); - - Matrix(std::initializer_list> l); - - Matrix(const MatrixBase& x); - - Matrix(const Vector& x); - - template - Matrix(const MatrixBaseBlock& x) - : Matrix(x.eval()) - { } - - template - Matrix(const Eigen::MatrixBase& x) - : MatrixBase(x) - { } - - Matrix transpose() const; - - Matrix diag_matrix() const; - - Matrix inverse() const; - - // Operators - - Matrix& operator+=(const Matrix& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e += x._e; - return *this; - } - - template - Matrix& operator+=(const MatrixBaseBlock& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e += eigen(x); - return *this; - } - - Matrix& operator-=(const Matrix& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e -= x._e; - return *this; - } - - template - Matrix& operator-=(const MatrixBaseBlock& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e -= eigen(x); - return *this; - } - - Matrix& operator*=(double x) - { - this->_e *= x; - return *this; - } - - Matrix& operator*=(const Matrix& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e *= x._e; - return *this; - } - - template - Matrix& operator*=(const MatrixBaseBlock& x) - { - assert_release(this->nb_rows() == x.nb_rows() && this->nb_cols() == x.nb_cols()); - this->_e *= eigen(x); - return *this; - } - - Matrix& operator/=(double x) - { - this->_e /= x; - return *this; - } - }; + os << x.format(codac_matrix_fmt()); + return os; + } } \ No newline at end of file diff --git a/src/core/matrices/codac2_MatrixBase.h b/src/core/matrices/codac2_MatrixBase.h deleted file mode 100644 index a675dcad..00000000 --- a/src/core/matrices/codac2_MatrixBase.h +++ /dev/null @@ -1,370 +0,0 @@ -/** - * \file codac2_MatrixBase.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include -#include "codac2_eigen.h" -#include "codac2_assert.h" -#include "codac2_MatrixBaseBlock.h" - -namespace codac2 -{ - template - class VectorBase; - - template - struct MatrixBaseBlock; - - template - using EigenMatrix = Eigen::Matrix; - - template - class MatrixBase - { - public: - - explicit MatrixBase(size_t r, size_t c) - : _e(EigenMatrix(r,c)) - { - assert(r >= 0 && c >= 0); - } - - explicit MatrixBase(size_t r, size_t c, const T& x) - : MatrixBase(r,c) - { - init(x); - } - - explicit MatrixBase(size_t r, size_t c, const T values[]) - : MatrixBase(r,c) - { - if(values == 0) - init(T(0.)); // in case the user called MatrixBase(r,c,0) and 0 is interpreted as NULL! - - else - { - size_t k = 0; - for(size_t i = 0 ; i < nb_rows() ; i++) - for(size_t j = 0 ; j < nb_cols() ; j++) - (*this)(i,j) = values[k++]; - assert(k == size()); - } - } - - explicit MatrixBase(const std::vector& x) - : MatrixBase(x.size(),1,&x[0]) - { - assert(!x.empty()); - } - - MatrixBase(std::initializer_list> l) - : MatrixBase(0,0 /* will be resized thereafter */) - { - assert(!std::empty(l)); - - int cols = -1; - for(const auto& ri : l) { - assert_release((cols == -1 || cols == (int)ri.size()) && "ill-formed matrix"); - cols = (int)ri.size(); - } - - resize(l.size(),cols); - size_t i = 0; - for(const auto& ri : l) - { - size_t j = 0; - for(const auto& ci : ri) - (*this)(i,j++) = ci; - i++; - } - // todo: use this instead (faster?) ? std::copy(l.begin(), l.end(), vec); - } - - MatrixBase(const std::vector>& l) - : MatrixBase(0,0 /* will be resized thereafter */) - { - assert(!std::empty(l)); - - int cols = -1; - for(const auto& ri : l) { - assert_release((cols == -1 || cols == (int)ri.size()) && "ill-formed matrix"); - cols = (int)ri.size(); - } - - resize(l.size(),cols); - size_t i = 0; - for(const auto& ri : l) - { - size_t j = 0; - for(const auto& ci : ri) - (*this)(i,j++) = ci; - i++; - } - // todo: use this instead (faster?) ? std::copy(l.begin(), l.end(), vec); - } - - template - MatrixBase(const Eigen::MatrixBase& x) - : _e(x) - { } - - virtual ~MatrixBase() - { } - - MatrixBase& operator=(const MatrixBase&) = default; - - size_t size() const - { - return _e.size(); - } - - size_t nb_rows() const - { - return _e.rows(); - } - - size_t nb_cols() const - { - return _e.cols(); - } - - bool is_squared() const - { - return nb_rows() == nb_cols(); - } - - #define minmax_item(op) \ - T m = *_e.data(); /* first element */ \ - for(size_t i = 1 ; i < size() ; i++) \ - { \ - if constexpr(std::is_same_v) \ - m = codac2::op(m,*(_e.data()+i)); \ - else \ - m = std::op(m,*(_e.data()+i)); \ - } \ - return m; \ - - T min_coeff() const - { - minmax_item(min); - } - - T max_coeff() const - { - minmax_item(max); - } - - T norm() const - { - return _e.norm(); - } - - T squared_norm() const - { - return _e.squaredNorm(); - } - - friend bool operator==(const MatrixBase& x1, const MatrixBase& x2) - { - if(x1.nb_rows() != x2.nb_rows() || x1.nb_cols() != x2.nb_cols()) - return false; - - for(size_t i = 0 ; i < x1.nb_rows() ; i++) - for(size_t j = 0 ; j < x1.nb_cols() ; j++) - if(x1(i,j) != x2(i,j)) - return false; - - return true; - } - - T& operator()(size_t i, size_t j) - { - return const_cast(const_cast*>(this)->operator()(i,j)); - } - - const T& operator()(size_t i, size_t j) const - { - assert_release(i >= 0 && i < nb_rows() && j >= 0 && j < nb_cols()); - return this->_e(i,j); - } - - void init(const T& x) - { - for(size_t i = 0 ; i < size() ; i++) - *(_e.data()+i) = x; - } - - void init(const S& x) - { - *this = x; - } - - void resize(size_t nb_rows, size_t nb_cols) - { - assert_release(nb_rows >= 0 && nb_cols >= 0); - - // With resize() of Eigen, the data is reallocated and all previous values are lost. - auto copy = _e; - _e.resize(nb_rows, nb_cols); - for(size_t i = 0 ; i < std::min((size_t)copy.rows(),nb_rows) ; i++) - for(size_t j = 0 ; j < std::min((size_t)copy.cols(),nb_cols) ; j++) - _e(i,j) = copy(i,j); - } - - MatrixBaseBlock&,T> block(size_t i, size_t j, size_t p, size_t q) - { - assert_release(i >= 0 && p > 0 && i+p <= nb_rows()); - assert_release(j >= 0 && q > 0 && j+q <= nb_cols()); - return { _e,i,j,p,q }; - } - - MatrixBaseBlock&,T> block(size_t i, size_t j, size_t p, size_t q) const - { - assert_release(i >= 0 && p > 0 && i+p <= nb_rows()); - assert_release(j >= 0 && q > 0 && j+q <= nb_cols()); - return { _e,i,j,p,q }; - } - - MatrixBaseBlock&,T> col(size_t i) - { - return block(0,i,nb_rows(),1); - } - - MatrixBaseBlock&,T> col(size_t i) const - { - return block(0,i,nb_rows(),1); - } - - MatrixBaseBlock&,T> row(size_t i) - { - return block(i,0,1,nb_cols()); - } - - MatrixBaseBlock&,T> row(size_t i) const - { - return block(i,0,1,nb_cols()); - } - - const auto& operator+() const - { - return _e; - } - - S operator-() const - { - return -_e; - } - - static S zeros(size_t r, size_t c) - { - assert_release(r >= 0 && c >= 0); - return EigenMatrix::Zero(r,c); - } - - static S ones(size_t r, size_t c) - { - assert_release(r >= 0 && c >= 0); - return EigenMatrix::Ones(r,c); - } - - static S eye(size_t r, size_t c) - { - assert_release(r >= 0 && c >= 0); - return EigenMatrix::Identity(r,c); - } - - // Note that this static function is not called "rand" - // because of ambiguity with the member function "rand" - static S random(size_t r, size_t c) - { - assert_release(r >= 0 && c >= 0); - return EigenMatrix::Random(r,c); - } - - template - friend std::ostream& operator<<(std::ostream& os, const MatrixBase& x); - - template - friend S_ abs(const MatrixBase& x); - - operator EigenMatrix() - { - return const_cast&>(const_cast*>(this)->operator EigenMatrix()); - } - - operator EigenMatrix() const - { - return _e; - } - - using iterator = typename EigenMatrix::iterator; - using const_iterator = typename EigenMatrix::const_iterator; - - iterator begin() - { - return const_cast(const_cast*>(this)->begin()); - } - - const_iterator begin() const - { - return _e.cbegin(); - } - - const_iterator end() const - { - return _e.cend(); - } - - iterator end() - { - return const_cast(const_cast*>(this)->end()); - } - - EigenMatrix _e; - }; - - template - S abs(const MatrixBase& x) - { - S a(x); - - for(size_t i = 0 ; i < x.size() ; i++) - { - if constexpr(std::is_same_v) - *(a._e.data()+i) = fabs(*(x._e.data()+i)); - else - *(a._e.data()+i) = abs(*(x._e.data()+i)); - } - - return a; - } - - template - std::ostream& operator<<(std::ostream& os, const MatrixBase& x) - { - os << "("; - for(size_t i = 0 ; i < x.nb_rows() ; i++) - { - os << (i!=0 ? " " : "") << "("; - for(size_t j = 0 ; j < x.nb_cols() ; j++) - os << x(i,j) << (j - const auto& eigen(const MatrixBase& x) - { - return x._e; - } -} \ No newline at end of file diff --git a/src/core/matrices/codac2_MatrixBaseBlock.h b/src/core/matrices/codac2_MatrixBaseBlock.h deleted file mode 100644 index c1a09b8b..00000000 --- a/src/core/matrices/codac2_MatrixBaseBlock.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * \file codac2_MatrixBaseBlock.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include -#include "codac2_eigen.h" -#include "codac2_assert.h" -#include "codac2_MatrixBase.h" - -namespace codac2 -{ - template - class MatrixBase; - - template - struct MatrixBaseBlock - { - Q _m; - size_t _i,_j,_p,_q; - - MatrixBaseBlock(Q m, size_t i, size_t j, size_t p, size_t q) - : _m(m), _i(i), _j(j), _p(p), _q(q) - { - assert(i >= 0 && p > 0 && i+p <= (size_t)m.rows()); - assert(j >= 0 && q > 0 && j+q <= (size_t)m.cols()); - } - - size_t nb_rows() const - { - return _p; - } - - size_t nb_cols() const - { - return _q; - } - - template - void operator=(const MatrixBase& x) - { - assert_release(x.nb_rows() == _p && x.nb_cols() == _q); - _m.block(_i,_j,_p,_q) = x._e; - } - - template - void operator=(const Eigen::MatrixBase& x) - { - assert_release(x.rows() == _p && x.cols() == _q); - _m.block(_i,_j,_p,_q) = x; - } - - // The following replaces operator=, that does not work in Python - // (assignment on function output Matrix::block()) - template - void init(const S_& x) - { - _m.block(_i,_j,_p,_q) = x; - } - - auto eval() const - { - return _m.block(_i,_j,_p,_q).eval(); - } - - template - bool operator==(const M& x) const - { - return this->eval() == x; - } - }; - - template - std::ostream& operator<<(std::ostream& os, const MatrixBaseBlock& x) - { - os << x.eval(); - return os; - } - - template - auto eigen(const MatrixBaseBlock& x) - { - return x._m.block(x._i,x._j,x._p,x._q); - } -} \ No newline at end of file diff --git a/src/core/matrices/codac2_Row.h b/src/core/matrices/codac2_Row.h new file mode 100644 index 00000000..7703efff --- /dev/null +++ b/src/core/matrices/codac2_Row.h @@ -0,0 +1,23 @@ +/** + * \file codac2_Row.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_matrices.h" + +namespace codac2 +{ + using Row = Eigen::Matrix; + + inline std::ostream& operator<<(std::ostream& os, const Row& x) + { + os << x.format(codac_row_fmt()); + return os; + } +} \ No newline at end of file diff --git a/src/core/matrices/codac2_Vector.cpp b/src/core/matrices/codac2_Vector.cpp deleted file mode 100644 index 324c7a3d..00000000 --- a/src/core/matrices/codac2_Vector.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/** - * codac2_Vector.cpp - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include "codac2_Vector.h" - -using namespace std; -using namespace codac2; - -namespace codac2 -{ - Vector::Vector(size_t n) - : Vector(n,0.) - { - assert_release(n >= 0); - } - - Vector::Vector(size_t n, double x) - : MatrixBase(n,1,x), - VectorBase(n) - { - assert_release(n >= 0); - } - - Vector::Vector(std::initializer_list l) - : MatrixBase(l.size(),1), - VectorBase(l) - { - assert_release(!std::empty(l)); - } - - Vector::Vector(const std::vector& l) - : MatrixBase(l.size(),1), - VectorBase(l) - { - assert_release(!std::empty(l)); - } - - Vector::Vector(const MatrixBase& x) - : Vector(x._e) - { } - - size_t Vector::min_coeff_index() const - { - size_t r,c; - this->_e.minCoeff(&r,&c); - assert(c == 0); - return r; - } - - size_t Vector::max_coeff_index() const - { - size_t r,c; - this->_e.maxCoeff(&r,&c); - assert(c == 0); - return r; - } - - std::ostream& operator<<(std::ostream& os, const Vector& x) - { - os << "("; - for(size_t i = 0 ; i < x.size() ; i++) - os << x[i] << (i; - class Vector : public VectorBase + inline std::ostream& operator<<(std::ostream& os, const Vector& x) { - public: - - explicit Vector(size_t n); - - explicit Vector(size_t n, double x); - - Vector(std::initializer_list l); - - Vector(const std::vector& l); - - Vector(const MatrixBase& x); - - template - Vector(const Eigen::MatrixBase& x) - : MatrixBase(x), - VectorBase(x) - { } - - double& operator()(size_t i, size_t j) = delete; - const double& operator()(size_t i, size_t j) const = delete; - - size_t min_coeff_index() const; - - size_t max_coeff_index() const; - - // Operators - - Vector& operator+=(const Vector& x) - { - assert_release(this->size() == x.size()); - this->_e += x._e; - return *this; - } - - Vector& operator-=(const Vector& x) - { - assert_release(this->size() == x.size()); - this->_e -= x._e; - return *this; - } - - Vector& operator*=(double x) - { - this->_e *= x; - return *this; - } - - Vector& operator/=(double x) - { - this->_e /= x; - return *this; - } - - }; - - std::ostream& operator<<(std::ostream& os, const Vector& x); + os << x.format(codac_vector_fmt()); + return os; + } } \ No newline at end of file diff --git a/src/core/matrices/codac2_VectorBase.h b/src/core/matrices/codac2_VectorBase.h deleted file mode 100644 index c918aab5..00000000 --- a/src/core/matrices/codac2_VectorBase.h +++ /dev/null @@ -1,134 +0,0 @@ -/** - * \file codac2_VectorBase.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include "codac2_MatrixBase.h" - -namespace codac2 -{ - template - class VectorBase : virtual public MatrixBase - { - public: - - explicit VectorBase(size_t n) - : MatrixBase(n,1) - { - assert_release(n >= 0); - } - - VectorBase(std::initializer_list l) - : MatrixBase(l.size(),1) - { - assert(!std::empty(l)); - size_t i = 0; - for(const auto& li : l) - (*this)[i++] = li; - } - - VectorBase(const std::vector& l) - : MatrixBase(l.size(),1) - { - assert(!std::empty(l)); - size_t i = 0; - for(const auto& li : l) - (*this)[i++] = li; - } - - template - VectorBase(const Eigen::MatrixBase& x) - : MatrixBase(x) - { } - - bool is_squared() const = delete; - - T& operator[](size_t i) - { - return const_cast(const_cast*>(this)->operator[](i)); - } - - const T& operator[](size_t i) const - { - assert_release(i >= 0 && i < this->size()); - return this->_e(i); - } - - S subvector(size_t start_id, size_t end_id) const - { - assert_release(end_id >= 0 && start_id >= 0); - assert_release(end_id < this->size() && start_id <= end_id); - return this->_e.block(start_id, 0, end_id-start_id+1, 1); - } - - void resize(size_t n) - { - assert_release(n >= 0); - MatrixBase::resize(n,1); - } - - void put(size_t start_id, const S& x) - { - assert_release(start_id >= 0 && start_id < this->size()); - assert_release(start_id+x.size() <= this->size()); - this->_e.block(start_id,0,x.size(),1) << x._e; - } - - M transpose() const - { - return this->_e.transpose(); - } - - M diag_matrix() const - { - M diag(this->size(),this->size(),0.); - for(size_t i = 0 ; i < this->size() ; i++) - diag(i,i) = (*this)[i]; - return diag; - } - - static S zeros(size_t r, size_t c) = delete; - - static S zeros(size_t n) - { - assert_release(n >= 0); - return EigenMatrix::Zero(n,1); - } - - static S ones(size_t r, size_t c) = delete; - - static S ones(size_t n) - { - assert_release(n >= 0); - return EigenMatrix::Ones(n,1); - } - - static S random(size_t r, size_t c) = delete; - - // Note that this static function is not called "rand" - // because of ambiguity with the member function "rand" - static S random(size_t n) - { - assert_release(n >= 0); - return EigenMatrix::Random(n,1); - } - - }; - - template - std::ostream& operator<<(std::ostream& os, const VectorBase& x) - { - os << "("; - for(size_t i = 0 ; i < x.size() ; i++) - os << x[i] << (i() + eigen(x2); - } - - // ====== First operand: matrix - - template - requires IsMatrix && IsMatrix - Matrix operator+(const M& x1, const M_& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1) + eigen(x2); - } - - template - requires IsMatrix && IsIntervalMatrix - IntervalMatrix operator+(const M& x1, const IM& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1).template cast() + eigen(x2); - } - - // ====== First operand: interval vector - - inline IntervalVector operator+(const IntervalVector& x1, const Vector& x2) - { - assert_release(x1.size() == x2.size()); - return eigen(x1) + eigen(x2).template cast(); - } - - inline IntervalVector operator+(const IntervalVector& x1, const IntervalVector& x2) - { - assert_release(x1.size() == x2.size()); - return eigen(x1) + eigen(x2); - } - - // ====== First operand: interval matrix - - template - requires IsIntervalMatrix && IsMatrix - IntervalMatrix operator+(const IM& x1, const M& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1) + eigen(x2).template cast(); - } - - template - requires IsIntervalMatrix && IsIntervalMatrix - IntervalMatrix operator+(const IM& x1, const IM_& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1) + eigen(x2); - } -} \ No newline at end of file diff --git a/src/core/matrices/codac2_arithmetic_div.h b/src/core/matrices/codac2_arithmetic_div.h deleted file mode 100644 index cba21e35..00000000 --- a/src/core/matrices/codac2_arithmetic_div.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * \file codac2_arithmetic_div.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include "codac2_template_tools.h" -#include "codac2_IntervalMatrix.h" -#include "codac2_IntervalVector.h" -#include "codac2_MatrixBaseBlock.h" - -namespace codac2 -{ - // ====== First operand: vector - - inline Vector operator/(const Vector& x1, double x2) - { - return eigen(x1) / x2; - } - - inline IntervalVector operator/(const Vector& x1, const Interval& x2) - { - return eigen(x1).template cast() / x2; - } - - // ====== First operand: matrix - - template - requires IsMatrix - Matrix operator/(const M& x1, double x2) - { - return eigen(x1) / x2; - } - - template - requires IsMatrix - IntervalMatrix operator/(const M& x1, const Interval& x2) - { - return eigen(x1).template cast() / x2; - } - - // ====== First operand: interval vector - - inline IntervalVector operator/(const IntervalVector& x1, double x2) - { - return eigen(x1) / Interval(x2); - } - - inline IntervalVector operator/(const IntervalVector& x1, const Interval& x2) - { - return eigen(x1) / x2; - } - - // ====== First operand: interval matrix - - template - requires IsIntervalMatrix - IntervalMatrix operator/(const IM& x1, double x2) - { - return eigen(x1) / Interval(x2); - } - - template - requires IsIntervalMatrix - IntervalMatrix operator/(const IM& x1, const Interval& x2) - { - return eigen(x1) / x2; - } -} \ No newline at end of file diff --git a/src/core/matrices/codac2_arithmetic_mul.h b/src/core/matrices/codac2_arithmetic_mul.h deleted file mode 100644 index 0506e334..00000000 --- a/src/core/matrices/codac2_arithmetic_mul.h +++ /dev/null @@ -1,190 +0,0 @@ -/** - * \file codac2_arithmetic_mul.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include "codac2_template_tools.h" -#include "codac2_IntervalMatrix.h" -#include "codac2_IntervalVector.h" -#include "codac2_MatrixBaseBlock.h" - -namespace codac2 -{ - // ====== First operand: double - - inline Vector operator*(double x1, const Vector& x2) - { - return x1 * eigen(x2); - } - - template - requires IsMatrix - Matrix operator*(double x1, const M& x2) - { - return x1 * eigen(x2); - } - - inline IntervalVector operator*(double x1, const IntervalVector& x2) - { - return Interval(x1) * eigen(x2); - } - - template - requires IsIntervalMatrix - IntervalMatrix operator*(double x1, const IM& x2) - { - return Interval(x1) * eigen(x2); - } - - // ====== First operand: interval - - inline IntervalVector operator*(const Interval& x1, const Vector& x2) - { - return x1 * eigen(x2).template cast(); - } - - template - requires IsMatrix - IntervalMatrix operator*(const Interval& x1, const M& x2) - { - return x1 * eigen(x2).template cast(); - } - - inline IntervalVector operator*(const Interval& x1, const IntervalVector& x2) - { - return x1 * eigen(x2); - } - - template - requires IsIntervalMatrix - IntervalMatrix operator*(const Interval& x1, const IM& x2) - { - return x1 * eigen(x2); - } - - // ====== First operand: vector - - inline Vector operator*(const Vector& x1, double x2) - { - return eigen(x1) * x2; - } - - inline IntervalVector operator*(const Vector& x1, const Interval& x2) - { - return eigen(x1).template cast() * x2; - } - - // ====== First operand: matrix - - template - requires IsMatrix - Matrix operator*(const M& x1, double x2) - { - return eigen(x1) * x2; - } - - template - requires IsMatrix - IntervalMatrix operator*(const M& x1, const Interval& x2) - { - return eigen(x1).template cast() * x2; - } - - template - requires IsMatrix - Vector operator*(const M& x1, const Vector& x2) - { - assert_release(x1.nb_cols() == x2.size()); - return eigen(x1) * eigen(x2); - } - - template - requires IsMatrix && IsMatrix - Matrix operator*(const M& x1, const M_& x2) - { - assert_release(x1.nb_cols() == x2.nb_rows()); - return eigen(x1) * eigen(x2); - } - - template - requires IsMatrix - IntervalVector operator*(const M& x1, const IntervalVector& x2) - { - assert_release(x1.nb_cols() == x2.size()); - return eigen(x1).template cast() * eigen(x2); - } - - template - requires IsMatrix && IsIntervalMatrix - IntervalMatrix operator*(const M& x1, const IM& x2) - { - assert_release(x1.nb_cols() == x2.nb_rows()); - return eigen(x1).template cast() * eigen(x2); - } - - // ====== First operand: interval vector - - inline IntervalVector operator*(const IntervalVector& x1, double x2) - { - return eigen(x1) * Interval(x2); - } - - inline IntervalVector operator*(const IntervalVector& x1, const Interval& x2) - { - return eigen(x1) * x2; - } - - // ====== First operand: interval matrix - - template - requires IsIntervalMatrix - IntervalMatrix operator*(const IM& x1, double x2) - { - return eigen(x1) * Interval(x2); - } - - template - requires IsIntervalMatrix - IntervalMatrix operator*(const IM& x1, const Interval& x2) - { - return eigen(x1) * x2; - } - - template - requires IsIntervalMatrix - IntervalVector operator*(const IM& x1, const Vector& x2) - { - assert_release(x1.nb_cols() == x2.size()); - return eigen(x1) * eigen(x2).template cast(); - } - - template - requires IsIntervalMatrix && IsMatrix - IntervalMatrix operator*(const IM& x1, const M& x2) - { - assert_release(x1.nb_cols() == x2.nb_rows()); - return eigen(x1) * eigen(x2).template cast(); - } - - template - requires IsIntervalMatrix - IntervalVector operator*(const IM& x1, const IntervalVector& x2) - { - assert_release(x1.nb_cols() == x2.size()); - return eigen(x1) * eigen(x2); - } - - template - requires IsIntervalMatrix && IsIntervalMatrix - IntervalMatrix operator*(const IM& x1, const IM_& x2) - { - assert_release(x1.nb_cols() == x2.nb_rows()); - return eigen(x1) * eigen(x2); - } -} \ No newline at end of file diff --git a/src/core/matrices/codac2_arithmetic_sub.h b/src/core/matrices/codac2_arithmetic_sub.h deleted file mode 100644 index a5ce04b8..00000000 --- a/src/core/matrices/codac2_arithmetic_sub.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * \file codac2_arithmetic_sub.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include "codac2_template_tools.h" - -namespace codac2 -{ - // ====== First operand: vector - - inline Vector operator-(const Vector& x1, const Vector& x2) - { - assert_release(x1.size() == x2.size()); - return eigen(x1) - eigen(x2); - } - - inline IntervalVector operator-(const Vector& x1, const IntervalVector& x2) - { - assert_release(x1.size() == x2.size()); - return eigen(x1).template cast() - eigen(x2); - } - - // ====== First operand: matrix - - template - requires IsMatrix && IsMatrix - Matrix operator-(const M& x1, const M_& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1) - eigen(x2); - } - - template - requires IsMatrix && IsIntervalMatrix - IntervalMatrix operator-(const M& x1, const IM& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1).template cast() - eigen(x2); - } - - // ====== First operand: interval vector - - inline IntervalVector operator-(const IntervalVector& x1, const Vector& x2) - { - assert_release(x1.size() == x2.size()); - return eigen(x1) - eigen(x2).template cast(); - } - - inline IntervalVector operator-(const IntervalVector& x1, const IntervalVector& x2) - { - assert_release(x1.size() == x2.size()); - return eigen(x1) - eigen(x2); - } - - // ====== First operand: interval matrix - - template - requires IsIntervalMatrix && IsMatrix - IntervalMatrix operator-(const IM& x1, const M& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1) - eigen(x2).template cast(); - } - - template - requires IsIntervalMatrix && IsIntervalMatrix - IntervalMatrix operator-(const IM& x1, const IM_& x2) - { - assert_release(x1.nb_rows() == x2.nb_rows() && x1.nb_cols() == x2.nb_cols()); - return eigen(x1) - eigen(x2); - } -} \ No newline at end of file diff --git a/src/core/matrices/codac2_matrices.h b/src/core/matrices/codac2_matrices.h new file mode 100644 index 00000000..f389d705 --- /dev/null +++ b/src/core/matrices/codac2_matrices.h @@ -0,0 +1,140 @@ +/** + * \file codac2_matrices.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_Interval.h" +#include "codac2_Interval_operations.h" +#include "codac2_assert.h" + +namespace Eigen +{ + template + concept IsVectorOrRow = (C == 1 || R == 1); + + template + concept IsIntervalDomain = std::is_same_v; +} + +#define EIGEN_MATRIXBASE_PLUGIN "codac2_MatrixBase_addons_include.h" +#define EIGEN_MATRIX_PLUGIN "codac2_Matrix_addons_include.h" + +#ifndef EIGEN_NO_DEBUG +/* Disables Eigen's assertions if defined. + * Not defined by default, unless the NDEBUG macro is defined + * (this is a standard C++ macro which disables all asserts). + * https://eigen.tuxfamily.org/dox/TopicPreprocessorDirectives.html + */ +//#define EIGEN_NO_DEBUG // uncomment to disable Eigen's assertions +#endif + +#include +#include + +namespace Eigen +{ + template<> struct NumTraits + : NumTraits // permits to get the epsilon, dummy_precision, lowest, highest functions + { + typedef codac2::Interval Real; + typedef codac2::Interval NonInteger; + typedef codac2::Interval Nested; + typedef codac2::Interval Scalar; + typedef double RealScalar; + + enum { + IsComplex = 0, + IsInteger = 0, + IsSigned = 1, + RequireInitialization = 1, + ReadCost = 1, + AddCost = 3, + MulCost = 3 + }; + }; + + template + struct ScalarBinaryOpTraits + { typedef codac2::Interval ReturnType; }; + + template + struct ScalarBinaryOpTraits + { typedef codac2::Interval ReturnType; }; +} + +namespace codac2 +{ + using Eigen::Dynamic; + + inline const Interval& conj(const Interval& x) { return x; } + inline const Interval& real(const Interval& x) { return x; } + inline Interval imag(const Interval&) { return 0.; } + //inline Interval abs(const Interval& x) { return codac2::abs(x); } + inline Interval abs2(const Interval& x) { return codac2::sqr(x); } + + template + using Mat = Eigen::Matrix; +} + +namespace codac2 +{ + template + inline auto abs(const Eigen::MatrixBase& x) + { + using M = Eigen::MatrixBase; + Eigen::Matrix a(x); + + for(Index i = 0 ; i < x.rows() ; i++) + for(Index j = 0 ; j < x.cols() ; j++) + { + if constexpr(std::is_same_v) + a(i,j) = fabs(x(i,j)); + else + a(i,j) = abs(x(i,j)); + } + + return a; + } + + template + requires Eigen::IsIntervalDomain + inline auto hull(const std::list>& l) + { + assert_release(!l.empty()); + Eigen::Matrix h(l.front()); + for(const auto& li : l) + h |= li; + return h; + } + + inline Eigen::IOFormat codac_row_fmt() + { + return Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, " ", "", "", "", "[ ", " ]"); + } + + inline Eigen::IOFormat codac_vector_fmt() + { + return Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, "", " ; ", "", "", "[ ", " ]"); + } + + inline Eigen::IOFormat codac_matrix_fmt() + { + return Eigen::IOFormat(Eigen::StreamPrecision, 0, " , ", "\n", "[ ", " ]", "[", "]"); + } +} \ No newline at end of file diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Base.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Base.h new file mode 100644 index 00000000..ae49d330 --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Base.h @@ -0,0 +1,46 @@ +/** + * \file codac2_MatrixBase_addons_Base.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +inline bool is_squared() const +{ + return this->rows() == this->cols(); +} + +inline auto squared_norm() const +{ + return this->squaredNorm(); +} + +#define minmax_item(op) \ + Scalar m = (*this)(0,0); /* first element */ \ + for(Index i = 0 ; i < this->rows() ; i++) \ + for(Index j = 0 ; j < this->cols() ; j++) \ + { \ + if constexpr(std::is_same_v) \ + m = codac2::op(m,(*this)(i,j)); \ + else \ + m = std::op(m,(*this)(i,j)); \ + } \ + return m; \ + +inline Scalar min_coeff() const +{ + minmax_item(min); +} + +inline Scalar max_coeff() const +{ + minmax_item(max); +} \ No newline at end of file diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrix.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrix.h new file mode 100644 index 00000000..fba89179 --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrix.h @@ -0,0 +1,14 @@ +/** + * \file codac2_MatrixBase_addons_IntervalMatrix.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrixBase.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrixBase.h new file mode 100644 index 00000000..54993bd9 --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalMatrixBase.h @@ -0,0 +1,338 @@ +/** + * \file codac2_MatrixBase_addons_IntervalMatrixBase.h + * + * This class reuses some of the functions developed for ibex::IntervalMatrixBase. + * The original IBEX code is revised in modern C++ and adapted to the template + * structure proposed in Codac, based on the Eigen library. + * See ibex::IntervalMatrixBase (IBEX lib, author: Gilles Chabert) + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Gilles Chabert + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires IsIntervalDomain +inline double volume() const +{ + if(this->is_empty()) + return 0.; + + double v = 0.; + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + { + if((*this)(i,j).is_unbounded()) return codac2::oo; + if((*this)(i,j).is_degenerated()) return 0.; + v += std::log((*this)(i,j).diam()); + } + return std::exp(v); +} + +inline bool is_empty() const +{ + for(Index i = 0 ; i < rows() ; i++) + for(Index j = 0 ; j < cols() ; j++) + if((*this)(i,j).is_empty()) + return true; + return false; +} + +#define degenerate_mat(op) \ + Matrix m(this->rows(),this->cols()); \ + \ + if(this->is_empty()) \ + m.init(std::numeric_limits::quiet_NaN()); \ + \ + else \ + { \ + for(Index i = 0 ; i < this->rows() ; i++) \ + for(Index j = 0 ; j < this->cols() ; j++) \ + m(i,j) = (*this)(i,j).op(); \ + } \ + \ + return m; \ + +template + requires IsIntervalDomain +inline auto lb() const +{ + degenerate_mat(lb); +} + +template + requires IsIntervalDomain +inline auto ub() const +{ + degenerate_mat(ub); +} + +template + requires IsIntervalDomain +inline auto mid() const +{ + degenerate_mat(mid); +} + +template + requires IsIntervalDomain +inline auto mag() const +{ + degenerate_mat(mag); +} + +template + requires IsIntervalDomain +inline auto mig() const +{ + degenerate_mat(mig); +} + +template + requires IsIntervalDomain +inline auto rand() const +{ + srand(time(NULL)); + degenerate_mat(rand); +} + +template + requires IsIntervalDomain +inline auto rad() const +{ + degenerate_mat(rad); +} + +template + requires IsIntervalDomain +inline auto diam() const +{ + degenerate_mat(diam); +} + +template +inline bool contains(const MatrixBase& x) const +{ + assert_release(x.size() == this->size()); + + if(this->is_empty()) + return false; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).contains(x(i,j))) + return false; + + return true; +} + +template +inline bool interior_contains(const MatrixBase& x) const +{ + assert_release(x.size() == this->size()); + + if(this->is_empty()) + return false; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).interior_contains(x(i,j))) + return false; + + return true; +} + +inline bool is_unbounded() const +{ + if(this->is_empty()) return false; + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if((*this)(i,j).is_unbounded()) + return true; + return false; +} + +inline bool is_degenerated() const +{ + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).is_degenerated()) + return false; + return true; +} + +inline bool is_flat() const +{ + if(this->is_empty()) return true; + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if((*this)(i,j).is_degenerated()) // don't use diam() because of roundoff + return true; + return false; +} + +template +inline bool intersects(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return false; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).intersects(x(i,j))) + return false; + + return true; +} + +template +inline bool is_disjoint(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return true; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if((*this)(i,j).is_disjoint(x(i,j))) + return true; + + return false; +} + +template +inline bool overlaps(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return false; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).overlaps(x(i,j))) + return false; + + return true; +} + +template +inline bool is_subset(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return true; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).is_subset(x(i,j))) + return false; + + return true; +} + +template +inline bool is_strict_subset(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return true; + + if(!is_subset(x)) + return false; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if((*this)(i,j).is_strict_subset(x(i,j))) + return true; + + return false; +} + +template +inline bool is_interior_subset(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return true; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).is_interior_subset(x(i,j))) + return false; + + return true; +} + +template +inline bool is_strict_interior_subset(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return true; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!(*this)(i,j).is_strict_interior_subset(x(i,j))) + return false; + + return true; +} + +template +inline bool is_superset(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return false; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(!x(i,j).is_subset((*this)(i,j))) + return false; + + return true; +} + +template +inline bool is_strict_superset(const MatrixBase& x) const +{ + assert_release(this->size() == x.size()); + + if(this->is_empty()) + return false; + + if(!is_superset(x)) + return false; + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if(x(i,j).is_strict_subset((*this)(i,j))) + return true; + + return false; +} + +inline bool is_bisectable() const +{ + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + if((*this)(i,j).is_bisectable()) + return true; + return false; +} \ No newline at end of file diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalVector.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalVector.h new file mode 100644 index 00000000..d9e85d62 --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_IntervalVector.h @@ -0,0 +1,89 @@ +/** + * \file codac2_MatrixBase_addons_IntervalVector.h + * + * This class reuses some of the functions developed for ibex::IntervalVector. + * The original IBEX code is revised in modern C++ and adapted to the template + * structure proposed in Codac, based on the Eigen library. + * See ibex::IntervalVector (IBEX lib, author: Gilles Chabert) + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Gilles Chabert + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires IsIntervalDomain && IsVectorOrRow +inline auto complementary() const +{ + return Matrix((int)this->size()).diff(*this); +} + +template + requires IsIntervalDomain && IsVectorOrRow +inline std::list> diff(const MatrixBase& y, bool compactness = true) const +{ + // This code originates from the ibex-lib + // See: ibex_TemplateVector.h + // Author: Gilles Chabert + // It has been revised with modern C++ and templated types + + const Index n = this->size(); + assert_release(y.size() == n); + + if(y == *this) + return { }; + + Matrix x = *this; + Matrix z = x & y; + + if(z.is_empty()) + { + if(x.is_empty()) return { }; + else return { x }; + } + + else + { + // Check if in one dimension y is flat and x not, + // in which case the diff returns also x directly + if(compactness) + for(Index i = 0 ; i < n ; i++) + if(z[i].is_degenerated() && !x[i].is_degenerated()) + { + if(x.is_empty()) return { }; + else return { x }; + } + } + + std::list> l; + + for(Index var = 0 ; var < n ; var++) + { + codac2::Interval c1, c2; + + for(const auto& ci : x[var].diff(y[var], compactness)) + { + assert(!ci.is_empty()); + + Matrix v(n); + for(Index i = 0 ; i < var ; i++) + v[i] = x[i]; + v[var] = ci; + for(Index i = var+1 ; i < n ; i++) + v[i] = x[i]; + if(!v.is_empty()) + l.push_back(v); + } + + x[var] = z[var]; + } + + return l; +} \ No newline at end of file diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Matrix.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Matrix.h new file mode 100644 index 00000000..247e837f --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Matrix.h @@ -0,0 +1,19 @@ +/** + * \file codac2_MatrixBase_addons_Matrix.h + * + * This class reuses some of the functions developed for ibex::Matrix. + * The original IBEX code is revised in modern C++ and adapted to the template + * structure proposed in Codac, based on the Eigen library. + * See ibex::Matrix (IBEX lib, author: Gilles Chabert) + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Gilles Chabert + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_MatrixBase.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_MatrixBase.h new file mode 100644 index 00000000..6c555930 --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_MatrixBase.h @@ -0,0 +1,14 @@ +/** + * \file codac2_MatrixBase_addons_MatrixBase.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Vector.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Vector.h new file mode 100644 index 00000000..22752f58 --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_Vector.h @@ -0,0 +1,34 @@ +/** + * \file codac2_MatrixBase_addons_Vector.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires (!IsIntervalDomain) && (IsVectorOrRow) +inline Index min_coeff_index() const +{ + Index r,c; + this->minCoeff(&r,&c); + assert(c == 0); + return r; +} + +template + requires (!IsIntervalDomain) && (IsVectorOrRow) +inline Index max_coeff_index() const +{ + Index r,c; + this->maxCoeff(&r,&c); + assert(c == 0); + return r; +} \ No newline at end of file diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_VectorBase.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_VectorBase.h new file mode 100644 index 00000000..fe1a470d --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_VectorBase.h @@ -0,0 +1,30 @@ +/** + * \file codac2_MatrixBase_addons_VectorBase.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires IsVectorOrRow +inline auto diag_matrix() const +{ + return this->asDiagonal().toDenseMatrix(); +} + +template + requires IsVectorOrRow +inline auto subvector(Index start_id, Index end_id) const +{ + assert_release(end_id >= 0 && start_id >= 0); + assert_release(end_id < this->size() && start_id <= end_id); + return this->segment(start_id,end_id-start_id+1); +} \ No newline at end of file diff --git a/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_include.h b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_include.h new file mode 100644 index 00000000..30a8cb4f --- /dev/null +++ b/src/core/matrices/eigen/MatrixBase_addons/codac2_MatrixBase_addons_include.h @@ -0,0 +1,23 @@ +/** + * \file codac2_MatrixBase_addons_include.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIXBASE_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_MatrixBase_addons_Base.h" +#include "codac2_MatrixBase_addons_IntervalMatrix.h" +#include "codac2_MatrixBase_addons_IntervalMatrixBase.h" +#include "codac2_MatrixBase_addons_IntervalVector.h" +#include "codac2_MatrixBase_addons_Matrix.h" +#include "codac2_MatrixBase_addons_MatrixBase.h" +#include "codac2_MatrixBase_addons_Vector.h" +#include "codac2_MatrixBase_addons_VectorBase.h" \ No newline at end of file diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Base.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Base.h new file mode 100644 index 00000000..8ed5f578 --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Base.h @@ -0,0 +1,76 @@ +/** + * \file codac2_Matrix_addons_Base.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template +inline Scalar& operator()(Index i, Index j) +{ + return const_cast(static_cast&>(*this).operator()(i,j)); +} + +template +inline const Scalar& operator()(Index i, Index j) const +{ + assert_release(i >= 0 && i < this->rows() && j >= 0 && j < this->cols()); + + if constexpr(!IsVectorOrRow) + return this->PlainObjectBase>::operator()(i,j); + + else + { + if constexpr(R == 1) + return (*this)[j]; + return (*this)[i]; + } +} + +inline auto& init(const Scalar& x) +{ + for(Index i = 0 ; i < this->size() ; i++) + *(this->data()+i) = x; + return *this; +} + +inline auto& init(const Matrix& x) // todo: keep this? +{ + *this = x; + return *this; +} + +// This operator should be related to Eigen::MatrixBase, +// for allowing a comparison between two matrix expressions. +// However, it is not possible to overwrite Eigen::MatrixBase::operator==. +// Therefore, only comparisons between Eigen::Matrix types is possible. +// This must be corrected... +template +inline bool operator==(const Matrix& x) const +{ + if(this->size() != x.size()) + return false; + + if constexpr(std::is_same_v && std::is_same_v) + { + if(this->is_empty() || x.is_empty()) + return this->is_empty() && x.is_empty(); + } + + if(this->rows() != x.rows() || this->cols() != x.cols()) + return false; + + for(Index i = 0 ; i < this->size() ; i++) + if(*(this->data()+i) != *(x.data()+i)) + return false; + + return true; +} \ No newline at end of file diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrix.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrix.h new file mode 100644 index 00000000..059dfb19 --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrix.h @@ -0,0 +1,14 @@ +/** + * \file codac2_Matrix_addons_IntervalMatrix.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrixBase.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrixBase.h new file mode 100644 index 00000000..a5d2c48f --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalMatrixBase.h @@ -0,0 +1,301 @@ +/** + * \file codac2_Matrix_addons_IntervalMatrixBase.h + * + * This class reuses some of the functions developed for ibex::IntervalMatrixBase. + * The original IBEX code is revised in modern C++ and adapted to the template + * structure proposed in Codac, based on the Eigen library. + * See ibex::IntervalMatrixBase (IBEX lib, author: Gilles Chabert) + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Gilles Chabert + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires IsIntervalDomain +Matrix(const Matrix& lb, const Matrix& ub) + : Matrix(lb) +{ + assert_release(lb.size() == ub.size()); + + for(Index i = 0 ; i < this->size() ; i++) + { + auto& lbi = *(this->data()+i); + const auto& ubi = *(ub.data()+i); + + if(lbi.lb() > ubi) + { + set_empty(); + break; + } + + else + lbi |= ubi; + } +} + +template + requires IsIntervalDomain +Matrix(int r, int c, const double bounds[][2]) + : Matrix(r,c) +{ + assert_release(r > 0 && c > 0); + + Index k = 0; + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + { + (*this)(i,j) = codac2::Interval(bounds[k][0],bounds[k][1]); + k++; + } + assert_release(k == this->size() && "incorrect array size"); +} + +template + requires IsIntervalDomain +inline bool operator==(const MatrixBase& x) const +{ + return operator==(x.eval().template cast()); +} + +template + requires IsIntervalDomain +inline double min_rad() const +{ + return (this->data()+extr_diam_index(true))->rad(); +} + +template + requires IsIntervalDomain +inline double max_rad() const +{ + return (this->data()+extr_diam_index(false))->rad(); +} + +template + requires IsIntervalDomain +inline double min_diam() const +{ + return (this->data()+extr_diam_index(true))->diam(); +} + +template + requires IsIntervalDomain +inline double max_diam() const +{ + return (this->data()+extr_diam_index(false))->diam(); +} + +template + requires IsIntervalDomain +inline Index min_diam_index() const +{ + return extr_diam_index(true); +} + +template + requires IsIntervalDomain +inline Index max_diam_index() const +{ + return extr_diam_index(false); +} + +template + requires IsIntervalDomain +inline Index extr_diam_index(bool min) const +{ + // This code originates from the ibex-lib + // See: ibex_TemplateVector.h + // Author: Gilles Chabert + + double d = min ? codac2::oo : -1; // -1 to be sure that even a 0-diameter interval can be selected + int selected_index = -1; + bool unbounded = false; + assert_release(!this->is_empty() && "Diameter of an empty IntervalVector is undefined"); + + Index i; + + for(i = 0 ; i < this->size() ; i++) + { + if((this->data()+i)->is_unbounded()) + { + unbounded = true; + if(!min) break; + } + else + { + double w = (this->data()+i)->diam(); + if(min ? wd) + { + selected_index = i; + d = w; + } + } + } + + if(min && selected_index == -1) + { + assert(unbounded); + // the selected interval is the first one. + i = 0; + } + + // The unbounded intervals are not considered if we look for the minimal diameter + // and some bounded intervals have been found (selected_index!=-1) + if(unbounded && (!min || selected_index == -1)) + { + double pt = min ? -codac2::oo : codac2::oo; // keep the point less/most distant from +oo (we normalize if the lower bound is -oo) + selected_index = i; + + for(; i < this->size() ; i++) + { + if((this->data()+i)->lb() == -codac2::oo) + { + if((this->data()+i)->ub() == codac2::oo) + if(!min) + { + selected_index = i; + break; + } + + if((min && (-(this->data()+i)->ub() > pt)) || (!min && (-(this->data()+i)->ub() < pt))) + { + selected_index = i; + pt = -(this->data()+i)->ub(); + } + } + + else if((this->data()+i)->ub() == codac2::oo) + if((min && ((this->data()+i)->lb() > pt)) || (!min && ((this->data()+i)->lb() < pt))) + { + selected_index = i; + pt = (this->data()+i)->lb(); + } + } + } + + return selected_index; +} + +template + requires IsIntervalDomain +inline void set_empty() +{ + this->init(codac2::Interval::empty()); +} + +template + requires IsIntervalDomain +inline auto& inflate(double r) +{ + assert_release(r >= 0.); + + for(Index i = 0 ; i < this->size() ; i++) + (this->data()+i)->inflate(r); + return *this; +} + +template + requires IsIntervalDomain +inline auto& inflate(const MatrixBase& r) +{ + assert_release(this->size() == r.size()); + assert_release(r.min_coeff() >= 0.); + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + (*this)(i,j).inflate(r(i,j)); + return *this; +} + +template + requires IsIntervalDomain +inline auto& operator&=(const MatrixBase& x) +{ + assert_release(this->size() == x.size()); + + if constexpr(std::is_same_v::Scalar,codac2::Interval>) + { + if(x.is_empty()) + { + set_empty(); + return *this; + } + } + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + (*this)(i,j) &= x(i,j); + return *this; +} + +template + requires IsIntervalDomain +inline auto& operator|=(const MatrixBase& x) +{ + assert_release(this->size() == x.size()); + + if constexpr(std::is_same_v::Scalar,codac2::Interval>) + { + if(x.is_empty()) + return *this; + } + + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + (*this)(i,j) |= x(i,j); + return *this; +} + +template + requires IsIntervalDomain +inline auto operator&(const MatrixBase& x) const +{ + auto y = *this; + return y &= x; +} + +template + requires IsIntervalDomain +inline auto operator|(const MatrixBase& x) const +{ + auto y = *this; + return y |= x; +} + +template + requires IsIntervalDomain +inline static auto empty(Index r, Index c) +{ + assert_release(r >= 0 && c >= 0); + return Matrix::constant(r,c,codac2::Interval::empty()); +} + +template + requires IsIntervalDomain +inline auto bisect(Index i, float ratio = 0.49) const +{ + assert_release(i >= 0 && i < this->size()); + assert_release((this->data()+i)->is_bisectable()); + assert_release(codac2::Interval(0,1).interior_contains(ratio)); + + auto p = std::make_pair(*this,*this); + auto pi = (this->data()+i)->bisect(ratio); + *(p.first.data()+i) = pi.first; + *(p.second.data()+i) = pi.second; + return p; +} + +template + requires IsIntervalDomain +inline auto bisect_largest(float ratio = 0.49) const +{ + return bisect(max_diam_index(), ratio); +} \ No newline at end of file diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalVector.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalVector.h new file mode 100644 index 00000000..75617809 --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_IntervalVector.h @@ -0,0 +1,81 @@ +/** + * \file codac2_Matrix_addons_IntervalVector.h + * + * This class reuses some of the functions developed for ibex::IntervalVector. + * The original IBEX code is revised in modern C++ and adapted to the template + * structure proposed in Codac, based on the Eigen library. + * See ibex::IntervalVector (IBEX lib, author: Gilles Chabert) + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Gilles Chabert + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires IsIntervalDomain && IsVectorOrRow +Matrix(const std::initializer_list& l) + : Matrix( + [&]() -> int { if(R == 1) return 1; else return l.size(); }(), + [&]() -> int { if(C == 1) return 1; else return l.size(); }() + ) +{ + assert_release(!std::empty(l)); + Index i = 0; + for(const auto& li : l) + (*this)[i++] = codac2::Interval(li); +} + +template + requires IsIntervalDomain && IsVectorOrRow +Matrix(const std::initializer_list>& l) + : Matrix( + [&]() -> int { if(R == 1) return 1; else return l.size(); }(), + [&]() -> int { if(C == 1) return 1; else return l.size(); }() + ) +{ + assert_release(!std::empty(l)); + Index i = 0; + for(const auto& li : l) + (*this)[i++] = codac2::Interval(li); +} + +template + requires IsIntervalDomain && IsVectorOrRow +Matrix(const std::initializer_list& l) + : Matrix( + [&]() -> int { if(R == 1) return 1; else return l.size(); }(), + [&]() -> int { if(C == 1) return 1; else return l.size(); }() + ) +{ + assert_release(!std::empty(l)); + Index i = 0; + for(const auto& li : l) + (*this)[i++] = li; +} + +template + requires IsIntervalDomain && IsVectorOrRow +Matrix(int n, const double bounds[][2]) + : Matrix( + [&]() -> int { if(R == 1) return 1; else return n; }(), + [&]() -> int { if(C == 1) return 1; else return n; }(), + bounds + ) +{ + assert_release(n > 0); +} + +template + requires IsIntervalDomain && IsVectorOrRow +inline static auto empty(Index n) +{ + assert_release(n >= 0); + return Matrix::constant((int)n,codac2::Interval::empty()); +} \ No newline at end of file diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Matrix.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Matrix.h new file mode 100644 index 00000000..f6d28008 --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Matrix.h @@ -0,0 +1,19 @@ +/** + * \file codac2_Matrix_addons_Matrix.h + * + * This class reuses some of the functions developed for ibex::Matrix. + * The original IBEX code is revised in modern C++ and adapted to the template + * structure proposed in Codac, based on the Eigen library. + * See ibex::Matrix (IBEX lib, author: Gilles Chabert) + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Gilles Chabert + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_MatrixBase.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_MatrixBase.h new file mode 100644 index 00000000..3eb5ca87 --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_MatrixBase.h @@ -0,0 +1,89 @@ +/** + * \file codac2_Matrix_addons_MatrixBase.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires (!IsVectorOrRow) +explicit Matrix(int r, int c, const Scalar values[]) + : Matrix(r,c) +{ + assert((R==(int)r || R==-1) && (C==(int)c || C==-1)); + assert(r >= 0 && c >= 0); + + if(values == 0) + init(Scalar(0.)); // in case the user called Matrix(r,c,0) and 0 is interpreted as NULL! + + else + { + Index k = 0; + for(Index i = 0 ; i < this->rows() ; i++) + for(Index j = 0 ; j < this->cols() ; j++) + (*this)(i,j) = values[k++]; + assert(k == this->size()); + } +} + +template + requires (!IsVectorOrRow) +inline static Matrix zero(Index r, Index c) +{ + assert_release(r >= 0 && c >= 0); + return DenseBase>::Zero(r,c); +} + +template + requires (!IsVectorOrRow) +inline static Matrix ones(Index r, Index c) +{ + assert_release(r >= 0 && c >= 0); + return DenseBase>::Ones(r,c); +} + +template + requires (!IsVectorOrRow) +inline static Matrix eye(Index r, Index c) +{ + assert_release(r >= 0 && c >= 0); + return MatrixBase>::Identity(r,c); +} + +template + requires (!IsVectorOrRow) +inline static Matrix constant(Index r, Index c, const Scalar& x) +{ + assert_release(r >= 0 && c >= 0); + return DenseBase>::Constant(r,c,x); +} + +// Note that this static function is not called "rand" +// because of ambiguity with the member function "rand" +template + requires (!IsVectorOrRow) +inline static Matrix random(Index r, Index c) +{ + assert_release(r >= 0 && c >= 0); + return DenseBase>::Random(r,c); +} + +template + requires (!IsVectorOrRow) +inline void resize_save_values(Index r, Index c) +{ + // With resize() of Eigen, the data is reallocated and all previous values are lost. + auto copy = *this; + this->resize(r,c); + for(Index i = 0 ; i < std::min((Index)copy.rows(),r) ; i++) + for(Index j = 0 ; j < std::min((Index)copy.cols(),c) ; j++) + (*this)(i,j) = copy(i,j); +} \ No newline at end of file diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Vector.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Vector.h new file mode 100644 index 00000000..33e315ed --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_Vector.h @@ -0,0 +1,40 @@ +/** + * \file codac2_Matrix_addons_Vector.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires (!IsIntervalDomain) && (IsVectorOrRow) +Matrix(std::initializer_list l) + : Matrix( + [&]() -> int { if(R == 1) return 1; else return l.size(); }(), + [&]() -> int { if(C == 1) return 1; else return l.size(); }() + ) +{ + assert_release(!std::empty(l)); + Index i = 0; + for(const auto& li : l) + (*this)[i++] = li; +} + +template + requires (!IsIntervalDomain) && (IsVectorOrRow) +explicit Matrix(int n, double values[]) + : Matrix( + [&]() -> int { if(R == 1) return 1; else return n; }(), + [&]() -> int { if(C == 1) return 1; else return n; }(), + values + ) +{ + assert_release(n > 0); +} \ No newline at end of file diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_VectorBase.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_VectorBase.h new file mode 100644 index 00000000..0a825e30 --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_VectorBase.h @@ -0,0 +1,99 @@ +/** + * \file codac2_Matrix_addons_VectorBase.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +template + requires IsVectorOrRow +inline Scalar& operator()(Index i) +{ + return const_cast(const_cast*>(this)->operator()(i)); +} + +template + requires IsVectorOrRow +inline const Scalar& operator()(Index i) const +{ + assert_release(i >= 0 && i < this->size()); + return this->PlainObjectBase>::operator()(i); +} + +template + requires IsVectorOrRow +inline Scalar& operator[](Index i) +{ + return const_cast(const_cast*>(this)->operator[](i)); +} + +template + requires IsVectorOrRow +inline const Scalar& operator[](Index i) const +{ + assert_release(i >= 0 && i < this->size()); + return this->PlainObjectBase>::operator[](i); +} + +template + requires IsVectorOrRow +inline static Matrix zero(Index n) +{ + assert_release(n >= 0); + return DenseBase>::Zero(n); +} + +template + requires IsVectorOrRow +inline static Matrix ones(Index n) +{ + assert_release(n >= 0); + return DenseBase>::Ones(n); +} + +template + requires IsVectorOrRow +inline static Matrix constant(Index n, const Scalar& x) +{ + assert_release(n >= 0); + return DenseBase>::Constant(n,x); +} + +// Note that this static function is not called "rand" +// because of ambiguity with the member function "rand" +template + requires IsVectorOrRow +inline static Matrix random(Index n) +{ + assert_release(n >= 0); + return DenseBase>::Random(n); +} + +template + requires IsVectorOrRow && IsVectorOrRow::RowsAtCompileTime,MatrixBase::ColsAtCompileTime> +inline void put(Index start_id, const MatrixBase& x) +{ + assert_release(start_id >= 0 && start_id < this->size()); + assert_release(start_id+x.size() <= this->size()); + + this->segment(start_id,x.size()) << x; +} + +template + requires IsVectorOrRow +inline void resize_save_values(Index n) +{ + // With resize() of Eigen, the data is reallocated and all previous values are lost. + auto copy = *this; + this->resize(n); + for(Index i = 0 ; i < std::min((Index)copy.size(),n) ; i++) + (*this)[i] = copy[i]; +} diff --git a/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_include.h b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_include.h new file mode 100644 index 00000000..2802ca6e --- /dev/null +++ b/src/core/matrices/eigen/Matrix_addons/codac2_Matrix_addons_include.h @@ -0,0 +1,23 @@ +/** + * \file codac2_Matrix_addons_include.h + * + * This file is included in the declaration of Eigen::MatrixBase, + * thanks to the preprocessor token EIGEN_MATRIX_PLUGIN. + * See: https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html + * and the file codac2_matrices.h + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2023 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_Matrix_addons_Base.h" +#include "codac2_Matrix_addons_IntervalMatrix.h" +#include "codac2_Matrix_addons_IntervalMatrixBase.h" +#include "codac2_Matrix_addons_IntervalVector.h" +#include "codac2_Matrix_addons_Matrix.h" +#include "codac2_Matrix_addons_MatrixBase.h" +#include "codac2_Matrix_addons_Vector.h" +#include "codac2_Matrix_addons_VectorBase.h" \ No newline at end of file diff --git a/src/core/paver/codac2_pave.cpp b/src/core/paver/codac2_pave.cpp index b1ee89e4..81c5cff1 100644 --- a/src/core/paver/codac2_pave.cpp +++ b/src/core/paver/codac2_pave.cpp @@ -14,6 +14,11 @@ using namespace codac2; namespace codac2 { + PavingOut pave(const IntervalVector& x, std::shared_ptr> c, double eps) + { + return pave(x, *c, eps); + } + PavingOut pave(const IntervalVector& x, const CtcBase& c, double eps) { assert_release(eps > 0.); @@ -48,6 +53,11 @@ namespace codac2 return p; } + PavingInOut pave(const IntervalVector& x, std::shared_ptr s, double eps) + { + return pave(x, *s, eps); + } + PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps) { assert_release(eps > 0.); diff --git a/src/core/paver/codac2_pave.h b/src/core/paver/codac2_pave.h index 82f4ea44..0f8c890c 100644 --- a/src/core/paver/codac2_pave.h +++ b/src/core/paver/codac2_pave.h @@ -18,7 +18,9 @@ namespace codac2 { // eps: accuracy of the paving algorithm, the undefined boxes will have their max_diam <= eps + PavingOut pave(const IntervalVector& x, std::shared_ptr> c, double eps); PavingOut pave(const IntervalVector& x, const CtcBase& c, double eps); + PavingInOut pave(const IntervalVector& x, std::shared_ptr s, double eps); PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps); template diff --git a/src/core/proj/codac2_ProjBase.cpp b/src/core/proj/codac2_ProjBase.cpp new file mode 100644 index 00000000..62c769f4 --- /dev/null +++ b/src/core/proj/codac2_ProjBase.cpp @@ -0,0 +1,107 @@ +/** + * codac2_ProjBase.cp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_ProjBase.h" + +using namespace std; + +namespace codac2 +{ + ProjBase::ProjBase(const std::vector& proj_indices, const IntervalVector& y, double default_eps) + : _n(proj_indices.size()+y.size()), _xi(proj_indices), _y(y), _default_eps(default_eps) + { + assert(default_eps > 0.); + } + + IntervalVector ProjBase::extract_x(const IntervalVector& w) const + { + assert(w.size() == _n); + + IntervalVector x(_xi.size()); + Index k = 0; + for(const auto& xi : _xi) + x[k++] = w[xi]; + assert(k == (Index)_xi.size()); // all components have been reached + return x; + } + + IntervalVector ProjBase::extract_y(const IntervalVector& w) const + { + assert(w.size() == _n); + + IntervalVector y(_y.size()); + Index k = 0; + for(Index j = 0 ; j < w.size() ; j++) + { + bool outside_proj = true; + for(const auto& xi : _xi) + if(xi == j) + { + outside_proj = false; + break; + } + + if(outside_proj) + y[k++] = w[j]; + } + + assert(k == y.size()); // all components have been reached + return y; + } + + IntervalVector ProjBase::cart_prod_xy(const IntervalVector& x, const IntervalVector& y) const + { + assert(x.size() == (Index)_xi.size()); + assert(y.size() == _y.size()); + + Index ix = 0, iy = 0; + IntervalVector w(_n); + + for(Index j = 0 ; j < _n ; j++) + { + bool outside_proj = true; + for(const auto& xi : _xi) + if(xi == j) + { + outside_proj = false; + break; + } + + w[j] = outside_proj ? y[iy++] : x[ix++]; + } + + assert(ix+iy == w.size()); // all components have been reached + return w; + } + + Index ProjBase::y_max_diam_index(const IntervalVector& y) const + { + Index k = 0, y_max = y.max_diam_index(); + for(Index i = 0 ; i < _n ; i++) + { + bool outside_proj = true; + for(const auto& xi : _xi) + if(xi == i) + { + outside_proj = false; + break; + } + + if(outside_proj) + { + if(k == y_max) + return i; + k++; + } + } + + assert(false && "unable to find y-index"); + return 0; + } +} \ No newline at end of file diff --git a/src/core/proj/codac2_ProjBase.h b/src/core/proj/codac2_ProjBase.h new file mode 100644 index 00000000..7d629e03 --- /dev/null +++ b/src/core/proj/codac2_ProjBase.h @@ -0,0 +1,34 @@ +/** + * \file codac2_CtcProj.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include "codac2_IntervalVector.h" + +namespace codac2 +{ + class ProjBase + { + protected: + + ProjBase(const std::vector& proj_indices, const IntervalVector& y, double default_eps = 0.01); + IntervalVector extract_x(const IntervalVector& w) const; + IntervalVector extract_y(const IntervalVector& w) const; + IntervalVector cart_prod_xy(const IntervalVector& x, const IntervalVector& y) const; + Index y_max_diam_index(const IntervalVector& y) const; + + protected: + + const Index _n; + const std::vector _xi; + const IntervalVector _y; + const double _default_eps; + }; +} \ No newline at end of file diff --git a/src/core/separators/codac2_Sep.h b/src/core/separators/codac2_Sep.h index 38b3f115..48c3f571 100644 --- a/src/core/separators/codac2_Sep.h +++ b/src/core/separators/codac2_Sep.h @@ -50,13 +50,13 @@ namespace codac2 { public: - SepBase(size_t n) + SepBase(Index n) : _n(n) { assert(n > 0); } - size_t size() const + Index size() const { return _n; } @@ -66,7 +66,7 @@ namespace codac2 protected: - const size_t _n; + const Index _n; }; template @@ -74,7 +74,7 @@ namespace codac2 { public: - Sep(size_t n) + Sep(Index n) : SepBase(n) { } diff --git a/src/core/separators/codac2_SepAction.h b/src/core/separators/codac2_SepAction.h index acc31a12..66d372e8 100644 --- a/src/core/separators/codac2_SepAction.h +++ b/src/core/separators/codac2_SepAction.h @@ -26,7 +26,7 @@ namespace codac2 SepAction(const S& s, const OctaSym& a) : Sep(a.size()), _sep(s), _s(a), __s(a.invert()) { - assert_release(size_of(s) == a.size()); + assert_release(size_of(s) == (Index)a.size()); } BoxPair separate(const IntervalVector& x) const; diff --git a/src/core/separators/codac2_SepCartProd.cpp b/src/core/separators/codac2_SepCartProd.cpp index 7ddd8b88..a0025406 100644 --- a/src/core/separators/codac2_SepCartProd.cpp +++ b/src/core/separators/codac2_SepCartProd.cpp @@ -17,7 +17,7 @@ BoxPair SepCartProd::separate(const IntervalVector& x) const assert_release(x.size() == this->size()); auto x_in = x, x_out = x; - size_t i = 0; + Index i = 0; for(const auto& si : _seps) { IntervalVector xi = x.subvector(i,i+si->size()-1); diff --git a/src/core/separators/codac2_SepCartProd.h b/src/core/separators/codac2_SepCartProd.h index 9b0ab408..e15aa1bb 100644 --- a/src/core/separators/codac2_SepCartProd.h +++ b/src/core/separators/codac2_SepCartProd.h @@ -23,7 +23,7 @@ namespace codac2 SepCartProd(const Collection& seps) : Sep([seps] { - size_t n = 0; + Index n = 0; for(const auto& si : seps) n += si->size(); return n; diff --git a/src/core/separators/codac2_SepCtcBoundary.cpp b/src/core/separators/codac2_SepCtcBoundary.cpp index 89866c79..77adafeb 100644 --- a/src/core/separators/codac2_SepCtcBoundary.cpp +++ b/src/core/separators/codac2_SepCtcBoundary.cpp @@ -16,7 +16,7 @@ BoxPair SepCtcBoundary::separate(const IntervalVector& x) const { assert_release(x.size() == this->size()); - size_t attempt_nb = 5; + Index attempt_nb = 5; IntervalVector x_boundary(x); _ctc_boundary.front().contract(x_boundary); @@ -29,7 +29,7 @@ BoxPair SepCtcBoundary::separate(const IntervalVector& x) const Vector m = b.mid(); // first try: midpoint of the box BoolInterval d; - size_t k = 0; + Index k = 0; do { diff --git a/src/core/separators/codac2_SepEllipse.cpp b/src/core/separators/codac2_SepEllipse.cpp index 5a296f5f..1c1ac2d6 100644 --- a/src/core/separators/codac2_SepEllipse.cpp +++ b/src/core/separators/codac2_SepEllipse.cpp @@ -8,7 +8,6 @@ */ #include "codac2_SepEllipse.h" -#include "codac2_arithmetic.h" using namespace std; using namespace codac2; @@ -19,15 +18,15 @@ SepEllipse::SepEllipse(const Vector& q) assert_release(q.size() == 6); } -bool test_ellipse(const Vector& x, const Vector& q) +bool test_ellipse(const IntervalVector& x, const IntervalVector& q) { // todo: Interval evaluation: - return q[0] - + q[1]*x[0] - + q[2]*x[1] - + q[3]*pow(x[0],2) - + q[4]*x[0]*x[1] - + q[5]*pow(x[1],2) < 0.; + return (q[0] + + q[1]*x[0] + + q[2]*x[1] + + q[3]*pow(x[0],2) + + q[4]*x[0]*x[1] + + q[5]*pow(x[1],2)).ub() < 0.; } BoxPair SepEllipse::separate(const IntervalVector& x) const @@ -46,7 +45,7 @@ BoxPair SepEllipse::separate(const IntervalVector& x) const return { x_in, IntervalVector::empty(2) }; } - size_t i = Vector(x_out.rad()-p.rad()).max_coeff_index(); + Index i = Vector(x_out.rad()-p.rad()).max_coeff_index(); double e1 = p[i].lb() - x_out[i].lb(); double e2 = x_out[i].ub() - p[i].ub(); diff --git a/src/core/separators/codac2_SepPolygon.cpp b/src/core/separators/codac2_SepPolygon.cpp index 4fb832ea..302dc16c 100644 --- a/src/core/separators/codac2_SepPolygon.cpp +++ b/src/core/separators/codac2_SepPolygon.cpp @@ -9,6 +9,7 @@ #include #include "codac2_SepPolygon.h" +#include "codac2_CtcUnion.h" #include "codac2_CtcSegment.h" #include "codac2_geometry.h" diff --git a/src/core/separators/codac2_SepPolygon.h b/src/core/separators/codac2_SepPolygon.h index 39f43732..ded41190 100644 --- a/src/core/separators/codac2_SepPolygon.h +++ b/src/core/separators/codac2_SepPolygon.h @@ -11,7 +11,6 @@ #include "codac2_Polygon.h" #include "codac2_SepCtcBoundary.h" -#include "codac2_CtcUnion.h" namespace codac2 { diff --git a/src/core/separators/codac2_SepProj.cpp b/src/core/separators/codac2_SepProj.cpp index 131ebb1c..b62ac9ac 100644 --- a/src/core/separators/codac2_SepProj.cpp +++ b/src/core/separators/codac2_SepProj.cpp @@ -84,92 +84,4 @@ namespace codac2 assert((x_in | x_out) == x); return { x_in, x_out }; } - - IntervalVector SepProj::extract_x(const IntervalVector& w) const - { - assert(w.size() == this->_sep.front().size()); - - IntervalVector x(_xi.size()); - size_t k = 0; - for(const auto& xi : _xi) - x[k++] = w[xi]; - assert(k == _xi.size()); // all components have been reached - return x; - } - - IntervalVector SepProj::extract_y(const IntervalVector& w) const - { - assert(w.size() == this->_sep.front().size()); - - IntervalVector y(_y.size()); - size_t k = 0; - for(size_t j = 0 ; j < w.size() ; j++) - { - bool outside_proj = true; - for(const auto& xi : _xi) - if(xi == j) - { - outside_proj = false; - break; - } - - if(outside_proj) - y[k++] = w[j]; - } - - assert(k == y.size()); // all components have been reached - return y; - } - - IntervalVector SepProj::cart_prod_xy(const IntervalVector& x, const IntervalVector& y) const - { - size_t n = this->_sep.front().size(); - assert(x.size() == this->size()); - assert(y.size() == _y.size()); - assert(x.size()+y.size() == n); - - size_t ix = 0, iy = 0; - IntervalVector w(n); - - for(size_t j = 0 ; j < n ; j++) - { - bool outside_proj = true; - for(const auto& xi : _xi) - if(xi == j) - { - outside_proj = false; - break; - } - - w[j] = outside_proj ? y[iy++] : x[ix++]; - } - - assert(ix+iy == w.size()); // all components have been reached - return w; - } - - size_t SepProj::y_max_diam_index(const IntervalVector& y) const - { - size_t k = 0, y_max = y.max_diam_index(); - for(size_t i = 0 ; i < this->_sep.front().size() ; i++) - { - bool outside_proj = true; - for(const auto& xi : _xi) - if(xi == i) - { - outside_proj = false; - break; - } - - if(outside_proj) - { - if(k == y_max) - return i; - k++; - } - } - - assert(false && "unable to find y-index"); - return 0; - } } \ No newline at end of file diff --git a/src/core/separators/codac2_SepProj.h b/src/core/separators/codac2_SepProj.h index 484659c6..c7dfa359 100644 --- a/src/core/separators/codac2_SepProj.h +++ b/src/core/separators/codac2_SepProj.h @@ -13,28 +13,30 @@ #include "codac2_Sep.h" #include "codac2_Collection.h" #include "codac2_template_tools.h" +#include "codac2_ProjBase.h" namespace codac2 { - class SepProj : public Sep + class SepProj : public Sep, protected ProjBase { public: template requires IsSepBaseOrPtr - SepProj(const S& s, const std::vector& proj_indices, double default_eps = 0.01) + SepProj(const S& s, const std::vector& proj_indices, double default_eps = 0.01) : SepProj(s, proj_indices, IntervalVector(size_of(s)-proj_indices.size()), default_eps) { } template requires IsSepBaseOrPtr - SepProj(const S& s, const std::vector& proj_indices, const IntervalVector& y, double default_eps = 0.01) - : Sep(proj_indices.size()), _sep(s), _xi(proj_indices), _y(y), _default_eps(default_eps) + SepProj(const S& s, const std::vector& proj_indices, const IntervalVector& y, double default_eps = 0.01) + : Sep(proj_indices.size()), ProjBase(proj_indices,y,default_eps), _sep(s) { - assert_release(_y.size() == size_of(s)-_xi.size()); + assert_release(_y.size() == size_of(s)-(Index)_xi.size()); assert_release(*min_element(_xi.begin(),_xi.end()) >= 0); assert_release(*max_element(_xi.begin(),_xi.end()) < size_of(s)); - assert_release(size_of(s) >= _xi.size() && "cannot compute a projection of a set into a superset"); + assert_release(size_of(s) >= (Index)_xi.size() && "cannot compute a projection of a set into a superset"); + assert_release(default_eps > 0.); } BoxPair separate(const IntervalVector& x) const; @@ -42,14 +44,6 @@ namespace codac2 protected: - IntervalVector extract_x(const IntervalVector& w) const; - IntervalVector extract_y(const IntervalVector& w) const; - IntervalVector cart_prod_xy(const IntervalVector& x, const IntervalVector& y) const; - size_t y_max_diam_index(const IntervalVector& w) const; - const Collection _sep; - const std::vector _xi; - const IntervalVector _y; - const double _default_eps; }; } \ No newline at end of file diff --git a/src/core/tools/codac2_Approx.h b/src/core/tools/codac2_Approx.h index 4584f742..46e3ccf1 100644 --- a/src/core/tools/codac2_Approx.h +++ b/src/core/tools/codac2_Approx.h @@ -11,6 +11,7 @@ #include #include "codac2_IntervalVector.h" +#include "codac2_matrices.h" namespace codac2 { @@ -26,7 +27,12 @@ namespace codac2 public: explicit Approx(const T& x, double eps = std::numeric_limits::epsilon()*10) - : _x(x ), _eps(eps) + : _x(x), _eps(eps) + { } + + template + explicit Approx(const Eigen::MatrixBase& x, double eps = std::numeric_limits::epsilon()*10) + : _x(x.eval()), _eps(eps) { } friend bool operator==(const T& x1, const Approx& x2) @@ -47,7 +53,7 @@ namespace codac2 { if constexpr(std::is_same_v || std::is_same_v) { - for(size_t i = 0 ; i < x1.size() ; i++) + for(Index i = 0 ; i < x1.size() ; i++) if(!(((std::fabs(_lb(x1[i])-_lb(x2._x[i])) < x2._eps) && _ub(x1[i]) == _ub(x2._x[i])) || ((std::fabs(_ub(x1[i])-_ub(x2._x[i])) < x2._eps) && _lb(x1[i]) == _lb(x2._x[i])) || ((std::fabs(_lb(x1[i])-_lb(x2._x[i])) < x2._eps) && std::fabs(_ub(x1[i])-_ub(x2._x[i])) < x2._eps))) @@ -56,8 +62,8 @@ namespace codac2 else { - for(size_t i = 0 ; i < x1.nb_rows() ; i++) - for(size_t j = 0 ; j < x1.nb_cols() ; j++) + for(Index i = 0 ; i < x1.rows() ; i++) + for(Index j = 0 ; j < x1.cols() ; j++) if(!(((std::fabs(_lb(x1(i,j))-_lb(x2._x(i,j))) < x2._eps) && _ub(x1(i,j)) == _ub(x2._x(i,j))) || ((std::fabs(_ub(x1(i,j))-_ub(x2._x(i,j))) < x2._eps) && _lb(x1(i,j)) == _lb(x2._x(i,j))) || ((std::fabs(_lb(x1(i,j))-_lb(x2._x(i,j))) < x2._eps) && std::fabs(_ub(x1(i,j))-_ub(x2._x(i,j))) < x2._eps))) diff --git a/src/core/matrices/codac2_arithmetic.h b/src/core/tools/codac2_Index.h similarity index 59% rename from src/core/matrices/codac2_arithmetic.h rename to src/core/tools/codac2_Index.h index fe022cba..874b0818 100644 --- a/src/core/matrices/codac2_arithmetic.h +++ b/src/core/tools/codac2_Index.h @@ -1,5 +1,5 @@ /** - * \file codac2_arithmetic.h + * \file codac2_Index.h * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou @@ -9,7 +9,8 @@ #pragma once -#include "codac2_arithmetic_add.h" -#include "codac2_arithmetic_sub.h" -#include "codac2_arithmetic_mul.h" -#include "codac2_arithmetic_div.h" \ No newline at end of file +namespace codac2 +{ + // The Index type is the same as for Eigen + typedef long int Index; +} \ No newline at end of file diff --git a/src/core/tools/codac2_assert.h b/src/core/tools/codac2_assert.h index 7c68dd64..c054a228 100644 --- a/src/core/tools/codac2_assert.h +++ b/src/core/tools/codac2_assert.h @@ -18,7 +18,7 @@ namespace codac2 { #if defined FAST_RELEASE & defined NDEBUG - #define assert_release(ignore_test,ignore_message) ((void)0) + #define assert_release(ignore_test) ((void)0) #else diff --git a/src/core/tools/codac2_math.h b/src/core/tools/codac2_math.h index cb895966..ba4cae14 100644 --- a/src/core/tools/codac2_math.h +++ b/src/core/tools/codac2_math.h @@ -9,8 +9,9 @@ #pragma once +#include + namespace codac2 { - constexpr double pi = 3.141592653589793238462643383279; - // To be replaced by C++20 implementation providing portable pi value. + constexpr double pi = std::numbers::pi; // Need C++20 } \ No newline at end of file diff --git a/src/core/tools/codac2_template_tools.h b/src/core/tools/codac2_template_tools.h index ea5dad5b..0e1cd4cf 100644 --- a/src/core/tools/codac2_template_tools.h +++ b/src/core/tools/codac2_template_tools.h @@ -15,16 +15,6 @@ namespace codac2 { - template - concept IsMatrix = (std::is_same_v - || std::is_same_v&,double>,T> - || std::is_same_v&,double>,T>); - - template - concept IsIntervalMatrix = (std::is_same_v - || std::is_same_v&,Interval>,T> - || std::is_same_v&,Interval>,T>); - template concept IsCtcBaseOrPtr = (std::is_base_of_v,C> || std::is_same_v>,C>); @@ -36,22 +26,22 @@ namespace codac2 concept IsSepBaseOrPtr = (std::is_base_of_v || std::is_base_of_v>); - inline size_t size_of(int x) + inline Index size_of([[maybe_unused]] int x) { return 1; } - inline size_t size_of(double x) + inline Index size_of([[maybe_unused]] double x) { return 1; } - inline size_t size_of(const std::shared_ptr>& x) + inline Index size_of(const std::shared_ptr>& x) { return x->size(); } - inline size_t size_of(const std::shared_ptr& x) + inline Index size_of(const std::shared_ptr& x) { return x->size(); } @@ -60,7 +50,7 @@ namespace codac2 requires (!std::is_base_of_v>,T> && !std::is_base_of_v,T> && !std::is_same_v && !std::is_same_v) - inline size_t size_of(const T& x) + inline Index size_of(const T& x) { return x.size(); } @@ -78,7 +68,7 @@ namespace codac2 } template - size_t size_first_item(const T&... x) + Index size_first_item(const T&... x) { return size_of(std::get<0>(std::make_tuple(x...))); } diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp index f75191c7..b9349c99 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp @@ -2,13 +2,14 @@ * codac2_Figure2D_IPE.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Maël Godard * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ #include #include "codac2_Figure2D_IPE.h" +#include "codac2_math.h" using namespace std; using namespace codac2; @@ -34,7 +35,7 @@ Figure2D_IPE::Figure2D_IPE(const Figure2D& fig) for(const auto& ci : codac_colors) // substr is needed to remove the "#" at the beginning of hex_str (deprecated by IPE) - _colors.emplace(ci.hex_str.substr(1), ci); + _colors.emplace(ci.hex_str().substr(1), ci); } Figure2D_IPE::~Figure2D_IPE() @@ -68,42 +69,77 @@ void Figure2D_IPE::update_window_properties() } -void Figure2D_IPE::center_viewbox(const Vector& c, const Vector& r) +void Figure2D_IPE::center_viewbox([[maybe_unused]] const Vector& c, [[maybe_unused]] const Vector& r) { assert(_fig.size() <= c.size() && _fig.size() <= r.size()); assert(r.min_coeff() > 0.); } -void Figure2D_IPE::begin_path(const StyleProperties& s) +std::string ipe_str(const Color& c) +{ + return c.hex_str().substr(1); +} + +int ipe_opacity(const Color& c) +{ + return (int)(10.*round(10.*(c.model()==Model::RGB ? (c[3]/255.):(c[3]/100.)))); +} + +void Figure2D_IPE::begin_path(const StyleProperties& s, bool tip=false) +{ + // substr is needed to remove the "#" at the beginning of hex_str (deprecated by IPE) + _colors.emplace(ipe_str(s.stroke_color), s.stroke_color); + _colors.emplace(ipe_str(s.fill_color), s.fill_color); + + _f_temp_content << "\n \ + \n"; +} + +void Figure2D_IPE::begin_path_with_matrix(const Vector& x, float length, const StyleProperties& s) { // substr is needed to remove the "#" at the beginning of hex_str (deprecated by IPE) - _colors.emplace(s.stroke_color.hex_str.substr(1), s.stroke_color); - _colors.emplace(s.fill_color.hex_str.substr(1), s.fill_color); + _colors.emplace(ipe_str(s.stroke_color), s.stroke_color); + _colors.emplace(ipe_str(s.fill_color), s.fill_color); _f_temp_content << "\n \ \n "; + stroke=\"codac_color_" << ipe_str(s.stroke_color) << "\" \n \ + fill=\"codac_color_" << ipe_str(s.fill_color) << "\" \n \ + opacity=\"" << ipe_opacity(s.fill_color) << "%\" \n \ + stroke-opacity=\"" << ipe_opacity(s.stroke_color) << "%\" \n \ + pen=\"heavier\" \n \ + matrix="; + + // Matrix is composed of the 4 components of the 2D transformation matrix and the translation vector + _f_temp_content << "\"" << scale_length(length) * std::cos(x[j()+1]) << " " << scale_length(length) * std::sin(x[j()+1]) << " " + << - scale_length(length) * std::sin(x[j()+1]) << " " << scale_length(length) * std::cos(x[j()+1]) << " " + << scale_x(x[i()]) << " " << scale_y(x[j()]) << "\">\n"; } void Figure2D_IPE::draw_point(const Vector& c, const StyleProperties& s) { assert(_fig.size() <= c.size()); - _colors.emplace(s.stroke_color.hex_str.substr(1), s.stroke_color); - _colors.emplace(s.fill_color.hex_str.substr(1), s.fill_color); + _colors.emplace(ipe_str(s.stroke_color), s.stroke_color); + _colors.emplace(ipe_str(s.fill_color), s.fill_color); _f_temp_content << "\n \ "; + stroke=\"codac_color_" << ipe_str(s.stroke_color) << "\" \n \ + fill=\"codac_color_" << ipe_str(s.fill_color) << "\" \n \ + opacity=\"" << ipe_opacity(s.fill_color) << "%\" \n \ + stroke-opacity=\"" << ipe_opacity(s.stroke_color) << "%\" \n \ + size=\"normal\"\n/>"; } void Figure2D_IPE::draw_box(const IntervalVector& x, const StyleProperties& s) @@ -144,9 +180,8 @@ void Figure2D_IPE::draw_polyline(const std::vector& x, float tip_length, { assert(x.size() > 1); assert(tip_length >= 0.); - // todo: draw tip - begin_path(s); + begin_path(s, tip_length>2e-3*_fig.scaled_unit()); for(size_t k = 0 ; k < x.size() ; k++) { @@ -166,14 +201,37 @@ void Figure2D_IPE::draw_pie(const Vector& c, const Interval& r, const Interval& { assert(_fig.size() <= c.size()); assert(r.lb() >= 0.); - // Not implemented yet + + begin_path(s); + + Vector point1 ({r.lb() * std::cos(theta.lb()), r.lb() * std::sin(theta.lb())}); + Vector point2 ({r.ub() * std::cos(theta.lb()), r.ub() * std::sin(theta.lb())}); + Vector point3 ({r.ub() * std::cos(theta.ub()), r.ub() * std::sin(theta.ub())}); + Vector point4 ({r.lb() * std::cos(theta.ub()), r.lb() * std::sin(theta.ub())}); + + _f_temp_content << scale_x(c[0] + point1[0]) << " " << scale_y(c[1] + point1[1]) << " m \n"; + _f_temp_content << scale_x(c[0] + point2[0]) << " " << scale_y(c[1] + point2[1]) << " l \n"; + _f_temp_content << scale_length(r.ub()) << " 0 0 " << scale_length(r.ub()) << " " + << scale_x(c[i()]) << " " << scale_y(c[j()]) << " " + << scale_x(c[0] + point3[0]) << " " << scale_y(c[1] + point3[1]) << " a \n"; + _f_temp_content << scale_x(c[0] + point4[0]) << " " << scale_y(c[1] + point4[1]) << " l \n"; + _f_temp_content << scale_length(r.lb()) << " 0 0 " << - scale_length(r.lb()) << " " + << scale_x(c[i()]) << " " << scale_y(c[j()]) << " " + << scale_x(c[0] + point1[0]) << " " << scale_y(c[1] + point1[1]) << " a \n"; + + _f_temp_content << ""; } void Figure2D_IPE::draw_ellipse(const Vector& c, const Vector& ab, double theta, const StyleProperties& s) { assert(c.size() == 2); assert(ab.size() == 2); - // Not implemented yet + + begin_path(s); + _f_temp_content << scale_length(ab[0]) * std::cos(theta) << " " << scale_length(ab[0]) * std::sin(theta) << " " + << - scale_length(ab[1]) * std::sin(theta) << " " << scale_length(ab[1]) * std::cos(theta) << " " + << scale_x(c[i()]) << " " << scale_y(c[j()]) << " e \n"; + _f_temp_content << ""; } void Figure2D_IPE::draw_tank(const Vector& x, float size, const StyleProperties& s) @@ -181,7 +239,16 @@ void Figure2D_IPE::draw_tank(const Vector& x, float size, const StyleProperties& assert(_fig.size() <= x.size()+1); assert(j()+1 < x.size()); assert(size >= 0.); - // Not implemented yet + + float length=size/4.0; // from VIBes : initial vehicle's length is 4 + + begin_path_with_matrix(x,length,s); + + constexpr char tank_shape[] = " 1 -1.5 m \n -1 -1.5 l \n 0 -1.5 l \n 0 -1 l \n -1 -1 l \n -1 1 l \n 0 1 l \n 0 1.5 l \n -1 1.5 l \n 1 1.5 l \n 0 1.5 l \n 0 1 l \n 3 0.5 l \n 3 -0.5 l \n 0 -1 l \n 0 -1.5 l \n"; + + _f_temp_content << tank_shape; + + _f_temp_content << ""; } void Figure2D_IPE::draw_AUV(const Vector& x, float size, const StyleProperties& s) @@ -189,7 +256,34 @@ void Figure2D_IPE::draw_AUV(const Vector& x, float size, const StyleProperties& assert(_fig.size() <= x.size()+1); assert(j()+1 < x.size()); assert(size >= 0.); - // Not implemented yet + + float length=size/7.0; // from VIBes : initial vehicle's length is 7 + + _f_temp_content<<"\n\n"; + + // Body + + begin_path_with_matrix(x,length,s); + + constexpr char body_shape[] = " -4 0 m \n -2 1 l \n 2 1 l \n 2.17365 0.984808 l \n 2.34202 0.939693 l \n 2.5 0.866025 l \n 2.64279 0.766044 l \n 2.76604 0.642788 l \n 2.86603 0.5 l \n 2.93969 0.34202 l \n 2.98481 0.173648 l \n 3 0 l \n 2.98481 -0.173648 l \n 2.93969 -0.34202 l \n 2.86603 -0.5 l \n 2.76604 -0.642788 l \n 2.64279 -0.766044 l \n 2.5 -0.866025 l \n 2.34202 -0.939693 l \n 2.17365 -0.984808 l \n 2 -1 l \n -2 -1 l \n -4 0 l \n"; + + _f_temp_content << body_shape; + + _f_temp_content << "\n"; + + // Propulsion unit + + constexpr char propeller_shape[] = " -4 1 m \n -3.25 1 l \n -3.25 -1 l \n -4 -1 l \n -4 1 l \n"; + + begin_path_with_matrix(x,length,s); + + _f_temp_content << propeller_shape; + + _f_temp_content << "\n"; + + _f_temp_content<<""; + + } double Figure2D_IPE::scale_x(double x) const @@ -459,9 +553,12 @@ void Figure2D_IPE::print_header_page() \n \ \n"; - for(const auto& [k,c] : _colors) - _f << " \n"; + for(auto& [k,c] : _colors) + { + Color c_rgb = c.rgb(); + _f << " \n"; + } _f << " \n \ \n \ @@ -490,14 +587,14 @@ void Figure2D_IPE::print_header_page() \n \ \n \ \n \ - \n \ + \n \ \n \ \n \ \n \ - \n \ - \n \ - \n \ - \n \ + \n \ + \n \ + \n \ + \n \ \n \ \n \ \n \ diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h index 3b6e1a3a..df0d5083 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h @@ -2,7 +2,7 @@ * \file codac2_Figure2D_IPE.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Maël Godard * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -29,7 +29,26 @@ namespace codac2 void update_axes(); void update_window_properties(); void center_viewbox(const Vector& c, const Vector& r); - void begin_path(const StyleProperties& s); + void begin_path(const StyleProperties& s,bool tip); + + /* For future doc: + https://github.com/codac-team/codac/pull/126#discussion_r1829030491 + Pour les véhicules (draw_tank et draw_AUV) le header par défaut du begin_path n'est pas suffisant. + J'ai donc ajouté cette fonction qui fait le même travail que le begin_path, avec en plus le champ + "matrix" complété. + Ce champ contient 6 valeurs : les 4 premières sont la matrice de transformation 2D, rotation et + dilatation, "par colonne" (i.e. m11, m21, m12, m22) et les 2 autres valeurs sont la translation. + Le tout permet de scale le véhicule, l'orienter et le déplacer au bon endroit. + Cette fonction écrit dans le xml quelque chose dans le style : + + */ + void begin_path_with_matrix(const Vector& x, float length, const StyleProperties& s); // Geometric shapes void draw_point(const Vector& c, const StyleProperties& s = StyleProperties()); diff --git a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp index 3b5a9d94..582e5a97 100644 --- a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp +++ b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp @@ -144,5 +144,5 @@ void Figure2D_VIBes::draw_AUV(const Vector& x, float size, const StyleProperties string Figure2D_VIBes::to_vibes_style(const StyleProperties& s) { - return s.stroke_color.hex_str + "[" + s.fill_color.hex_str + "]"; + return s.stroke_color.hex_str() + "[" + s.fill_color.hex_str() + "]"; } \ No newline at end of file diff --git a/src/graphics/3rd/vibes/vibes.cpp b/src/graphics/3rd/vibes/vibes.cpp index 63038abd..e55a9c13 100644 --- a/src/graphics/3rd/vibes/vibes.cpp +++ b/src/graphics/3rd/vibes/vibes.cpp @@ -1,7 +1,7 @@ // This file is part of VIBes' C++ API // // Copyright (c) 2013-2015 Vincent Drevelle, Jeremy Nicola, Simon Rohou, -// Benoit Desrochers +// Benoit Desrochers, Maël Godard // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,7 @@ #include #include #include +#include // // Vibes properties key,value system implementation @@ -94,7 +95,8 @@ namespace vibes namespace { /// Current communication file descriptor - FILE *channel=0; + // FILE *channel=nullptr; + std::shared_ptr channel; /// Current figure name (client-maintained state) string current_fig="default"; @@ -125,59 +127,83 @@ namespace vibes void beginDrawing(const std::string &fileName) { - channel=fopen(fileName.c_str(),"a"); + if (!channel) + channel = std::shared_ptr( + fopen(fileName.c_str(),"a"), + // Callback for automatically closing the file + // when the shared_ptr is released: + [](FILE* file) { + if(file) + fclose(file); + } + ); + } + + void beginDrawingIfNeeded() + { + if (!channel) + { + beginDrawing(); + } } void endDrawing() { - fclose(channel); + } + + // // Figure management // void newFigure(const std::string &figureName) { + beginDrawingIfNeeded(); std::string msg; if (!figureName.empty()) current_fig = figureName; msg ="{\"action\":\"new\"," "\"figure\":\""+(figureName.empty()?current_fig:figureName)+"\"}\n\n"; - fputs(msg.c_str(),channel); - fflush(channel); + fputs(msg.c_str(),channel.get()); + fflush(channel.get()); } void clearFigure(const std::string &figureName) { + beginDrawingIfNeeded(); std::string msg; msg="{\"action\":\"clear\"," "\"figure\":\""+(figureName.empty()?current_fig:figureName)+"\"}\n\n"; - fputs(msg.c_str(),channel); - fflush(channel); + fputs(msg.c_str(),channel.get()); + fflush(channel.get()); } void closeFigure(const std::string &figureName) { + beginDrawingIfNeeded(); std::string msg; msg="{\"action\":\"close\"," "\"figure\":\""+(figureName.empty()?current_fig:figureName)+"\"}\n\n"; - fputs(msg.c_str(),channel); - fflush(channel); + fputs(msg.c_str(),channel.get()); + fflush(channel.get()); } void saveImage(const std::string &fileName, const std::string &figureName) { - std::string msg; - msg="{\"action\":\"export\"," - "\"figure\":\""+(figureName.empty()?current_fig:figureName)+"\"," - "\"file\":\""+fileName+"\"}\n\n"; - fputs(msg.c_str(),channel); - fflush(channel); + beginDrawingIfNeeded(); + std::string msg; + msg="{\"action\":\"export\"," + "\"figure\":\""+(figureName.empty()?current_fig:figureName)+"\"," + "\"file\":\""+fileName+"\"}\n\n"; + fputs(msg.c_str(),channel.get()); + fflush(channel.get()); } void selectFigure(const std::string &figureName) { - current_fig = figureName; + beginDrawingIfNeeded(); + current_fig = figureName; } @@ -187,17 +213,20 @@ namespace vibes void axisAuto(const std::string &figureName) { + beginDrawingIfNeeded(); setFigureProperty(figureName.empty()?current_fig:figureName, "viewbox", "auto"); } void axisLimits(const double &x_lb, const double &x_ub, const double &y_lb, const double &y_ub, const std::string &figureName) { + beginDrawingIfNeeded(); Vec4d v4d = { x_lb, x_ub, y_lb, y_ub }; setFigureProperty(figureName.empty()?current_fig:figureName, "viewbox", v4d); } void axisLabels(const std::string &x_label, const std::string &y_label, const std::string &figureName) { + beginDrawingIfNeeded(); vector labels; labels.push_back(x_label); labels.push_back(y_label); @@ -206,6 +235,7 @@ namespace vibes void axisLabels(const std::vector &labels, const std::string &figureName) { + beginDrawingIfNeeded(); setFigureProperty( figureName.empty()?current_fig:figureName, "axislabels", labels); } @@ -216,18 +246,20 @@ namespace vibes void drawBox(const double &x_lb, const double &x_ub, const double &y_lb, const double &y_ub, Params params) { + beginDrawingIfNeeded(); Vec4d v4d = { x_lb, x_ub, y_lb, y_ub }; Params msg; msg["action"] = "draw"; msg["figure"] = params.pop("figure",current_fig); msg["shape"] = (params, "type", "box", "bounds", v4d); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawBox(const vector &bounds, Params params) { + beginDrawingIfNeeded(); assert(!bounds.empty()); assert(bounds.size()%2 == 0); @@ -236,13 +268,14 @@ namespace vibes msg["figure"] = params.pop("figure",current_fig); msg["shape"] = (params, "type", "box", "bounds", vector(bounds.begin(),bounds.end())); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawEllipse(const double &cx, const double &cy, const double &a, const double &b, const double &rot, Params params) { + beginDrawingIfNeeded(); Vec2d vc = { cx, cy }; Vec2d va = {a, b}; Params msg; @@ -253,14 +286,15 @@ namespace vibes "axis", va, "orientation", rot); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawConfidenceEllipse(const double &cx, const double &cy, const double &sxx, const double &sxy, const double &syy, const double &K, Params params) { + beginDrawingIfNeeded(); Vec2d vc = {cx, cy}; Vec4d vcov = { sxx, sxy, sxy, syy }; Params msg; @@ -271,13 +305,14 @@ namespace vibes "covariance", vcov, "sigma", K); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawConfidenceEllipse(const vector ¢er, const vector &cov, const double &K, Params params) { + beginDrawingIfNeeded(); Params msg; msg["action"] = "draw"; msg["figure"] = params.pop("figure",current_fig); @@ -286,13 +321,14 @@ namespace vibes "covariance", vector(cov.begin(),cov.end()), "sigma", K); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawSector(const double &cx, const double &cy, const double &a, const double &b, const double &startAngle, const double &endAngle, Params params) { + beginDrawingIfNeeded(); // Angle need to be in degree Params msg; Vec2d cxy={ cx, cy }; @@ -306,13 +342,14 @@ namespace vibes "orientation", 0, "angles", startEnd); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawPie(const double &cx, const double &cy, const double &r_min, const double &r_max, const double &theta_min, const double &theta_max, Params params) { + beginDrawingIfNeeded(); // Angle need to be in degree Params msg; Vec2d cxy = { cx, cy }; @@ -325,36 +362,39 @@ namespace vibes "rho", rMinMax, "theta", thetaMinMax); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawPoint(const double &cx, const double &cy, Params params) { + beginDrawingIfNeeded(); Params msg; Vec2d cxy = { cx, cy }; msg["action"]="draw"; msg["figure"]=params.pop("figure",current_fig); msg["shape"]=(params, "type","point", "point",cxy); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawPoint(const double &cx, const double &cy, const double &radius, Params params) { + beginDrawingIfNeeded(); Params msg; Vec2d cxy = { cx, cy }; msg["action"]="draw"; msg["figure"]=params.pop("figure",current_fig); msg["shape"]=(params, "type","point", "point",cxy,"Radius",radius); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawRing(const double &cx, const double &cy, const double &r_min, const double &r_max, Params params) { + beginDrawingIfNeeded(); Params msg; Vec2d cxy = { cx, cy }; Vec2d rMinMax = { r_min, r_max }; @@ -363,48 +403,52 @@ namespace vibes msg["shape"] = (params, "type", "ring", "center", cxy, "rho", rMinMax); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawBoxes(const std::vector > &bounds, Params params) { + beginDrawingIfNeeded(); Params msg; msg["action"] = "draw"; msg["figure"] = params.pop("figure",current_fig); msg["shape"] = (params, "type", "boxes", "bounds", bounds); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawBoxesUnion(const std::vector > &bounds, Params params) { + beginDrawingIfNeeded(); Params msg; msg["action"] = "draw"; msg["figure"] = params.pop("figure",current_fig); msg["shape"] = (params, "type", "boxes union", "bounds", bounds); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawLine(const std::vector > &points, Params params) { + beginDrawingIfNeeded(); Params msg; msg["action"] = "draw"; msg["figure"] = params.pop("figure",current_fig); msg["shape"] = (params, "type", "line", "points", points); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawLine(const std::vector &x, const std::vector &y, Params params) { + beginDrawingIfNeeded(); // Reshape x and y into a vector of points std::vector points; std::vector::const_iterator itx = x.begin(); @@ -422,8 +466,8 @@ namespace vibes msg["shape"] = (params, "type", "line", "points", points); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } //void drawPoints(const std::vector > &points, Params params) @@ -433,8 +477,8 @@ namespace vibes // msg["figure"] = params.pop("figure",current_fig); // msg["shape"] = (params, "type", "points", // "points", points); - // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - // fflush(channel); + // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + // fflush(channel.get()); //} //void drawPoints(const std::vector > &points, const std::vector &colorLevels, const std::vector &radiuses, Params params) @@ -446,12 +490,13 @@ namespace vibes // "points", points, // "colorLevels", colorLevels, // "radiuses", radiuses); - // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - // fflush(channel); + // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + // fflush(channel.get()); //} void drawPoints(const std::vector &x, const std::vector &y, Params params) { + beginDrawingIfNeeded(); // Reshape x and y into a vector of points std::vector points; std::vector::const_iterator itx = x.begin(); @@ -469,8 +514,8 @@ namespace vibes msg["shape"] = (params, "type", "points", "centers", points); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } //void drawPoints(const std::vector &x, const std::vector y, const std::vector &colorLevels, Params params) @@ -493,8 +538,8 @@ namespace vibes // "points", points, // "colorLevels", colorLevels); // - // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - // fflush(channel); + // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + // fflush(channel.get()); //} //void drawPoints(const std::vector &x, const std::vector y, const std::vector &colorLevels, const std::vector &radiuses, Params params) @@ -518,12 +563,13 @@ namespace vibes // "colorLevels", colorLevels, // "radiuses", radiuses); // - // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - // fflush(channel); + // fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + // fflush(channel.get()); //} void drawArrow(const double &xA, const double &yA, const double &xB, const double &yB, const double &tip_length, Params params) { + beginDrawingIfNeeded(); // Reshape A and B into a vector of points std::vector points; Vec2d va = { xA, yA }; @@ -539,12 +585,13 @@ namespace vibes "points", points, "tip_length", tip_length); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawArrow(const std::vector > &points, const double &tip_length, Params params) { + beginDrawingIfNeeded(); Params msg; msg["action"] = "draw"; msg["figure"] = params.pop("figure",current_fig); @@ -552,12 +599,13 @@ namespace vibes "points", points, "tip_length", tip_length); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawArrow(const std::vector &x, const std::vector &y, const double &tip_length, Params params) { + beginDrawingIfNeeded(); // Reshape x and y into a vector of points std::vector points; std::vector::const_iterator itx = x.begin(); @@ -576,12 +624,13 @@ namespace vibes "points", points, "tip_length", tip_length); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawPolygon(const std::vector &x, const std::vector &y, Params params) { + beginDrawingIfNeeded(); // Reshape x and y into a vector of points std::vector points; std::vector::const_iterator itx = x.begin(); @@ -599,12 +648,13 @@ namespace vibes msg["shape"] = (params, "type", "polygon", "bounds", points); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawVehicle(const double &cx, const double &cy, const double &rot, const double &length, Params params) { + beginDrawingIfNeeded(); Vec2d vc = { cx, cy }; Params msg; msg["action"] = "draw"; @@ -614,12 +664,13 @@ namespace vibes "length", length, "orientation", rot); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawAUV(const double &cx, const double &cy, const double &rot, const double &length, Params params) { + beginDrawingIfNeeded(); Vec2d vc = { cx, cy }; Params msg; msg["action"] = "draw"; @@ -629,12 +680,13 @@ namespace vibes "length", length, "orientation", rot); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawTank(const double &cx, const double &cy, const double &rot, const double &length, Params params) { + beginDrawingIfNeeded(); Vec2d vc = { cx, cy }; Params msg; msg["action"] = "draw"; @@ -644,12 +696,13 @@ namespace vibes "length", length, "orientation", rot); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void drawRaster(const std::string& rasterFilename, const double &xlb, const double &yub, const double &xres, const double &yres, Params params) { + beginDrawingIfNeeded(); Vec2d ul_corner = { xlb, yub }; Vec2d scale = { xres, yres }; @@ -662,13 +715,14 @@ namespace vibes "scale", scale ); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void newGroup(const std::string &name, Params params) { + beginDrawingIfNeeded(); // Send message Params msg; msg["action"] = "draw"; @@ -676,19 +730,20 @@ namespace vibes msg["shape"] = (params, "type", "group", "name", name); - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void clearGroup(const std::string &figureName, const std::string &groupName) { + beginDrawingIfNeeded(); Params msg; msg["action"] = "clear"; msg["figure"] = figureName; msg["group"] = groupName; - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void clearGroup(const std::string &groupName) @@ -699,13 +754,14 @@ namespace vibes void removeObject(const std::string &figureName, const std::string &objectName) { + beginDrawingIfNeeded(); Params msg; msg["action"] = "delete"; msg["figure"] = figureName; msg["object"] = objectName; - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void removeObject(const std::string &objectName) @@ -716,23 +772,26 @@ namespace vibes // Property modification void setFigureProperties(const std::string &figureName, const Params &properties) { + beginDrawingIfNeeded(); // Send message Params msg; msg["action"] = "set"; msg["figure"] = figureName; msg["properties"] = properties; - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void setFigureProperties(const Params &properties) { + beginDrawingIfNeeded(); setFigureProperties(current_fig, properties); } void setObjectProperties(const std::string &figureName, const std::string &objectName, const Params &properties) { + beginDrawingIfNeeded(); // Send message Params msg; msg["action"] = "set"; @@ -740,12 +799,12 @@ namespace vibes msg["object"] = objectName; msg["properties"] = properties; - fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel); - fflush(channel); + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); } void setObjectProperties(const std::string &objectName, const Params &properties) { setObjectProperties(current_fig, objectName, properties); } -} +} \ No newline at end of file diff --git a/src/graphics/3rd/vibes/vibes.h b/src/graphics/3rd/vibes/vibes.h index 7fb859a9..bdfb094e 100644 --- a/src/graphics/3rd/vibes/vibes.h +++ b/src/graphics/3rd/vibes/vibes.h @@ -7,7 +7,7 @@ // This file is part of VIBes' C++ API // // Copyright (c) 2013-2015 Vincent Drevelle, Jeremy Nicola, Simon Rohou, -// Benoit Desrochers +// Benoit Desrochers, Maël Godard // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -221,9 +221,13 @@ namespace vibes { /// Start VIBes in file saving mode. All commands are saved to the specified file. void beginDrawing(const std::string &fileName); + /// Start VIBes in connected mode: connects to the VIBes viewer if needed. + void beginDrawingIfNeeded(); + /// Close connection to the viewer or the drawing file. void endDrawing(); + /** @} */ // end of group connection @@ -460,7 +464,7 @@ namespace vibes { * \param params Optional attributes * * Draws a circle of radius \a r with center at (\a cx , \a cy ). - * This functions internally calls drawEllipse + * This functions internally calls \fn drawEllipse */ inline void drawCircle(const double &cx, const double &cy, const double &r, Params params) { @@ -537,4 +541,4 @@ namespace vibes { #define vibesDrawCircle(cx,cy,r,...) vibes::drawCircle(cx,cy,r,vibesParams(__VA_ARGS__)) #endif //#ifdef VIBES_GENERATE_vibesXXX_MACROS -#endif //#ifndef VIBES_CPP_API_H +#endif //#ifndef VIBES_CPP_API_H \ No newline at end of file diff --git a/src/graphics/CMakeLists.txt b/src/graphics/CMakeLists.txt index 7b38751b..c18ba4b8 100644 --- a/src/graphics/CMakeLists.txt +++ b/src/graphics/CMakeLists.txt @@ -22,6 +22,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/styles/codac2_Color.cpp ${CMAKE_CURRENT_SOURCE_DIR}/styles/codac2_Color.h + ${CMAKE_CURRENT_SOURCE_DIR}/styles/codac2_ColorMap.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/styles/codac2_ColorMap.h ${CMAKE_CURRENT_SOURCE_DIR}/styles/codac2_StyleProperties.cpp ${CMAKE_CURRENT_SOURCE_DIR}/styles/codac2_StyleProperties.h ) diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index c9c78181..9f9d210d 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -2,16 +2,19 @@ * codac2_Figure2D.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Morgan Louédec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ +#include "codac2_Index.h" #include "codac2_Figure2D.h" #include "codac2_Figure2D_VIBes.h" #include "codac2_Figure2D_IPE.h" #include "codac2_math.h" #include "codac2_pave.h" +#include "codac2_matrices.h" +#include "codac2_Matrix.h" using namespace std; using namespace codac2; @@ -35,7 +38,7 @@ const std::string& Figure2D::name() const return _name; } -size_t Figure2D::size() const +Index Figure2D::size() const { return _axes.size(); } @@ -52,6 +55,16 @@ void Figure2D::set_axes(const FigureAxis& axis1, const FigureAxis& axis2) output_fig->update_axes(); } +const Index& Figure2D::i() const +{ + return axes()[0].dim_id; +} + +const Index& Figure2D::j() const +{ + return axes()[1].dim_id; +} + const Vector& Figure2D::pos() const { return _pos; @@ -146,7 +159,7 @@ void Figure2D::draw_polyline(const vector& x, float tip_length, const St { assert_release(x.size() > 1); assert_release(tip_length >= 0.); // 0 = disabled tip - for(const auto& xi : x) + for([[maybe_unused]] const auto& xi : x) { assert_release(this->size() <= xi.size()); } @@ -158,7 +171,7 @@ void Figure2D::draw_polyline(const vector& x, float tip_length, const St void Figure2D::draw_polygone(const vector& x, const StyleProperties& s) { assert_release(x.size() > 1); - for(const auto& xi : x) + for([[maybe_unused]] const auto& xi : x) { assert_release(this->size() <= xi.size()); } @@ -197,51 +210,32 @@ void Figure2D::draw_ellipse(const Vector& c, const Vector& ab, double theta, con } void Figure2D::draw_ellipsoid(const Ellipsoid &e, const StyleProperties &s) { + // Author: Morgan Louédec assert_release(this->size() <= e.size()); - for (const auto &output_fig: _output_figures) { - Matrix G_draw(2, 2); - Vector mu_draw(2); + + Index n = e.size(); + Ellipsoid proj_e(2); + // 2d projection of the ellipsoid - if (e.size() > 2) { - Ellipsoid ep(e); - Vector v = Eigen::VectorXd::Zero(e.size()); - v[output_fig->i()] = 1; - Vector u = Eigen::VectorXd::Zero(e.size()); - u[output_fig->j()] = 1; - ep.projection2D(Eigen::VectorXd::Zero(e.size()),v,u); - G_draw = ep.G; - mu_draw = ep.mu; - -// // affine space of the projection -// Vector d(Eigen::VectorXd::Zero(e.mu.nb_rows())); -// Matrix T(Eigen::MatrixXd::Zero(e.G.nb_rows(), 2)); -// T(output_fig->i(), 0) = 1; -// T(output_fig->j(), 1) = 1; -// -// // project ellipsoid E(mu,Q) = {x in R^n | (x-mu).T*G.{-T}*G^{-1}*(x-mu)<1} -// // on the affine plan A = {x|x=d+Tt} [Pope -2008] -// // reduce the dimensions of mu and Q -// -// auto TTG = T._e.transpose() * e.G._e; -// Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); -// Matrix U(bdcsvd.matrixU()); -// Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); -// G_draw = U._e * E._e; -// mu_draw = T._e.transpose() * (d._e + T._e * T._e.transpose() * (e.mu._e - d._e)); + if (n > 2) { + Vector v = Vector::zero(n); + v[i()] = 1; + Vector u = Vector::zero(n); + u[j()] = 1; + proj_e = e.proj_2d(Vector::zero(n), v, u); } else { - G_draw = e.G; - mu_draw = e.mu; + proj_e = e; } // draw the 2d ellipsoid - Eigen::JacobiSVD jsvd(G_draw._e, Eigen::ComputeThinU); + Eigen::JacobiSVD jsvd(proj_e.G, Eigen::ComputeThinU); Matrix U(jsvd.matrixU()); Vector ab(jsvd.singularValues()); - double theta = atan2(U(1, 0), U(0, 0)).mid(); + double theta = std::atan2(U(1, 0), U(0, 0)); - output_fig->draw_ellipse(mu_draw, ab, theta, s); - } + for(const auto& output_fig : _output_figures) + output_fig->draw_ellipse(proj_e.mu, ab, theta, s); } void Figure2D::draw_tank(const Vector& x, float size, const StyleProperties& s) diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 901805f4..81e58764 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -12,6 +12,7 @@ #include #include #include +#include "codac2_Index.h" #include "codac2_Figure2DInterface.h" #include "codac2_OutputFigure2D.h" #include "codac2_Paving.h" @@ -34,12 +35,12 @@ namespace codac2 struct FigureAxis { - size_t dim_id; + Index dim_id; Interval limits; std::string label; }; - inline FigureAxis axis(size_t dim_id, const Interval& limits, const std::string& label = "") + inline FigureAxis axis(Index dim_id, const Interval& limits, const std::string& label = "") { assert_release(dim_id >= 0); //assert_release(!limits.is_empty()); @@ -64,11 +65,14 @@ namespace codac2 Figure2D(const std::string& name, GraphicOutput o, bool set_as_default = false); const std::string& name() const; - size_t size() const; + Index size() const; const std::vector& axes() const; void set_axes(const FigureAxis& axis1, const FigureAxis& axis2); + const Index& i() const; + const Index& j() const; + const Vector& pos() const; const Vector& window_size() const; void set_window_properties(const Vector& pos, const Vector& size); diff --git a/src/graphics/figures/codac2_OutputFigure2D.cpp b/src/graphics/figures/codac2_OutputFigure2D.cpp index bfd81aaa..32afc150 100644 --- a/src/graphics/figures/codac2_OutputFigure2D.cpp +++ b/src/graphics/figures/codac2_OutputFigure2D.cpp @@ -14,12 +14,12 @@ using namespace std; using namespace codac2; -const size_t& OutputFigure2D::i() const +const Index& OutputFigure2D::i() const { - return _fig.axes()[0].dim_id; + return _fig.i(); } -const size_t& OutputFigure2D::j() const +const Index& OutputFigure2D::j() const { - return _fig.axes()[1].dim_id; + return _fig.j(); } \ No newline at end of file diff --git a/src/graphics/figures/codac2_OutputFigure2D.h b/src/graphics/figures/codac2_OutputFigure2D.h index 1059029d..d222c927 100644 --- a/src/graphics/figures/codac2_OutputFigure2D.h +++ b/src/graphics/figures/codac2_OutputFigure2D.h @@ -27,8 +27,8 @@ namespace codac2 : _fig(fig) { } - const size_t& i() const; - const size_t& j() const; + const Index& i() const; + const Index& j() const; virtual void update_axes() = 0; virtual void update_window_properties() = 0; diff --git a/src/graphics/paver/codac2_drawwhilepaving.cpp b/src/graphics/paver/codac2_drawwhilepaving.cpp index c147b5a0..8aa87323 100644 --- a/src/graphics/paver/codac2_drawwhilepaving.cpp +++ b/src/graphics/paver/codac2_drawwhilepaving.cpp @@ -54,7 +54,7 @@ namespace codac2 fig->draw_box(x0, StyleProperties::outside()); list l { x0 }; - size_t n = 0; + Index n = 0; while(!l.empty()) { @@ -83,7 +83,7 @@ namespace codac2 } } - printf("Computation time: %.4fs, %zd boxes\n", (double)(clock()-t_start)/CLOCKS_PER_SEC, n); + printf("Computation time: %.4fs, %ld boxes\n", (double)(clock()-t_start)/CLOCKS_PER_SEC, n); } void draw_while_paving(const IntervalVector& x0, std::shared_ptr s, double eps, std::shared_ptr fig) @@ -103,7 +103,7 @@ namespace codac2 clock_t t_start = clock(); list l { x0 }; - size_t n_inner = 0, n_boundary = 0; + Index n_inner = 0, n_boundary = 0; while(!l.empty()) { @@ -138,7 +138,7 @@ namespace codac2 } } - printf("Computation time: %.4fs, %zd inner boxes, %zd boundary boxes\n", + printf("Computation time: %.4fs, %ld inner boxes, %ld boundary boxes\n", (double)(clock()-t_start)/CLOCKS_PER_SEC, n_inner, n_boundary); } } \ No newline at end of file diff --git a/src/graphics/styles/codac2_Color.cpp b/src/graphics/styles/codac2_Color.cpp index 99350065..55b5860d 100644 --- a/src/graphics/styles/codac2_Color.cpp +++ b/src/graphics/styles/codac2_Color.cpp @@ -2,7 +2,7 @@ * codac2_Color.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Maël Godard * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -12,23 +12,146 @@ using namespace std; using namespace codac2; -Color::Color(float r_, float g_, float b_, float alpha_) - : r(r_), g(g_), b(b_), alpha(alpha_), - hex_str([&] +Color::Color() + : Color({0.,0.,0.,0.}) +{ } + +Color::Color(const std::array& xyz, Model m_) + : Color({xyz[0],xyz[1],xyz[2],(m_ == Model::RGB ? (float) 255. : (float) 100.)}, m_) +{ } + +Color::Color(const std::array& xyza, Model m_) + : std::array(xyza), m(m_) +{ + if (m_==Model::RGB) + assert(xyza[0] >= 0. && xyza[0] <= 255. && xyza[1]>=0. && xyza[1] <= 255. && xyza[2]>=0. && xyza[2] <= 255. && xyza[3]>=0. && xyza[3] <= 255.); + else if (m_==Model::HSV) + assert(xyza[0] >= 0. && xyza[0] <= 360. && xyza[1]>=0. && xyza[1] <= 100. && xyza[2]>=0. && xyza[2] <= 100. && xyza[3]>=0. && xyza[3] <= 100.); +} + +Color::Color(const std::initializer_list xyza, Model m_) + : Color(xyza.size() == 3 ? Color(to_array<3>(xyza), m_) : Color(to_array<4>(xyza), m_)) +{ } + +Color::Color(const std::string& hex_str) : m(Model::RGB) +{ + assert(hex_str.size() == 7 || hex_str.size() == 9); + assert(hex_str[0] == '#'); + + int red,green,blue,a; + std::istringstream(hex_str.substr(1,2)) >> std::hex >> red; + std::istringstream(hex_str.substr(3,2)) >> std::hex >> green; + std::istringstream(hex_str.substr(5,2)) >> std::hex >> blue; + (*this)[0] = (float) (red); + (*this)[1] = (float) (green); + (*this)[2] = (float) (blue); + + // Alpha (transparency) component may be appended to the #hexa notation. + // Value is '255.' (max opacity) by default. + if(hex_str.size() == 9) + { + std::istringstream(hex_str.substr(7,2)) >> std::hex >> a; + (*this)[3] = (float) (a); + } + else + (*this)[3] = 255.; +} + +Color Color::rgb() const +{ + if (m==Model::RGB) + return *this; + else { - std::stringstream s; - s << std::hex << std::setfill('0'); - s << std::setw(2) << (int)(r*255) << std::setw(2) << (int)(g*255) << std::setw(2) << (int)(b*255); - if(alpha != 1.) - s << std::setw(2) << (int)(alpha*255); - return "#"+s.str(); - }()) -{ - assert(r_ >= 0. && r_ <= 1. && g_ >= 0. && g_ <= 1. && b_ >= 0. && b_ <= 1. && alpha_ >= 0. && alpha_ <= 1.); + float r = 0., g = 0., b = 0.; + + // Normalisation des valeurs + float h = (*this)[0] / 360.; // Hue normalisée (0 à 1) + float s = (*this)[1] / 100.; // Saturation normalisée (0 à 1) + float v = (*this)[2] / 100.; // Value normalisée (0 à 1) + + int i = static_cast(h * 6); + float f = (h * 6) - i; + i = i % 6; + + float p = v * (1 - s); + float q = v * (1 - f * s); + float t = v * (1 - (1 - f) * s); + + switch (i) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } + + // Conversion vers l'échelle [0, 255] + r *= 255.; + g *= 255.; + b *= 255.; + + return Color({r, g, b,std::min(255.,((*this)[3]*2.55))},Model::RGB); + } +} + +Color Color::hsv() const +{ + if (m==Model::HSV) + return *this; + else + { + float r = (*this)[0]/255.; + float g = (*this)[1]/255.; + float b = (*this)[2]/255.; + float c_max = std::max({r, g, b}); + float c_min = std::min({r, g, b}); + float delta = c_max - c_min; + + float h = 0.0; + if (delta != 0) { + if (c_max == r) { + h = fmod((g - b) / delta, 6.0); + } else if (c_max == g) { + h = (b - r) / delta + 2.0; + } else if (c_max == b) { + h = (r - g) / delta + 4.0; + } + h /= 6.0; + if (h < 0) { + h += 1.0; + } + } + + float s = (c_max == 0) ? 0 : (delta / c_max); + + float v = c_max; + + h*=360.; + s*=100.; + v*=100.; + + return Color({h, s, v,std::min(100.,((*this)[3]/2.55))},Model::HSV); + } +} + +std::string Color::hex_str() const +{ + if (m == Model::RGB) + { + std::stringstream s; + s << std::hex << std::setfill('0'); + s << std::setw(2) << (int)((*this)[0]) << std::setw(2) << (int)((*this)[1]) << std::setw(2) << (int)((*this)[2]); + if((*this)[3] != 1.) + s << std::setw(2) << (int)((*this)[3]); + return "#"+s.str(); + } + else + return rgb().hex_str(); } -Color::Color(int r_, int g_, int b_, int alpha_) - : Color((float)(r_/255.), (float)(g_/255.), (float)(b_/255.), (float)(alpha_/255.)) +codac2::Vector Color::vec() const { - assert(r_ >= 0 && r_ <= 255 && g_ >= 0 && g_ <= 255 && b_ >= 0 && b_ <= 255 && alpha_ >= 0 && alpha_ <= 255); + return codac2::Vector({(*this)[0], (*this)[1], (*this)[2], (*this)[3]}); } \ No newline at end of file diff --git a/src/graphics/styles/codac2_Color.h b/src/graphics/styles/codac2_Color.h index 03c52692..a7ae40c6 100644 --- a/src/graphics/styles/codac2_Color.h +++ b/src/graphics/styles/codac2_Color.h @@ -2,7 +2,7 @@ * \file codac2_Color.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Maël Godard * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -11,35 +11,76 @@ #include #include +#include + #include"codac2_assert.h" +#include"codac2_Vector.h" namespace codac2 { - /** - * \struct Color - * \brief Represents an RGB value - */ - struct Color + + enum Model { RGB, HSV }; + + struct Color : public std::array { - float r; ///< red, value between 0. and 1. - float g; ///< green, value between 0. and 1. - float b; ///< blue, value between 0. and 1. - float alpha = 1.; ///< opacity, value between 0. (transparent) and 1. (opaque) - std::string hex_str; ///< represents an RGB value in a HTML standard - - explicit Color(float r_, float g_, float b_, float alpha_ = 1.); - explicit Color(int r_, int g_, int b_, int alpha_ = 255); - - static Color none() { return Color(255, 255, 255, 0 ); }; - static Color black(float alpha = 1) { return Color(0, 0, 0, (int)(alpha*255)); }; - static Color white(float alpha = 1) { return Color(255, 255, 255, (int)(alpha*255)); }; - static Color green(float alpha = 1) { return Color(144, 242, 0, (int)(alpha*255)); }; - static Color blue(float alpha = 1) { return Color(0, 98, 198, (int)(alpha*255)); }; - static Color cyan(float alpha = 1) { return Color(75, 207, 250, (int)(alpha*255)); }; - static Color yellow(float alpha = 1) { return Color(255, 211, 42, (int)(alpha*255)); }; - static Color red(float alpha = 1) { return Color(209, 59, 0, (int)(alpha*255)); }; - static Color dark_gray(float alpha = 1) { return Color(112, 112, 112, (int)(alpha*255)); }; - static Color purple(float alpha = 1) { return Color(154, 0, 170, (int)(alpha*255)); }; - static Color dark_green(float alpha = 1) { return Color(94, 158, 0, (int)(alpha*255)); }; + protected: + Model m; + + public: + + // Constructors + + explicit Color(); + explicit Color(const std::array& xyz, Model m_ = Model::RGB); + explicit Color(const std::array& xyza, Model m_ = Model::RGB); + explicit Color(const std::initializer_list xyza, Model m_ = Model::RGB); + explicit Color(const std::string& hex_str); + + const Model& model() const { return m; } + + + // other formats + + std::string hex_str() const; + + codac2::Vector vec() const; + + // Conversions + + Color rgb() const; + Color hsv() const; + + // Overload flux operator + + friend std::ostream& operator<<(std::ostream& os, const Color& c) + { + if (c.m == Model::RGB) + os << "RGB Color (" << c[0] << "," << c[1] << "," << c[2] << "," << c[3] << ")"; + else if (c.m == Model::HSV) + os << "HSV Color (" << c[0] << "," << c[1] << "," << c[2] << "," << c[3] << ")"; + return os; + } + + // Predefined colors + + static Color none() { return Color({255., 255., 255., 0.}); }; + static Color black(float alpha = 1.) { return Color({0., 0., 0., (float) (alpha*255.)}); }; + static Color white(float alpha = 1.) { return Color({255., 255., 255., (float) (alpha*255.)}); }; + static Color green(float alpha = 1.) { return Color({144., 242., 0., (float) (alpha*255.)}); }; + static Color blue(float alpha = 1.) { return Color({0., 98., 198., (float) (alpha*255.)}); }; + static Color cyan(float alpha = 1.) { return Color({75., 207., 250., (float) (alpha*255.)}); }; + static Color yellow(float alpha = 1.) { return Color({255., 211., 42., (float) (alpha*255.)}); }; + static Color red(float alpha = 1.) { return Color({209., 59., 0., (float) (alpha*255.)}); }; + static Color dark_gray(float alpha = 1.) { return Color({112., 112., 112., (float) (alpha*255.)}); }; + static Color purple(float alpha = 1.) { return Color({154., 0., 170., (float) (alpha*255.)}); }; + static Color dark_green(float alpha = 1.) { return Color({94., 158., 0., (float) (alpha*255.)}); }; }; + + template + static std::array to_array(const std::initializer_list& list) { + assert(list.size() == N); + std::array arr; + std::copy(list.begin(), list.end(), arr.begin()); + return arr; + } } \ No newline at end of file diff --git a/src/graphics/styles/codac2_ColorMap.cpp b/src/graphics/styles/codac2_ColorMap.cpp new file mode 100644 index 00000000..728264b9 --- /dev/null +++ b/src/graphics/styles/codac2_ColorMap.cpp @@ -0,0 +1,62 @@ +/** + * codac2_ColorMap.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_ColorMap.h" + +using namespace std; +using namespace codac2; + +ColorMap::ColorMap(Model m_) : + m(m_) +{ } + +Color ColorMap::color(float r) const +{ + assert (this->size() >= 2); + if(std::isnan(r)) // undefined ratio + return Color({0.5, 0.5, 0.5}); + assert(Interval(0.,1.).contains(r)); + + Interval map_domain = Interval(this->begin()->first,prev(this->end())->first); + float real_index = map_domain.lb() + r*map_domain.diam(); + + if(this->find(real_index) == this->end()) // color interpolation + { + typename map::const_iterator it_ub; + it_ub = this->lower_bound(real_index); + Color color_lb = prev(it_ub)->second; + Color color_ub = it_ub->second; + + // Interpolation according to the ColorMap model + + if (m == Model::RGB) + { + color_lb = color_lb.rgb(); + color_ub = color_ub.rgb(); + } + + else if (m == Model::HSV) + { + color_lb = color_lb.hsv(); + color_ub = color_ub.hsv(); + } + + + float local_ratio = (real_index - prev(it_ub)->first) / (it_ub->first - prev(it_ub)->first); + + return Color({(color_lb[0] + (color_ub[0] - color_lb[0]) * local_ratio), + (color_lb[1] + (color_ub[1] - color_lb[1]) * local_ratio), + (color_lb[2] + (color_ub[2] - color_lb[2]) * local_ratio), + (color_lb[3] + (color_ub[3] - color_lb[3]) * local_ratio)},color_lb.model()); + + } + + else // color key + return this->at(real_index); +} \ No newline at end of file diff --git a/src/graphics/styles/codac2_ColorMap.h b/src/graphics/styles/codac2_ColorMap.h new file mode 100644 index 00000000..c8d9e09a --- /dev/null +++ b/src/graphics/styles/codac2_ColorMap.h @@ -0,0 +1,126 @@ +/** + * \file codac2_ColorMap.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include +#include "codac2_Color.h" +#include "codac2_Interval.h" +#include"codac2_assert.h" + +namespace codac2 +{ + /** + * \struct ColorMap + * \brief Represents a set of RGB values + */ + struct ColorMap : public std::map + { + protected: + Model m; //RGB or HSV + + public: + + explicit ColorMap(Model m_ = Model::RGB); + + const Model& model() const { return m; } + + Color color (float r) const; + + static ColorMap haxby() + { + ColorMap cmap( Model::RGB ); + cmap[0]=Color({39.,90.,211.}); + cmap[1]=Color({40.,123.,245.}); + cmap[2]=Color({45.,155.,253.}); + cmap[3]=Color({73.,209.,255.}); + cmap[4]=Color({100.,230.,254.}); + cmap[5]=Color({118.,235.,226.}); + cmap[6]=Color({135.,236.,187.}); + cmap[7]=Color({194.,252.,165.}); + cmap[8]=Color({217.,251.,151.}); + cmap[9]=Color({233.,241.,131.}); + cmap[10]=Color({252.,201.,96.}); + cmap[11]=Color({255.,184.,84.}); + cmap[12]=Color({255.,170.,75.}); + cmap[13]=Color({255.,167.,83.}); + cmap[14]=Color({255.,200.,158.}); + cmap[15]=Color({255.,233.,217.}); + return cmap; + } + + static ColorMap basic() // Can't use default as name + { + ColorMap cmap( Model::RGB ); + cmap[0]=Color({10.,0.,121.}); + cmap[1]=Color({40.,0.,150.}); + cmap[2]=Color({20.,5.,175.}); + cmap[3]=Color({0.,10.,200.}); + cmap[4]=Color({0.,25.,212.}); + cmap[5]=Color({0.,40.,224.}); + cmap[6]=Color({26.,102.,240.}); + cmap[7]=Color({13.,129.,248.}); + cmap[8]=Color({25.,175.,255.}); + cmap[9]=Color({50.,190.,255.}); + cmap[10]=Color({68.,202.,255.}); + cmap[11]=Color({97.,225.,240.}); + cmap[12]=Color({106.,235.,225.}); + cmap[13]=Color({124.,235.,200.}); + cmap[14]=Color({138.,236.,174.}); + cmap[15]=Color({172.,245.,168.}); + cmap[16]=Color({205.,255.,162.}); + cmap[17]=Color({223.,245.,141.}); + cmap[18]=Color({240.,236.,121.}); + cmap[19]=Color({247.,215.,104.}); + cmap[20]=Color({255.,189.,87.}); + cmap[21]=Color({255.,160.,69.}); + cmap[22]=Color({244.,117.,75.}); + cmap[23]=Color({238.,80.,78.}); + cmap[24]=Color({255.,90.,90.}); + cmap[25]=Color({255.,124.,124.}); + cmap[26]=Color({255.,158.,158.}); + cmap[27]=Color({245.,179.,174.}); + cmap[28]=Color({255.,196.,196.}); + cmap[29]=Color({255.,215.,215.}); + cmap[30]=Color({255.,235.,235.}); + cmap[31]=Color({255.,254.,253.}); + return cmap; + } + + static ColorMap blue_tube() + { + ColorMap cmap( Model::RGB ); + cmap[0]=Color({76.,110.,127.}); + cmap[1]=Color({136.,197.,228.}); + return cmap; + } + + static ColorMap red_tube() + { + ColorMap cmap( Model::RGB ); + cmap[0]=Color({169.,55.,0.}); + cmap[1]=Color({241.,140.,54.}); + return cmap; + } + + static ColorMap rainbow() + { + ColorMap cmap( Model::HSV ); + int i = 0; + for(int h = 300 ; h > 0 ; h-=10) + { + cmap[i]=Color({(float)h,100.,100.},Model::HSV); + i++; + } + return cmap; + } + + }; +} \ No newline at end of file diff --git a/src/graphics/styles/codac2_StyleProperties.cpp b/src/graphics/styles/codac2_StyleProperties.cpp index 869b6e0b..d6b42b8b 100644 --- a/src/graphics/styles/codac2_StyleProperties.cpp +++ b/src/graphics/styles/codac2_StyleProperties.cpp @@ -20,15 +20,15 @@ StyleProperties::StyleProperties(const Color& stroke_color_) { } StyleProperties::StyleProperties(std::initializer_list colors) - : stroke_color(*colors.begin()), fill_color(*std::prev(colors.end())) + : stroke_color(*colors.begin()) { assert(colors.size() <= 2); + if (colors.size() == 1) + fill_color = Color::none(); + else + fill_color = *std::prev(colors.end()); } -StyleProperties::StyleProperties(const string& vibes_style) - : stroke_color(Color::green()), fill_color(Color::none()) -{ } - StyleProperties StyleProperties::inside() { StyleProperties s; diff --git a/src/graphics/styles/codac2_StyleProperties.h b/src/graphics/styles/codac2_StyleProperties.h index 4b6455dd..218b7c30 100644 --- a/src/graphics/styles/codac2_StyleProperties.h +++ b/src/graphics/styles/codac2_StyleProperties.h @@ -22,7 +22,6 @@ namespace codac2 StyleProperties(); StyleProperties(const Color& stroke_color); StyleProperties(std::initializer_list colors); - StyleProperties(const std::string& vibes_style); static StyleProperties inside(); static StyleProperties outside(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4bd8f43d..500ea627 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,16 +4,28 @@ # Finding Catch2 - message(STATUS "Getting Catch2 library... (an Internet connection is required)") + #message(STATUS "Getting Catch2 library... (an Internet connection might be required)") Include(FetchContent) - FetchContent_Declare( + + #find_package(Catch2 3.6.0 EXACT QUIET) + find_package(Catch2 3.6.0 QUIET) + if(Catch2_FOUND) + message(STATUS "Found Catch2 version ${Catch2_VERSION} in ${Catch2_DIR}") + else() + message(STATUS "Attempt to install Catch2 automatically...") + FetchContent_Declare( Catch2 - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v3.6.0 + #GIT_REPOSITORY https://github.com/catchorg/Catch2.git + #GIT_TAG v3.6.0 + #URL https://github.com/catchorg/Catch2/archive/refs/tags/v3.6.0.zip + URL ${CMAKE_SOURCE_DIR}/3rd/Catch2-3.6.0.zip + #SOURCE_DIR "P:/devel/GitHub/Catch2" + #FIND_PACKAGE_ARGS ) - FetchContent_MakeAvailable(Catch2) + # Adds Catch2::Catch2WithMain + endif() list(APPEND SRC_TESTS # listing files without extension @@ -28,10 +40,12 @@ list(APPEND SRC_TESTS # listing files without extension core/contractors/codac2_tests_CtcAction core/contractors/codac2_tests_CtcCartProd + core/contractors/codac2_tests_CtcCtcBoundary core/contractors/codac2_tests_CtcFixpoint core/contractors/codac2_tests_CtcInverse core/contractors/codac2_tests_CtcInverseNotIn core/contractors/codac2_tests_CtcLazy + core/contractors/codac2_tests_CtcPolygon core/contractors/codac2_tests_CtcSegment core/contractors/codac2_tests_linear_ctc @@ -54,6 +68,7 @@ list(APPEND SRC_TESTS # listing files without extension core/matrices/codac2_tests_arithmetic_sub core/matrices/codac2_tests_Matrix core/matrices/codac2_tests_Vector + core/matrices/codac2_tests_Inversion core/separators/codac2_tests_SepCartProd core/separators/codac2_tests_SepCtcBoundary @@ -63,6 +78,9 @@ list(APPEND SRC_TESTS # listing files without extension core/separators/codac2_tests_SepTransform core/tools/codac2_tests_Approx + + graphics/styles/codac2_tests_Color + ) @@ -84,4 +102,4 @@ foreach(SRC_TEST ${SRC_TESTS}) add_test(NAME ${TEST_NAME}_py COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_TEST}.py) endif() -endforeach() \ No newline at end of file +endforeach() diff --git a/tests/core/3rd/codac2_tests_ibex.cpp b/tests/core/3rd/codac2_tests_ibex.cpp index c2f86962..a75725a5 100644 --- a/tests/core/3rd/codac2_tests_ibex.cpp +++ b/tests/core/3rd/codac2_tests_ibex.cpp @@ -38,13 +38,13 @@ TEST_CASE("IBEX") // [Vector] Codac -> IBEX { - CHECK(codac2::to_ibex(codac2::Vector(2)) == ibex::Vector(2)); + CHECK(codac2::to_ibex(codac2::Vector::zero(2)) == ibex::Vector(2)); CHECK(codac2::to_ibex(codac2::Vector({1,2,3})) == ibex::Vector({1,2,3})); } // [Vector] IBEX -> Codac { - CHECK(codac2::to_codac(ibex::Vector(2)) == codac2::Vector(2)); + CHECK(codac2::to_codac(ibex::Vector::zeros(2)) == codac2::Vector::zero(2)); CHECK(codac2::to_codac(ibex::Vector({1,2,3})) == codac2::Vector({1,2,3})); } @@ -64,14 +64,14 @@ TEST_CASE("IBEX") // [Matrix] Codac -> IBEX { - CHECK(codac2::to_ibex(codac2::Matrix(2,3)) == ibex::Matrix(2,3)); + CHECK(codac2::to_ibex(codac2::Matrix::zero(2,3)) == ibex::Matrix(2,3)); CHECK(codac2::to_ibex(codac2::Matrix({{1,2,3},{4,5,6}})) == ibex::Matrix({{1,2,3},{4,5,6}})); } // [Matrix] IBEX -> Codac { - CHECK(codac2::to_codac(ibex::Matrix(2,3)) == codac2::Matrix(2,3)); + CHECK(codac2::to_codac(ibex::Matrix(2,3)) == codac2::Matrix::zero(2,3)); CHECK(codac2::to_codac(ibex::Matrix({{1,2,3},{4,5,6}})) == codac2::Matrix({{1,2,3},{4,5,6}})); } diff --git a/tests/core/contractors/codac2_tests_CtcAction.cpp b/tests/core/contractors/codac2_tests_CtcAction.cpp index fb74f9c5..cc62b968 100644 --- a/tests/core/contractors/codac2_tests_CtcAction.cpp +++ b/tests/core/contractors/codac2_tests_CtcAction.cpp @@ -18,7 +18,7 @@ TEST_CASE("CtcAction") { { VectorVar x(2); - CtcInverse_ c1(AnalyticFunction({x}, x-IntervalVector({{1,5},{8,6}})), IntervalVector({{0},{0}})); + CtcInverse_ c1(AnalyticFunction({x}, x-IntervalVector({{1,5},{8,6}})), IntervalVector({0.,0.})); IntervalVector b(2); c1.contract(b); diff --git a/tests/core/contractors/codac2_tests_CtcCtcBoundary.cpp b/tests/core/contractors/codac2_tests_CtcCtcBoundary.cpp new file mode 100644 index 00000000..4dd9107c --- /dev/null +++ b/tests/core/contractors/codac2_tests_CtcCtcBoundary.cpp @@ -0,0 +1,59 @@ +/** + * Codac tests + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace codac2; + +BoolInterval test_inside_diamond(const Vector& x) +{ + if((x[1] < x[0]+1) && (x[1] > x[0]-1) && (x[1] < -x[0]+1) && (x[1] > -x[0]-1)) + return BoolInterval::TRUE; + else if(!(x[1] < x[0]+1) || !(x[1] > x[0]-1) || !(x[1] < -x[0]+1) || !(x[1] > -x[0]-1)) + return BoolInterval::FALSE; + else + return BoolInterval::UNKNOWN; +} + +TEST_CASE("CtcCtcBoundary") +{ + auto ctc_bound_diamond = CtcSegment({-1,0}, {0,-1}) | CtcSegment({0,-1}, {1,0}) + | CtcSegment({1,0}, {0,1}) | CtcSegment({0,1}, {-1,0}); + + CtcCtcBoundary ctc_diamond(ctc_bound_diamond,test_inside_diamond); + + //draw_while_paving(IntervalVector({{-2,2},{-2,2}}), ctc_diamond, 0.1); + + IntervalVector x(2); + ctc_diamond.contract(x); + //DefaultView::draw_box(x,Color::dark_green()); + CHECK(x == IntervalVector({{-1,1},{-1,1}})); + + x = IntervalVector({{0,10},{0,10}}); + ctc_diamond.contract(x); + //DefaultView::draw_box(x,Color::blue()); + CHECK(x == IntervalVector({{0,1},{0,1}})); + + x = IntervalVector({{0.2,10},{0.2,10}}); + ctc_diamond.contract(x); + //DefaultView::draw_box(x,Color::blue()); + CHECK(x == IntervalVector({{0.2,0.8},{0.2,0.8}})); + + x = IntervalVector({{0.5,10},{0.5,10}}); + ctc_diamond.contract(x); + //DefaultView::draw_box(x,Color::blue()); + CHECK(x == IntervalVector({0.5,0.5})); +} \ No newline at end of file diff --git a/tests/core/contractors/codac2_tests_CtcCtcBoundary.py b/tests/core/contractors/codac2_tests_CtcCtcBoundary.py new file mode 100644 index 00000000..680ac875 --- /dev/null +++ b/tests/core/contractors/codac2_tests_CtcCtcBoundary.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Codac tests +# ---------------------------------------------------------------------------- +# \date 2024 +# \author Simon Rohou +# \copyright Copyright 2024 Codac Team +# \license GNU Lesser General Public License (LGPL) + +import unittest +from codac import * + +def test_inside_diamond(x): + if (x[1] < x[0]+1) and (x[1] > x[0]-1) and (x[1] < -x[0]+1) and (x[1] > -x[0]-1): + return BoolInterval.TRUE + elif not(x[1] < x[0]+1) or not(x[1] > x[0]-1) or not(x[1] < -x[0]+1) or not(x[1] > -x[0]-1): + return BoolInterval.FALSE + else: + return BoolInterval.UNKNOWN + +class TestCtcCtcBoundary(unittest.TestCase): + + def tests_CtcCtcBoundary(self): + + ctc_bound_diamond = CtcSegment([[-1],[0]], [[0],[-1]]) | CtcSegment([[0],[-1]], [[1],[0]]) \ + | CtcSegment([[1],[0]], [[0],[1]]) | CtcSegment([[0],[1]], [[-1],[0]]) + + ctc_diamond = CtcCtcBoundary(ctc_bound_diamond,test_inside_diamond) + #draw_while_paving(IntervalVector([[-2,2],[-2,2]]), ctc_diamond, 0.1) + + x = IntervalVector(2) + ctc_diamond.contract(x) + #self.assertTrue(x == IntervalVector([[-1,1],[-1,1]])) + + x = IntervalVector([[0,10],[0,10]]) + ctc_diamond.contract(x) + #self.assertTrue(x == IntervalVector([[0,1],[0,1]])) + + x = IntervalVector([[0.2,10],[0.2,10]]) + ctc_diamond.contract(x) + #self.assertTrue(x == IntervalVector([[0.2,0.8],[0.2,0.8]])) + + x = IntervalVector([[0.5,10],[0.5,10]]) + ctc_diamond.contract(x) + #self.assertTrue(x == IntervalVector([[0.5],[0.5]])) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/core/contractors/codac2_tests_CtcFixpoint.cpp b/tests/core/contractors/codac2_tests_CtcFixpoint.cpp index d44fa825..697a4247 100644 --- a/tests/core/contractors/codac2_tests_CtcFixpoint.cpp +++ b/tests/core/contractors/codac2_tests_CtcFixpoint.cpp @@ -10,7 +10,6 @@ #include #include #include -#include using namespace std; using namespace codac2; diff --git a/tests/core/contractors/codac2_tests_CtcInverse.cpp b/tests/core/contractors/codac2_tests_CtcInverse.cpp index 9aa85c12..666c0084 100644 --- a/tests/core/contractors/codac2_tests_CtcInverse.cpp +++ b/tests/core/contractors/codac2_tests_CtcInverse.cpp @@ -81,9 +81,9 @@ TEST_CASE("CtcInverse") c.contract(b); CHECK(b == IntervalVector({{1,oo},{1,oo}})); - b = IntervalVector({{10},{10}}); + b = IntervalVector({10,10}); c.contract(b); - CHECK(b == IntervalVector({{10},{10}})); + CHECK(b == IntervalVector({10,10})); b = IntervalVector({{1,5},{8,9}}); c.contract(b); @@ -93,7 +93,7 @@ TEST_CASE("CtcInverse") { VectorVar x(2); AnalyticFunction f { {x}, vec(x[0]-x[1]) }; - CtcInverse_ c(f, {{0}}); + CtcInverse_ c(f, {0}); //pave(IntervalVector({{-10,10},{-10,10}}), c, 0.1); @@ -110,9 +110,9 @@ TEST_CASE("CtcInverse") c.contract(b); CHECK(b == IntervalVector({{1,oo},{1,oo}})); - b = IntervalVector({{10},{10}}); + b = IntervalVector({10,10}); c.contract(b); - CHECK(b == IntervalVector({{10},{10}})); + CHECK(b == IntervalVector({10,10})); b = IntervalVector({{1,5},{8,9}}); c.contract(b); diff --git a/tests/core/contractors/codac2_tests_CtcInverseNotIn.cpp b/tests/core/contractors/codac2_tests_CtcInverseNotIn.cpp index 65883a36..d66035a2 100644 --- a/tests/core/contractors/codac2_tests_CtcInverseNotIn.cpp +++ b/tests/core/contractors/codac2_tests_CtcInverseNotIn.cpp @@ -28,7 +28,7 @@ TEST_CASE("CtcInverseNotIn") VectorVar x(2); AnalyticFunction f { {x}, vec(x[0]-x[1]) }; - CtcInverseNotIn c(f, {{0}}); + CtcInverseNotIn c(f, {0}); //pave(IntervalVector({{-10,10},{-10,10}}), c, 0.1); @@ -45,9 +45,9 @@ TEST_CASE("CtcInverseNotIn") c.contract(b); CHECK(b == IntervalVector({{1,oo},{1,oo}})); - b = IntervalVector({{10},{10}}); + b = IntervalVector({10,10}); c.contract(b); - CHECK(b == IntervalVector({{10},{10}})); + CHECK(b == IntervalVector({10,10})); b = IntervalVector({{1,5},{8,9}}); c.contract(b); diff --git a/tests/core/contractors/codac2_tests_CtcLazy.cpp b/tests/core/contractors/codac2_tests_CtcLazy.cpp index 7c3be9b5..9fb06ad7 100644 --- a/tests/core/contractors/codac2_tests_CtcLazy.cpp +++ b/tests/core/contractors/codac2_tests_CtcLazy.cpp @@ -10,7 +10,6 @@ #include #include #include -#include using namespace std; using namespace codac2; diff --git a/tests/core/contractors/codac2_tests_CtcPolygon.cpp b/tests/core/contractors/codac2_tests_CtcPolygon.cpp new file mode 100644 index 00000000..49a16e95 --- /dev/null +++ b/tests/core/contractors/codac2_tests_CtcPolygon.cpp @@ -0,0 +1,93 @@ +/** + * Codac tests + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include + +using namespace std; +using namespace codac2; + +TEST_CASE("CtcPolygon") +{ + CtcPolygon c({{3,-1},{3,4},{5,6},{-1,1}}); + + IntervalVector x(2); + c.contract(x); + CHECK(x == IntervalVector({{-1,5},{-1,6}})); + + x = IntervalVector({{3.02,3.16},{2.5,3.2}}); // possible bug + c.contract(x); + CHECK(x.is_empty()); +} + +TEST_CASE("CtcPolygon - tests from Codac1") +{ + // Polygone with hole + { + CtcPolygon c({ + // external border + Edge({{6,-6},{7,9}}), + Edge({{7,9},{0,5}}), + Edge({{0,5},{-9,8}}), + Edge({{-9,8},{-8,-9}}), + Edge({{-8,-9},{6,-6}}), + // hole + Edge({{-2,3},{3.5,2}}), + Edge({{3.5,2},{1.5,0.5}}), + Edge({{1.5,0.5},{3,-4}}), + Edge({{3,-4},{-3,-3}}), + Edge({{-3,-3},{-2,3}}) + }); + + //draw_while_paving(IntervalVector({{-10,10},{-10,10}}), c, 0.1); + + // Check a box inside the hole + { + IntervalVector x = IntervalVector({0,0}).inflate(0.5); + //DefaultView::draw_box(x,Color::purple()); + c.contract(x); + CHECK(x.is_empty()); + } + + // Check a box inside the polygon + { + IntervalVector x = IntervalVector({5,-5}).inflate(0.5), _x(x); + //DefaultView::draw_box(x,Color::purple()); + c.contract(x); + CHECK(x == _x); + } + + // Check a box outside the polygon + { + IntervalVector x = IntervalVector({-1,8}).inflate(0.5); + //DefaultView::draw_box(x,Color::purple()); + c.contract(x); + CHECK(x.is_empty()); + } + } + + { + CtcPolygon c({{6,-6},{7,9},{0,5},{-9,8},{-8,-9}}); + + // Check a box inside the polygon + { + IntervalVector x = IntervalVector({5,-5}).inflate(0.5), _x(x); + c.contract(x); + CHECK(x == _x); + } + + // Check a box outside the polygon + { + IntervalVector x = IntervalVector({-1,8}).inflate(0.5); + c.contract(x); + CHECK(x.is_empty()); + } + } +} \ No newline at end of file diff --git a/tests/core/contractors/codac2_tests_CtcPolygon.py b/tests/core/contractors/codac2_tests_CtcPolygon.py new file mode 100644 index 00000000..34810594 --- /dev/null +++ b/tests/core/contractors/codac2_tests_CtcPolygon.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +# Codac tests +# ---------------------------------------------------------------------------- +# \date 2024 +# \author Simon Rohou +# \copyright Copyright 2024 Codac Team +# \license GNU Lesser General Public License (LGPL) + +import unittest +from codac import * + +class TestCtcPolygon(unittest.TestCase): + + def tests_CtcPolygon(self): + + # Polygon, defined as a list of vertices + c = CtcPolygon([[3,-1],[3,4],[5,6],[-1,1]]) + + x = IntervalVector(2) + c.contract(x) + self.assertTrue(x == IntervalVector([[-1,5],[-1,6]])) + + x = IntervalVector([[3.02,3.16],[2.5,3.2]]) # possible bug + c.contract(x) + self.assertTrue(x.is_empty()) + + def tests_CtcPolygon_fromCodac1(self): + + # Polygone with hole, defined as a list of edges + + c = CtcPolygon([ + # external border + [[6,-6], [7,9]], + [[7,9], [0,5]], + [[0,5], [-9,8]], + [[-9,8], [-8,-9]], + [[-8,-9], [6,-6]], + # hole + [[-2,3], [3.5,2]], + [[3.5,2], [1.5,0.5]], + [[1.5,0.5], [3,-4]], + [[3,-4], [-3,-3]], + [[-3,-3], [-2,3]] + ]) + + #draw_while_paving(IntervalVector([[-10,10],[-10,10]]), c, 0.1) + + # Check a box inside the hole + + x = IntervalVector([[0],[0]]).inflate(0.5) + #DefaultView.draw_box(x,Color::purple()) + c.contract(x) + self.assertTrue(x.is_empty()) + + # Check a box inside the polygon + + x = IntervalVector([[5],[-5]]).inflate(0.5) + _x = IntervalVector(x) + #DefaultView.draw_box(x,Color::purple()) + c.contract(x) + self.assertTrue(x == _x) + + # Check a box outside the polygon + + x = IntervalVector([[-1],[8]]).inflate(0.5) + #DefaultView.draw_box(x,Color::purple()) + c.contract(x) + self.assertTrue(x.is_empty()) + + + # Other polygon, defined as a list of vertices + + c = CtcPolygon([[6,-6],[7,9],[0,5],[-9,8],[-8,-9]]) + + # Check a box inside the polygon + + x = IntervalVector([[5],[-5]]).inflate(0.5) + _x = IntervalVector(x) + c.contract(x) + self.assertTrue(x == _x) + + # Check a box outside the polygon + + x = IntervalVector([[-1],[8]]).inflate(0.5) + c.contract(x) + self.assertTrue(x.is_empty()) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/core/contractors/codac2_tests_CtcSegment.cpp b/tests/core/contractors/codac2_tests_CtcSegment.cpp index 3e600a61..9b49ed34 100644 --- a/tests/core/contractors/codac2_tests_CtcSegment.cpp +++ b/tests/core/contractors/codac2_tests_CtcSegment.cpp @@ -17,7 +17,7 @@ TEST_CASE("CtcSegment") { { IntervalVector x(2); - CtcSegment c({{3},{-1}},{{3},{4}}); + CtcSegment c({3,-1},{3,4}); x = IntervalVector(2); c.contract(x); @@ -34,7 +34,7 @@ TEST_CASE("CtcSegment") { IntervalVector x(2); - CtcSegment c({{-1},{-1}},{{1},{1}}); + CtcSegment c({-1,-1},{1,1}); x = IntervalVector(2); c.contract(x); @@ -42,7 +42,7 @@ TEST_CASE("CtcSegment") x = IntervalVector({{-oo,oo},{0}}); c.contract(x); - CHECK(x == IntervalVector({{0},{0}})); + CHECK(x == IntervalVector({0,0})); x = IntervalVector({{0,oo},{0,oo}}); c.contract(x); @@ -58,7 +58,7 @@ TEST_CASE("CtcSegment - tests from Codac1") { // Test_CtcSegment01 { - CtcSegment c({{0},{0}}, {{10},{20}}); + CtcSegment c({0,0}, {10,20}); IntervalVector x({{-5,50},{-5, 50}}); c.contract(x); CHECK(x == IntervalVector({{0,10},{0,20}})); @@ -66,7 +66,7 @@ TEST_CASE("CtcSegment - tests from Codac1") // Test_CtcSegment02 { - CtcSegment c({{0},{0}}, {{10},{20}}); + CtcSegment c({0,0}, {10,20}); IntervalVector x({{10,50},{20,50}}); c.contract(x); CHECK(x == IntervalVector({{10,10},{20,20}})); @@ -74,7 +74,7 @@ TEST_CASE("CtcSegment - tests from Codac1") // Test_contract_degenerate { - CtcSegment c({{5},{5}}, {{5},{5}}); + CtcSegment c({5,5}, {5,5}); IntervalVector x({{-5,50},{-5,50}}); c.contract(x); CHECK(x == IntervalVector({{5,5},{5,5}})); @@ -82,7 +82,7 @@ TEST_CASE("CtcSegment - tests from Codac1") // Test_contract_degenerate_x { - CtcSegment c({{5},{5}}, {{10},{5}}); + CtcSegment c({5,5}, {10,5}); IntervalVector x({{-50,50},{-50,50}}); c.contract(x); CHECK(x == IntervalVector({{5,10},{5,5}})); @@ -90,7 +90,7 @@ TEST_CASE("CtcSegment - tests from Codac1") // Test_contract_degenerate_y { - CtcSegment c({{-5},{-5}}, {{-5},{15}}); + CtcSegment c({-5,-5}, {-5,15}); IntervalVector x({Interval(-50, 50), Interval(-50, 50)}); c.contract(x); CHECK(x == IntervalVector({{-5,-5},{-5,15}})); @@ -98,7 +98,7 @@ TEST_CASE("CtcSegment - tests from Codac1") // Test_contract_empty { - CtcSegment c({{0},{0}}, {{10},{20}}); + CtcSegment c({0,0}, {10,20}); IntervalVector x({{-5,-2},{-5,50}}); c.contract(x); CHECK(x.is_empty()); @@ -106,7 +106,7 @@ TEST_CASE("CtcSegment - tests from Codac1") // Test_call_with_empty_x { - CtcSegment c({{0},{0}}, {{10},{20}}); + CtcSegment c({0,0}, {10,20}); IntervalVector x(2); c.contract(x); CHECK(x == IntervalVector({{0,10},{0,20}})); diff --git a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp index d252b5ec..0f984d42 100644 --- a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp +++ b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp @@ -52,20 +52,20 @@ TEST_CASE("Ellipsoids") {x}, vec(x[0]+0.1*x[1],-0.2*sin(x[0])+0.9*x[1])}; Matrix A = h.diff(e.mu).mid(); - Vector b(h.eval(e.mu).mid()._e - A._e*e.mu._e); + Vector b(h.eval(e.mu).mid() - A*e.mu); Ellipsoid e2 = unreliable_linear_mapping(e, A, b); Vector mu2({1 , -0.168294}); Matrix G2({{0.0500001 , 0.00500001},{-0.00540302 , 0.0450001}}); CHECK(e2.size() == 2); - CHECK((e2.mu._e-mu2._e).norm() < 1e-6); - CHECK((e2.G._e-G2._e).norm() < 1e-6); + CHECK((e2.mu-mu2).norm() < 1e-6); + CHECK((e2.G-G2).norm() < 1e-6); Ellipsoid e3 = nonlinear_mapping(e, h); Vector mu3({1. , -0.168294}); Matrix G3({{0.0550724 , 0.00550724},{-0.00595114 , 0.0495651}}); CHECK(e3.size() == 2); - CHECK((e3.mu._e-mu3._e).norm() < 1e-6); - CHECK((e3.G._e-G3._e).norm() < 1e-6); + CHECK((e3.mu-mu3).norm() < 1e-6); + CHECK((e3.G-G3).norm() < 1e-6); Ellipsoid e4_ = e4(); Ellipsoid e5_ = e5(); @@ -81,8 +81,8 @@ TEST_CASE("Ellipsoids") Ellipsoid e7 = unreliable_linear_mapping(e, A2, b2); Ellipsoid e8 = linear_mapping(e, A2, b2); - CHECK((e7.mu._e - e8.mu._e).norm()<1e-6); - CHECK((e7.G._e - e8.G._e).norm()<0.04); + CHECK((e7.mu - e8.mu).norm()<1e-6); + CHECK((e7.G - e8.G).norm()<0.04); } \ No newline at end of file diff --git a/tests/core/domains/interval/codac2_tests_IntervalMatrix.cpp b/tests/core/domains/interval/codac2_tests_IntervalMatrix.cpp index 402932ac..eaf88e14 100644 --- a/tests/core/domains/interval/codac2_tests_IntervalMatrix.cpp +++ b/tests/core/domains/interval/codac2_tests_IntervalMatrix.cpp @@ -7,16 +7,16 @@ * * ---------------------------------------------------------------------------- * \date 2024 - * \author Gilles Chabert, (Simon Rohou) + * \author Gilles Chabert, Simon Rohou * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ #include +#include #include #include #include -#include using namespace std; using namespace codac2; @@ -66,10 +66,10 @@ TEST_CASE("IntervalMatrix") IntervalMatrix m1(2,3); IntervalMatrix m2(2,3); - CHECK(m1.nb_rows() == 2); - CHECK(m1.nb_cols() == 3); - CHECK(m2.nb_rows() == 2); - CHECK(m2.nb_cols() == 3); + CHECK(m1.rows() == 2); + CHECK(m1.cols() == 3); + CHECK(m2.rows() == 2); + CHECK(m2.cols() == 3); m1(0,0) = 1.; m1(0,1) = 2.; @@ -107,8 +107,8 @@ TEST_CASE("IntervalMatrix") { IntervalMatrix m(2,3); - CHECK(m.nb_rows() == 2); - CHECK(m.nb_cols() == 3); + CHECK(m.rows() == 2); + CHECK(m.cols() == 3); CHECK(m(0,0) == Interval(-oo,oo)); CHECK(m(0,1) == Interval(-oo,oo)); CHECK(m(0,2) == Interval(-oo,oo)); @@ -121,34 +121,28 @@ TEST_CASE("IntervalMatrix") } { - IntervalMatrix m1(2,3, 0.); - double _r1[][2] = {{0,1},{0,2},{0,3}}; - double _r2[][2] = {{-1,0},{-2,0},{-3,0}}; - auto r1_0 = IntervalVector(3,_r1); - CHECK(r1_0.nb_cols() == 1); - CHECK(r1_0.nb_rows() == 3); - auto r1 = IntervalVector(3,_r1).transpose(); - CHECK(r1.nb_cols() == 3); - CHECK(r1.nb_rows() == 1); - auto r2 = IntervalVector(3,_r2).transpose(); - CHECK(r2.nb_cols() == 3); - CHECK(r2.nb_rows() == 1); + IntervalMatrix m1 = IntervalMatrix::zero(2,3); + auto r1_0 = IntervalVector({{0,1},{0,2},{0,3}}); + CHECK(r1_0.cols() == 1); + CHECK(r1_0.rows() == 3); + auto r1 = IntervalVector({{0,1},{0,2},{0,3}}).transpose().eval(); + CHECK(r1.cols() == 3); + CHECK(r1.rows() == 1); + auto r2 = IntervalVector({{-1,0},{-2,0},{-3,0}}).transpose().eval(); + CHECK(r2.cols() == 3); + CHECK(r2.rows() == 1); CHECK(r1 == IntervalMatrix({ { {0,1}, {0,2}, {0,3} } })); m1.row(0) = r1; m1.row(1) = r2; - double _c1[][2] = {{0,1},{-1,0}}; - double _c2[][2] = {{0,2},{-2,0}}; - double _c3[][2] = {{0,3},{-3,0}}; + IntervalVector c1({{0,1},{-1,0}}); + IntervalVector c2({{0,2},{-2,0}}); + IntervalVector c3({{0,3},{-3,0}}); - IntervalVector c1(2,_c1); - IntervalVector c2(2,_c2); - IntervalVector c3(2,_c3); - - CHECK(m1.nb_rows() == 2); - CHECK(m1.nb_cols() == 3); + CHECK(m1.rows() == 2); + CHECK(m1.cols() == 3); CHECK((m1.row(0) == r1)); CHECK((m1.row(1) == r2)); CHECK((m1.row(0) == r1)); @@ -170,10 +164,10 @@ TEST_CASE("IntervalMatrix") { Interval x(-1,2); - IntervalMatrix m(2,3,x); + IntervalMatrix m = IntervalMatrix::constant(2,3,x); - CHECK(m.nb_rows() == 2); - CHECK(m.nb_cols() == 3); + CHECK(m.rows() == 2); + CHECK(m.cols() == 3); for(size_t i = 0 ; i < 2 ; i++) for(size_t j = 0 ; j < 3 ; j++) CHECK(m(i,j) == x); @@ -212,8 +206,8 @@ TEST_CASE("IntervalMatrix") } { - CHECK(IntervalMatrix::empty(2,3).nb_rows() == 2); - CHECK(IntervalMatrix::empty(2,3).nb_cols() == 3); + CHECK(IntervalMatrix::empty(2,3).rows() == 2); + CHECK(IntervalMatrix::empty(2,3).cols() == 3); CHECK(IntervalMatrix(IntervalMatrix::empty(2,3)) == IntervalMatrix::empty(2,3)); CHECK((IntervalMatrix(2,3)=IntervalMatrix::empty(2,3)) == IntervalMatrix::empty(2,3)); @@ -306,13 +300,11 @@ TEST_CASE("IntervalMatrix") { IntervalMatrix m1(2,2); - double _r1[][2] = {{0,1},{0,2}}; - double _r2[][2] = {{-1,0},{-2,0}}; - IntervalVector r1(2,_r1); - IntervalVector r2(2,_r2); - m1.row(0) = r1.transpose(); - m1.row(1) = r2.transpose(); - m1.resize(2,3); + IntervalVector r1({{0,1},{0,2}}); + IntervalVector r2({{-1,0},{-2,0}}); + m1.row(0) = r1.transpose().eval(); + m1.row(1) = r2.transpose().eval(); + m1.resize_save_values(2,3); m1(0,2) = Interval(0,3); m1(1,2) = Interval(-3,0); @@ -321,10 +313,9 @@ TEST_CASE("IntervalMatrix") { IntervalMatrix m1(1,3); - double _r1[][2] = {{0,1},{0,2},{0,3}}; - IntervalVector r1(3,_r1); - m1.row(0) = r1.transpose(); - m1.resize(2,3); + IntervalVector r1({{0,1},{0,2},{0,3}}); + m1.row(0) = r1.transpose().eval(); + m1.resize_save_values(2,3); m1(1,0) = Interval(-1,0); m1(1,1) = Interval(-2,0); m1(1,2) = Interval(-3,0); @@ -334,7 +325,7 @@ TEST_CASE("IntervalMatrix") { IntervalMatrix e(IntervalMatrix::empty(1,1)); - e.resize(2,3); + e.resize_save_values(2,3); CHECK(e.is_empty()); } @@ -347,7 +338,7 @@ TEST_CASE("IntervalMatrix") } { - CHECK(-IntervalMatrix::empty(2,3).is_empty()); + CHECK((-IntervalMatrix::empty(2,3)).is_empty()); } { @@ -393,8 +384,8 @@ TEST_CASE("IntervalMatrix") IntervalMatrix m1(M1()); IntervalMatrix m2(M2()); IntervalMatrix m3(m1*m2); - CHECK(m3.nb_rows() == 2); - CHECK(m3.nb_cols() == 2); + CHECK(m3.rows() == 2); + CHECK(m3.cols() == 2); for(size_t i = 0 ; i < 2 ; i++) for(size_t j = 0 ; j < 2 ; j++) @@ -451,7 +442,7 @@ TEST_CASE("IntervalMatrix") IntervalMatrix res(4,4); res.block(0,0,3,3) = M1; res.block(0,3,3,1) = V1; - res.block(3,0,1,3) = IntervalVector::ones(3).transpose(); + res.block(3,0,1,3) = IntervalVector::ones(3).transpose().eval(); res(3,3) = 6; double _expected[16] = { 2,0,0,3, @@ -510,7 +501,7 @@ TEST_CASE("IntervalMatrix") } } -TEST_CASE("IntervalMatrix - mixing types") +TEST_CASE("IntervalMatrix - mixing type") { { Matrix m1 { @@ -531,10 +522,13 @@ TEST_CASE("IntervalMatrix - mixing types") }); IntervalVector v1({ - {-1}, - {-2} + -1, + -2 }); + CHECK(v1[0] == -1); + CHECK(v1[1] == -2); + IntervalVector iv1({ {-1,1}, {-1,1} @@ -614,6 +608,128 @@ TEST_CASE("IntervalMatrix - mixing types") // Row of IntervalMatrix - col of IntervalMatrix CHECK((im1.row(1) * im1.col(0)) == IntervalMatrix({{{-15,15}}})); } + + { + Matrix m1 { + { {1},{2} }, + { {3},{4} } + }; + + Matrix m2 { + { {2},{3} }, + { {4},{5} } + }; + + IntervalMatrix im(m1,m2); + CHECK(im == IntervalMatrix{ + { {1,2},{2,3} }, + { {3,4},{4,5} } + }); + + m2(0,1) = 1.; + + IntervalMatrix im_empty(m1,m2); + CHECK(im_empty == IntervalMatrix::empty(2,2)); + } + + { + IntervalMatrix m1 = IntervalMatrix::ones(3,3); + IntervalMatrix m2 = IntervalMatrix::zero(3,3); + CHECK(m1.volume() == 0.); + CHECK(m2.volume() == 0.); + CHECK((m1+m2).volume() == 0.); + } + + { + IntervalMatrix m1 { + { {1,2},{2,3} }, + { {3,4},{4,5} } + }; + Matrix m2 { + { 1.5, 2.5 }, + { 3.5, 4.5 } + }; + + CHECK(m1.contains(m2)); + CHECK(m2.template cast().is_strict_subset(m1)); + + Matrix m3(2,2); + m3.init(m2+m2); + CHECK(m3 == Matrix({ + { 3, 5 }, + { 7, 9 } + })); + + IntervalMatrix m4(m2+m2); + CHECK(m4 == IntervalMatrix({ + {{3,3},{5,5}}, + {{7,7},{9,9}} + })); + + IntervalMatrix m5(m2*m2); + CHECK(m5 == IntervalMatrix({ + {{11,11},{15,15}}, + {{21,21},{29,29}} + })); + } + + { + IntervalMatrix test1 { + { {0,1}, {0,2}, {0,0} } + }; + CHECK(test1.rows() == 1); + CHECK(test1.cols() == 3); + CHECK(test1(0,0) == Interval(0,1)); + CHECK(test1(0,1) == Interval(0,2)); + CHECK(test1(0,2) == Interval(0,0)); + + IntervalMatrix test2 { + {0,1}, + {2,3}, + {4,5} + }; + CHECK(test2.rows() == 3); + CHECK(test2.cols() == 2); + CHECK(test2(0,0) == Interval(0)); + CHECK(test2(0,1) == Interval(1)); + CHECK(test2(1,0) == Interval(2)); + CHECK(test2(1,1) == Interval(3)); + CHECK(test2(2,0) == Interval(4)); + CHECK(test2(2,1) == Interval(5)); + + IntervalMatrix test3 { + {{1,oo},{2,oo}}, + {{3,oo},{4,oo}}, + {{5,oo},{6,oo}} + }; + CHECK(test3.rows() == 3); + CHECK(test3.cols() == 2); + CHECK(test3(0,0) == Interval(1,oo)); + CHECK(test3(0,1) == Interval(2,oo)); + CHECK(test3(1,0) == Interval(3,oo)); + CHECK(test3(1,1) == Interval(4,oo)); + CHECK(test3(2,0) == Interval(5,oo)); + CHECK(test3(2,1) == Interval(6,oo)); + + IntervalMatrix test4 { + {{1,2}}, + {{3,4}}, + {{5,6}} + }; + CHECK(test4.rows() == 3); + CHECK(test4.cols() == 1); + CHECK(test4(0,0) == Interval(1,2)); + CHECK(test4(1,0) == Interval(3,4)); + CHECK(test4(2,0) == Interval(5,6)); + + IntervalVector iv({{1,2},{3,4},{5,6}}); + IntervalMatrix test5(iv); + CHECK(test5.rows() == 3); + CHECK(test5.cols() == 1); + CHECK(test5(0,0) == Interval(1,2)); + CHECK(test5(1,0) == Interval(3,4)); + CHECK(test5(2,0) == Interval(5,6)); + } } #if 0 diff --git a/tests/core/domains/interval/codac2_tests_IntervalMatrix.py b/tests/core/domains/interval/codac2_tests_IntervalMatrix.py index 7498053b..ba46854c 100644 --- a/tests/core/domains/interval/codac2_tests_IntervalMatrix.py +++ b/tests/core/domains/interval/codac2_tests_IntervalMatrix.py @@ -8,7 +8,7 @@ # # ---------------------------------------------------------------------------- # \date 2024 -# \author Gilles Chabert, (Simon Rohou) +# \author Gilles Chabert, Simon Rohou # \copyright Copyright 2024 Codac Team # \license GNU Lesser General Public License (LGPL) @@ -19,7 +19,26 @@ class TestIntervalMatrix(unittest.TestCase): - def tests_intervalmatrix(self): + def M1(self): + return IntervalMatrix([ + [[0,1],[0,2],[0,3]], + [[-1,0],[-2,0],[-3,0]] + ]) + + def M2(self): # the transpose of M1 + return IntervalMatrix([ + [[0,1],[-1,0]], + [[0,2],[-2,0]], + [[0,3],[-3,0]] + ]) + + def M3(self): # non-null intersection with M1 + return IntervalMatrix([ + [[1,2],[1,2],[2,4]], + [[-2,-1],[-2,-1],[-4,-2]] + ]) + + def tests_0_intervalmatrix(self): x = IntervalMatrix([ [ [-1,1], [-2,2] ], @@ -36,5 +55,610 @@ def tests_intervalmatrix(self): #m = IntervalMatrix(x) + def tests_intervalmatrix(self): + + m1 = IntervalMatrix(2,3) + m2 = IntervalMatrix(3,2) + self.assertTrue(m1 != m2) + self.assertTrue(not (m1 == m2)) + + m1 = IntervalMatrix(3,2) + m2 = IntervalMatrix(2,2) + self.assertTrue(m1 != m2) + self.assertTrue(not (m1 == m2)) + + m1 = IntervalMatrix(2,3) + m2 = IntervalMatrix(2,3) + + self.assertTrue(m1.rows() == 2) + self.assertTrue(m1.cols() == 3) + self.assertTrue(m2.rows() == 2) + self.assertTrue(m2.cols() == 3) + + m1[0,0] = 1. + m1[0,1] = 2. + m1[0,2] = 3. + m1[1,0] = 4. + m1[1,1] = 5. + m1[1,2] = 6. + m2[0,0] = 1. + m2[0,1] = 2. + m2[0,2] = 3. + m2[1,0] = 4. + m2[1,1] = 5. + m2[1,2] = 6. + + self.assertTrue(m1 == m2) + self.assertTrue(not (m1 != m2)) + + m2[1,2] = 7. + self.assertTrue(m1 != m2) + self.assertTrue(not (m1 == m2)) + + m1 = IntervalMatrix(2,3) + m2 = IntervalMatrix(2,3) + m1[1,1] = -1 + m2[1,1] = -2 + self.assertTrue(m1 != m2) + self.assertTrue(not (m1 == m2)) + m1.set_empty() + m2.set_empty() + self.assertTrue(m1 == m2) + self.assertTrue(not (m1 != m2)) + + m = IntervalMatrix(2,3) + self.assertTrue(m.rows() == 2) + self.assertTrue(m.cols() == 3) + self.assertTrue(m(0,0) == Interval(-oo,oo)) + self.assertTrue(m(0,1) == Interval(-oo,oo)) + self.assertTrue(m(0,2) == Interval(-oo,oo)) + self.assertTrue(m(1,0) == Interval(-oo,oo)) + self.assertTrue(m(1,1) == Interval(-oo,oo)) + self.assertTrue(m(1,2) == Interval(-oo,oo)) + + self.assertTrue(m == IntervalMatrix(m)) + #self.assertTrue(m == (IntervalMatrix(2,3)=m)) + + m1 = IntervalMatrix.zero(2,3) + r1_0 = IntervalVector([[0,1],[0,2],[0,3]]) + self.assertTrue(r1_0.cols() == 1) + self.assertTrue(r1_0.rows() == 3) + r1 = IntervalVector([[0,1],[0,2],[0,3]]).transpose() + self.assertTrue(r1.cols() == 3) + self.assertTrue(r1.rows() == 1) + r2 = IntervalVector([[-1,0],[-2,0],[-3,0]]).transpose() + self.assertTrue(r2.cols() == 3) + self.assertTrue(r2.rows() == 1) + self.assertTrue(r1 == IntervalMatrix([ + [ [0,1], [0,2], [0,3] ] + ])) + + m1.set_row(0,r1) + m1.set_row(1,r2) + + c1 = IntervalVector([[0,1],[-1,0]]) + c2 = IntervalVector([[0,2],[-2,0]]) + c3 = IntervalVector([[0,3],[-3,0]]) + + self.assertTrue(m1.rows() == 2) + self.assertTrue(m1.cols() == 3) + + a1 = IntervalRow(r1) + a2 = IntervalRow(m1.row(0)) + self.assertTrue(a1 == a2) + + self.assertTrue((m1.row(0) == r1)) + self.assertTrue((m1.row(1) == r2)) + self.assertTrue((m1.row(0) == r1)) + self.assertTrue((m1.row(1) == r2)) + + self.assertTrue((m1.col(0) == c1)) + self.assertTrue((m1.col(1) == c2)) + self.assertTrue((m1.col(2) == c3)) + self.assertTrue(m1(0,0) == Interval(0,1)) + self.assertTrue(m1(0,1) == Interval(0,2)) + self.assertTrue(m1(0,2) == Interval(0,3)) + self.assertTrue(m1(1,0) == Interval(-1,0)) + self.assertTrue(m1(1,1) == Interval(-2,0)) + self.assertTrue(m1(1,2) == Interval(-3,0)) + + self.assertTrue(m1 == IntervalMatrix(m1)) + #self.assertTrue(m1 == (IntervalMatrix(2,3)=m1)) + + x = Interval(-1,2) + m = IntervalMatrix.constant(2,3,x) + + self.assertTrue(m.rows() == 2) + self.assertTrue(m.cols() == 3) + for i in range (0,2): + for j in range (0,3): + self.assertTrue(m(i,j) == x) + + self.assertTrue(m == IntervalMatrix(m)) + #self.assertTrue(m == (IntervalMatrix(2,3)=m)) + + #double _m[][2] = [ + # [0,1], [0,2], [0,3], + # [-1,0],[-2,0],[-3,0] + #] + #m = IntervalMatrix(2,3,_m) + #self.assertTrue(m == self.M1()) + + m = IntervalMatrix([ + [[0,1], [0,2], [0,3]], + [[-1,0],[-2,0],[-3,0]] + ]) + self.assertTrue(m == self.M1()) + + m = IntervalMatrix(2,3) + # accessor (row,col) + m[0,0] = Interval(0,1) + m[0,1] = Interval(0,2) + m[0,2] = Interval(0,3) + m[1,0] = Interval(-1,0) + m[1,1] = Interval(-2,0) + m[1,2] = Interval(-3,0) + self.assertTrue(m == self.M1()) + + self.assertTrue(IntervalMatrix.empty(2,3).rows() == 2) + self.assertTrue(IntervalMatrix.empty(2,3).cols() == 3) + + self.assertTrue(IntervalMatrix(IntervalMatrix.empty(2,3)) == IntervalMatrix.empty(2,3)) + #self.assertTrue((IntervalMatrix(2,3)=IntervalMatrix.empty(2,3)) == IntervalMatrix.empty(2,3)) + + self.assertTrue(not IntervalMatrix(2,3).is_empty()) + self.assertTrue(IntervalMatrix.empty(2,3).is_empty()) + + m = IntervalMatrix(2,3) + m.set_empty() + self.assertTrue(m.is_empty()) + + # Intersection of a matrix with itself + m1 = self.M1() + m1 &= self.M1() + self.assertTrue(m1 == self.M1()) + + # Intersection of two overlapping matrices + m = IntervalMatrix([ + [[1,1], [1,2], [2,3]], + [[-1,-1],[-2,-1],[-3,-2]] + ]) + + m1 = self.M1() + m1 &= self.M3() + self.assertTrue(m1 == m) + + # Intersection of two non-overlapping matrices + m3 = IntervalMatrix(self.M3()) + m3[1,2] = Interval(-5,-4) + m1 = IntervalMatrix(self.M1()) + m1 &= m3 + self.assertTrue(m1.is_empty()) + + m1 = IntervalMatrix(self.M1()) + + v = IntervalVector(2) + v[0] = Interval(1,2) + v[1] = Interval(-2,-1) + + m1.set_col(1,v) + + m2 = IntervalMatrix([ + [[0,1], [1,2], [0,3]], + [[-1,0],[-2,-1],[-3,0]] + ]) + self.assertTrue(m1 == m2) + + self.assertTrue(self.M1().block(0,0,2,3) == self.M1()) + self.assertTrue(self.M1().block(0,0,1,3) == IntervalMatrix([[[0,1],[0,2],[0,3]]])) + self.assertTrue(self.M1().block(1,0,1,3) == IntervalMatrix([[[-1,0],[-2,0],[-3,0]]])) + self.assertTrue(self.M1().block(0,0,2,1) == IntervalMatrix([[[0,1]],[[-1,0]]])) + self.assertTrue(self.M1().block(0,1,2,1) == IntervalMatrix([[[0,2]],[[-2,0]]])) + self.assertTrue(self.M1().block(0,2,2,1) == IntervalMatrix([[[0,3]],[[-3,0]]])) + self.assertTrue(self.M1().block(0,1,2,2) == IntervalMatrix([[[0,2],[0,3]],[[-2,0],[-3,0]]])) + + m1 = IntervalMatrix(2,2) + r1 = IntervalVector([[0,1],[0,2]]) + r2 = IntervalVector([[-1,0],[-2,0]]) + m1.set_row(0,r1.transpose()) + m1.set_row(1,r2.transpose()) + m1.resize_save_values(2,3) + m1[0,2] = Interval(0,3) + m1[1,2] = Interval(-3,0) + + self.assertTrue(m1 == self.M1()) + + m1 = IntervalMatrix(1,3) + r1 = IntervalVector([[0,1],[0,2],[0,3]]) + m1.set_row(0,r1.transpose()) + m1.resize_save_values(2,3) + m1[1,0] = Interval(-1,0) + m1[1,1] = Interval(-2,0) + m1[1,2] = Interval(-3,0) + + self.assertTrue(m1 == self.M1()) + + e = IntervalMatrix.empty(1,1) + e.resize_save_values(2,3) + self.assertTrue(e.is_empty()) + + m1 = IntervalMatrix(self.M1()) + m2 = IntervalMatrix(-m1) + for i in range (0,2): + for j in range(0,3): + self.assertTrue(m2(i,j) == -m1(i,j)) + + self.assertTrue((-IntervalMatrix.empty(2,3)).is_empty()) + + m1 = IntervalMatrix(self.M1()) + m2 = IntervalMatrix(m1+m1) + + for i in range (0,2): + for j in range(0,3): + self.assertTrue(m2(i,j) == m1(i,j)+m1(i,j)) + + m0 = IntervalMatrix(m1) + m0 += m1 + self.assertTrue(m2 == m0) + + m1 = IntervalMatrix.empty(2,3) + m2 = IntervalMatrix(2,3) + + self.assertTrue((m1+m2).is_empty()) + m1+=m2 + self.assertTrue(m1.is_empty()) + m2+=m1 + self.assertTrue(m2.is_empty()) + + m1 = IntervalMatrix(self.M1()) + m2 = IntervalMatrix(m1-m1) + for i in range (0,2): + for j in range(0,3): + self.assertTrue(m2(i,j) == m1(i,j)-m1(i,j)) + + m0 = IntervalMatrix(m1) + m0 -= m1 + self.assertTrue(m2 == m0) + + m1 = IntervalMatrix.empty(2,3) + m2 = IntervalMatrix(2,3) + + self.assertTrue((m1-m2).is_empty()) + m1-=m2 + self.assertTrue(m1.is_empty()) + m2-=m1 + self.assertTrue(m2.is_empty()) + + m1 = IntervalMatrix(self.M1()) + m2 = IntervalMatrix(self.M2()) + m3 = IntervalMatrix(m1*m2) + self.assertTrue(m3.rows() == 2) + self.assertTrue(m3.cols() == 2) + + for i in range (0,2): + for j in range(0,2): + self.assertTrue(m3(i,j) == m1(i,0)*m2(0,j)+m1(i,1)*m2(1,j)+m1(i,2)*m2(2,j)) + + # Not supported by Eigen: self.assertTrue(m3 == (IntervalMatrix(m1)*=m2)) + + m1 = IntervalMatrix.empty(2,3) + m2 = IntervalMatrix(3,2) + + self.assertTrue((m1*m2).is_empty()) + # Not supported by Eigen: self.assertTrue((m1*=m2).is_empty()) + # Not supported by Eigen: self.assertTrue((m2*=m1).is_empty()) + + M1 = IntervalMatrix(Matrix.eye(2,2)) + self.assertTrue(M1 == IntervalMatrix([ + [ [1,1],[0,0] ], + [ [0,0],[1,1] ] + ])) + + M2 = IntervalMatrix(2.*Matrix.eye(2,2)) + self.assertTrue(M2 == IntervalMatrix([ + [ [2,2],[0,0] ], + [ [0,0],[2,2] ] + ])) + + M3_degenerate = Matrix(-1.*Matrix.eye(2,2)) + self.assertTrue(M3_degenerate == Matrix([ + [ -1,0 ], + [ 0,-1 ] + ])) + + M3_Matrix = IntervalMatrix(Interval(-1,1)*Matrix.eye(2,2)) + self.assertTrue(M3_Matrix == IntervalMatrix([ + [ [-1,1],[0,0] ], + [ [0,0],[-1,1] ] + ])) + + M3_IntervalMatrix = IntervalMatrix(Interval(-1,1)*IntervalMatrix.eye(2,2)) + self.assertTrue(M3_IntervalMatrix == IntervalMatrix([ + [ [-1,1],[0,0] ], + [ [0,0],[-1,1] ] + ])) + + M1 = IntervalMatrix(2.*Matrix.eye(3,3)) + V1 = IntervalVector(3) + V1[0] = 3 + V1[1] = 4 + V1[2] = 5 + res = IntervalMatrix(4,4) + res.set_block(0,0,3,3,M1) + res.set_block(0,3,3,1,V1) + res.set_block(3,0,1,3,IntervalVector.ones(3).transpose()) + res[3,3] = 6 + + self.assertTrue((res == Matrix([ + [2,0,0,3], + [0,2,0,4], + [0,0,2,5], + [1,1,1,6] + ]))) + + m1 = Matrix([ + [ 0,2 ], + [ 3,10 ] + ]) + m2 = Matrix([ + [ -1,7 ], + [ 8,4 ] + ]) + + self.assertTrue((IntervalMatrix(m1) | m2) == IntervalMatrix([ + [ [-1,0],[2,7] ], + [ [3,8],[4,10] ] + ])) + + m1 = IntervalMatrix([ + [ [0,1],[0,2] ], + [ [0,0],Interval.empty() ] + ]) + m2 = IntervalMatrix([ + [ [-oo,oo],[-1,3] ], + [ [2,4],[1,1] ] + ]) + + self.assertTrue((m1 | m2) == IntervalMatrix([ + [ [-oo,oo],[-1,3] ], + [ [0,4],[1,1] ] + ])) + + m1 = IntervalMatrix([ + [ [0,1],[0,2] ], + [ [0,0],Interval.empty() ] + ]) + m2 = IntervalMatrix([ + [ [-oo,oo],[-1,3] ], + [ [2,4],[1,1] ] + ]) + + self.assertTrue((m1 & m2) == IntervalMatrix([ + [ [0,1],[0,2] ], + [ Interval.empty(),Interval.empty() ] + ])) + + + def tests_intervalmatrix_mixing_type(self): + + m1 = Matrix([ + [ 1,2 ], + [ 3,4 ] + ]) + + # Interval - Matrix + self.assertTrue((Interval(-1,1) * m1) == IntervalMatrix([ + [ [-1,1],[-2,2] ], + [ [-3,3],[-4,4] ] + ])) + + # Matrix - Interval + self.assertTrue((m1 / Interval(2)) == IntervalMatrix([ + [ [1./2.],[2./2.] ], + [ [3./2.],[4./2.] ] + ])) + + v1 = IntervalVector([ + -1, + -2 + ]) + + self.assertTrue(v1[0] == -1) + self.assertTrue(v1[1] == -2) + + iv1 = IntervalVector([ + [-1,1], + [-1,1] + ]) + + # Matrix - IntervalVector + self.assertTrue((m1 * iv1) == IntervalVector([ + [-3,3], + [-7,7] + ])) + + # double - IntervalVector + self.assertTrue((-3 * iv1) == IntervalVector([ + [-3,3], + [-3,3] + ])) + + # Interval - Vector + self.assertTrue((Interval(-1,1) * v1) == IntervalVector([ + [-1,1], + [-2,2] + ])) + + im1 = IntervalMatrix([ + [ [-1,1],[-2,2] ], + [ [-3,3],[-4,4] ] + ]) + + # Matrix - IntervalMatrix + self.assertTrue((m1 + im1) == IntervalMatrix([ + [ [0,2],[0,4] ], + [ [0,6],[0,8] ] + ])) + + # IntervalMatrix - Matrix + self.assertTrue((im1 + m1) == IntervalMatrix([ + [ [0,2],[0,4] ], + [ [0,6],[0,8] ] + ])) + + # IntervalMatrix - Matrix block + self.assertTrue((im1 + m1.block(0,0,2,2)) == IntervalMatrix([ + [ [0,2],[0,4] ], + [ [0,6],[0,8] ] + ])) + + # Matrix block - IntervalMatrix + self.assertTrue((m1.block(0,0,2,2) + im1) == IntervalMatrix([ + [ [0,2],[0,4] ], + [ [0,6],[0,8] ] + ])) + + # Matrix - IntervalMatrix + self.assertTrue((m1 - im1) == IntervalMatrix([ + [ [0,2],[0,4] ], + [ [0,6],[0,8] ] + ])) + + # IntervalMatrix - Matrix + self.assertTrue((im1 - m1) == IntervalMatrix([ + [ [-2,0],[-4,0] ], + [ [-6,0],[-8,0] ] + ])) + + # Matrix - col of IntervalMatrix + self.assertTrue((m1 * im1.col(0)) == IntervalMatrix([ + [ [-7,7] ], + [ [-15,15] ] + ])) + + # Row of Matrix - col of Matrix + # operations on Row types not supported yet in Python: self.assertTrue((m1.row(1) * m1.col(0)) == Matrix([[15]])) + + # Row of Matrix - col of IntervalMatrix + # operations on Row types not supported yet in Python: self.assertTrue((m1.row(1) * im1.col(0)) == IntervalMatrix([[[-15,15]]])) + + # Row of IntervalMatrix - col of IntervalMatrix + # operations on Row types not supported yet in Python: self.assertTrue((im1.row(1) * im1.col(0)) == IntervalMatrix([[[-15,15]]])) + + m1 = Matrix([ + [ 1,2 ], + [ 3,4 ] + ]) + + m2 = Matrix([ + [ 2,3 ], + [ 4,5 ] + ]) + + im = IntervalMatrix(m1,m2) + self.assertTrue(im == IntervalMatrix([ + [ [1,2],[2,3] ], + [ [3,4],[4,5] ] + ])) + + m2[0,1] = 1. + + im_empty = IntervalMatrix(m1,m2) + self.assertTrue(im_empty == IntervalMatrix.empty(2,2)) + + m1 = IntervalMatrix.ones(3,3) + m2 = IntervalMatrix.zero(3,3) + self.assertTrue(m1.volume() == 0.) + self.assertTrue(m2.volume() == 0.) + self.assertTrue((m1+m2).volume() == 0.) + + m1 = IntervalMatrix([ + [ [1,2],[2,3] ], + [ [3,4],[4,5] ] + ]) + m2 = Matrix([ + [ 1.5, 2.5 ], + [ 3.5, 4.5 ] + ]) + + self.assertTrue(m1.contains(m2)) + self.assertTrue(IntervalMatrix(m2).is_strict_subset(m1)) + + m3 = Matrix(2,2) + m3.init(m2+m2) + self.assertTrue(m3 == Matrix([ + [ 3, 5 ], + [ 7, 9 ] + ])) + + m4 = IntervalMatrix(m2+m2) + self.assertTrue(m4 == IntervalMatrix([ + [[3,3],[5,5]], + [[7,7],[9,9]] + ])) + + m5 = IntervalMatrix(m2*m2) + self.assertTrue(m5 == IntervalMatrix([ + [[11,11],[15,15]], + [[21,21],[29,29]] + ])) + + test1 = IntervalMatrix([ + [ [0,1], [0,2], [0,0] ] + ]) + self.assertTrue(test1.rows() == 1) + self.assertTrue(test1.cols() == 3) + self.assertTrue(test1(0,0) == Interval(0,1)) + self.assertTrue(test1(0,1) == Interval(0,2)) + self.assertTrue(test1(0,2) == Interval(0,0)) + + test2 = IntervalMatrix([ + [0,1], + [2,3], + [4,5] + ]) + self.assertTrue(test2.rows() == 3) + self.assertTrue(test2.cols() == 2) + self.assertTrue(test2(0,0) == Interval(0)) + self.assertTrue(test2(0,1) == Interval(1)) + self.assertTrue(test2(1,0) == Interval(2)) + self.assertTrue(test2(1,1) == Interval(3)) + self.assertTrue(test2(2,0) == Interval(4)) + self.assertTrue(test2(2,1) == Interval(5)) + + test3 = IntervalMatrix([ + [[1,oo],[2,oo]], + [[3,oo],[4,oo]], + [[5,oo],[6,oo]] + ]) + self.assertTrue(test3.rows() == 3) + self.assertTrue(test3.cols() == 2) + self.assertTrue(test3(0,0) == Interval(1,oo)) + self.assertTrue(test3(0,1) == Interval(2,oo)) + self.assertTrue(test3(1,0) == Interval(3,oo)) + self.assertTrue(test3(1,1) == Interval(4,oo)) + self.assertTrue(test3(2,0) == Interval(5,oo)) + self.assertTrue(test3(2,1) == Interval(6,oo)) + + test4 = IntervalMatrix([ + [[1,2]], + [[3,4]], + [[5,6]] + ]) + self.assertTrue(test4.rows() == 3) + self.assertTrue(test4.cols() == 1) + self.assertTrue(test4(0,0) == Interval(1,2)) + self.assertTrue(test4(1,0) == Interval(3,4)) + self.assertTrue(test4(2,0) == Interval(5,6)) + + iv = IntervalVector([[1,2],[3,4],[5,6]]) + test5 = IntervalMatrix(iv) + self.assertTrue(test5.rows() == 3) + self.assertTrue(test5.cols() == 1) + self.assertTrue(test5(0,0) == Interval(1,2)) + self.assertTrue(test5(1,0) == Interval(3,4)) + self.assertTrue(test5(2,0) == Interval(5,6)) + + if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/tests/core/domains/interval/codac2_tests_IntervalVector.cpp b/tests/core/domains/interval/codac2_tests_IntervalVector.cpp index 12cbfe24..5102b483 100644 --- a/tests/core/domains/interval/codac2_tests_IntervalVector.cpp +++ b/tests/core/domains/interval/codac2_tests_IntervalVector.cpp @@ -7,15 +7,15 @@ * * ---------------------------------------------------------------------------- * \date 2024 - * \author Gilles Chabert, (Simon Rohou) + * \author Gilles Chabert, Simon Rohou * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ #include #include +#include #include -#include using namespace std; using namespace codac2; @@ -33,7 +33,7 @@ void CHECK_diff(const IntervalVector& x, const IntervalVector& y, bool compactne for(const auto& ci : c) { bool found = false; - for(size_t i = 0 ; i < result.nb_rows() ; i++) + for(Index i = 0 ; i < result.rows() ; i++) if(ci == IntervalMatrix(result.row(i)).transpose().col(0)) { found = true; @@ -58,7 +58,7 @@ TEST_CASE("IntervalVector") IntervalVector x(2); x[0] = Interval(0,1); x[1] = Interval(0,1); - CHECK(x == IntervalVector(2,Interval(0,1))); + CHECK(x == IntervalVector({{0,1},{0,1}})); CHECK(x == IntervalVector(x)); CHECK(x == (IntervalVector(2)=x)); } @@ -112,7 +112,7 @@ TEST_CASE("IntervalVector") { IntervalVector x(1); x[0] = Interval(1,2); - x.resize(3); + x.resize_save_values(3); CHECK(x.size() == 3); CHECK(x[0] == Interval(1,2)); CHECK(x[1] == Interval(-oo,oo)); @@ -122,7 +122,7 @@ TEST_CASE("IntervalVector") { IntervalVector x(1); x[0] = Interval(1,2); - x.resize(1); + x.resize_save_values(1); CHECK(x.size() == 1); CHECK(x[0] == Interval(1,2)); } @@ -131,7 +131,7 @@ TEST_CASE("IntervalVector") IntervalVector x(2); x[0] = Interval(1,2); x.set_empty(); - x.resize(3); + x.resize_save_values(3); CHECK(x.size() == 3); CHECK(x.is_empty()); CHECK(x[2] == Interval(-oo,oo)); @@ -141,7 +141,7 @@ TEST_CASE("IntervalVector") IntervalVector x(5); x[0] = Interval(1,2); x[1] = Interval(3,4); - x.resize(2); + x.resize_save_values(2); CHECK(x.size() == 2); CHECK(x[0] == Interval(1,2)); CHECK(x[1] == Interval(3,4)); @@ -239,8 +239,8 @@ TEST_CASE("IntervalVector") CHECK(!IntervalVector({{0,1},{2,3},{4,5}}).is_flat()); CHECK(IntervalVector::empty(3).is_flat()); - CHECK(IntervalVector(1,Interval(0,0)).is_flat()); - CHECK(!IntervalVector(1,Interval(0,1)).is_flat()); + CHECK(IntervalVector({{0,0}}).is_flat()); + CHECK(!IntervalVector({{0,1}}).is_flat()); CHECK(IntervalVector({{0,1},{2,2},{3,4}}).is_flat()); CHECK(IntervalVector({{0,1},{2,3},{4,4}}).is_flat()); CHECK(!IntervalVector::empty(3).is_unbounded()); diff --git a/tests/core/domains/interval/codac2_tests_IntervalVector.py b/tests/core/domains/interval/codac2_tests_IntervalVector.py index 218b57d3..93a3851b 100644 --- a/tests/core/domains/interval/codac2_tests_IntervalVector.py +++ b/tests/core/domains/interval/codac2_tests_IntervalVector.py @@ -8,7 +8,7 @@ # # ---------------------------------------------------------------------------- # \date 2024 -# \author Gilles Chabert, (Simon Rohou) +# \author Gilles Chabert, Simon Rohou # \copyright Copyright 2024 Codac Team # \license GNU Lesser General Public License (LGPL) @@ -27,10 +27,10 @@ def CHECK_diff(self, x, y, compactness, result): if not c: return not result - + for ci in c: found = False - for i in range(0,result_.nb_rows()): + for i in range(0,result_.rows()): if IntervalMatrix(ci).transpose() == IntervalMatrix(result_.row(i)): found = True break @@ -50,7 +50,7 @@ def tests_intervalvector(self): x = IntervalVector(2) x[0] = Interval(0,1) x[1] = Interval(0,1) - self.assertTrue(x == IntervalVector(2,Interval(0,1))) + self.assertTrue(x == IntervalVector([[0,1],[0,1]])) self.assertTrue(x == IntervalVector(x)) #self.assertTrue(x == (IntervalVector(2)=x)) @@ -92,7 +92,7 @@ def tests_intervalvector(self): x = IntervalVector(1) x[0] = Interval(1,2) - x.resize(3) + x.resize_save_values(3) self.assertTrue(x.size() == 3) self.assertTrue(x[0] == Interval(1,2)) self.assertTrue(x[1] == Interval(-oo,oo)) @@ -100,14 +100,14 @@ def tests_intervalvector(self): x = IntervalVector(1) x[0] = Interval(1,2) - x.resize(1) + x.resize_save_values(1) self.assertTrue(x.size() == 1) self.assertTrue(x[0] == Interval(1,2)) x = IntervalVector(2) x[0] = Interval(1,2) x.set_empty() - x.resize(3) + x.resize_save_values(3) self.assertTrue(x.size() == 3) self.assertTrue(x.is_empty()) self.assertTrue(x[2] == Interval(-oo,oo)) @@ -115,7 +115,7 @@ def tests_intervalvector(self): x = IntervalVector(5) x[0] = Interval(1,2) x[1] = Interval(3,4) - x.resize(2) + x.resize_save_values(2) self.assertTrue(x.size() == 2) self.assertTrue(x[0] == Interval(1,2)) self.assertTrue(x[1] == Interval(3,4)) @@ -219,8 +219,8 @@ def tests_intervalvector(self): self.assertTrue(not IntervalVector([[0,1],[2,3],[4,5]]).is_flat()) self.assertTrue(IntervalVector.empty(3).is_flat()) - self.assertTrue(IntervalVector(1,Interval(0,0)).is_flat()) - self.assertTrue(not IntervalVector(1,Interval(0,1)).is_flat()) + self.assertTrue(IntervalVector([[0,0]]).is_flat()) + self.assertTrue(not IntervalVector([[0,1]]).is_flat()) self.assertTrue(IntervalVector([[0,1],[2,2],[3,4]]).is_flat()) self.assertTrue(IntervalVector([[0,1],[2,3],[4,4]]).is_flat()) self.assertTrue(not IntervalVector.empty(3).is_unbounded()) diff --git a/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp b/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp index 92453556..4f2715c7 100644 --- a/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp +++ b/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp @@ -16,12 +16,13 @@ #include #include #include +#include #include using namespace std; using namespace codac2; -#define PI 3.1415926535897932384626433832795028L // todo: use std::numbers::pi with C++20 +#define PI codac2::pi const double MAX_DOUBLE = std::numeric_limits::max(); @@ -365,9 +366,9 @@ TEST_CASE("bwd mul operations") A(1,0) = deltaM; A(1,1) = 1+deltaM; - Vector b(2,1.0); + Vector b({1,1}); - IntervalVector x(2,Interval(-10,10)); + IntervalVector x({{-10,10},{-10,10}}); double _M[16]={1+delta, 0, 0, delta, 0, 1-delta, 0, -delta, @@ -376,13 +377,13 @@ TEST_CASE("bwd mul operations") Matrix M(4,4,_M); Matrix invM = M.inverse(); - Vector b2(4,1.0); + Vector b2 = Vector::ones(4); Vector bounds = invM * b2; - double _x2[2][2]={ {bounds[0],bounds[1]}, {bounds[2],bounds[3]} }; - IntervalVector x2(2,_x2); - - MulOp::bwd(b,A,x); - - cout << x << endl; - cout << x2 << endl; + //double _x2[][2]={ {bounds[0],bounds[1]}, {bounds[2],bounds[3]} }; + //IntervalVector x2(_x2,(size_t)2); + // + //MulOp::bwd(b,A,x); + // + //cout << x << endl; + //cout << x2 << endl; } \ No newline at end of file diff --git a/tests/core/domains/interval/codac2_tests_Interval_operations.cpp b/tests/core/domains/interval/codac2_tests_Interval_operations.cpp index ea3738f8..9f99d2fa 100644 --- a/tests/core/domains/interval/codac2_tests_Interval_operations.cpp +++ b/tests/core/domains/interval/codac2_tests_Interval_operations.cpp @@ -7,7 +7,7 @@ * * ---------------------------------------------------------------------------- * \date 2024 - * \author Gilles Chabert, (Simon Rohou) + * \author Gilles Chabert, Simon Rohou * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ diff --git a/tests/core/domains/interval/codac2_tests_Interval_operations.py b/tests/core/domains/interval/codac2_tests_Interval_operations.py index f06e85bb..a091ba25 100644 --- a/tests/core/domains/interval/codac2_tests_Interval_operations.py +++ b/tests/core/domains/interval/codac2_tests_Interval_operations.py @@ -8,7 +8,7 @@ # # ---------------------------------------------------------------------------- # \date 2024 -# \author Gilles Chabert, (Simon Rohou) +# \author Gilles Chabert, Simon Rohou # \copyright Copyright 2024 Codac Team # \license GNU Lesser General Public License (LGPL) diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp index 45b4b82a..cc09983c 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp @@ -71,7 +71,7 @@ TEST_CASE("AnalyticFunction") AnalyticFunction f({x}, vec(x,x)); AnalyticFunction fvec({x}, vec(x,x)); - CHECK(Approx(f.eval(m, 1)) == IntervalVector({{1},{1}})); + CHECK(Approx(f.eval(m, 1)) == IntervalVector({1,1})); } { @@ -112,7 +112,7 @@ TEST_CASE("AnalyticFunction") // .def("__rmul__", {}(const ScalarVar& e1, const Interval& e2); CHECK(AnalyticFunction({x1}, Interval(6.)*x1).eval(m, 5.) == 30.); // .def("__mul__", {}(const ScalarVar& e1, const VectorVar& e2); - CHECK(AnalyticFunction({v1,v2}, v1[0]*v2).eval(m, Vector({5.,10.}),IntervalVector(2,3.)) == Vector(2,15.)); + CHECK(AnalyticFunction({v1,v2}, v1[0]*v2).eval(m, Vector({5.,10.}),IntervalVector({3,3})) == Vector({15,15})); // .def("__mul__", {}(const ScalarVar& e1, const IntervalVector& e2); CHECK(AnalyticFunction({x1}, x1*IntervalVector({{-2,3},{0,1}})).centered_eval(5.) == IntervalVector({{-10,15},{0,5}})); // .def("__truediv__", {}(const ScalarVar& e1, const ScalarVar& e2); @@ -123,23 +123,24 @@ TEST_CASE("AnalyticFunction") CHECK(Approx(AnalyticFunction({x1}, Interval(2.)/x1).eval(m, 10.)) == 0.2); // ======> VectorVar + CHECK(-IntervalVector({-5.,-6.}) == Vector({5.,6.})); //.def("__pos__", {}(const VectorVar& e1); CHECK(AnalyticFunction({v1}, +v1).eval(m, Vector({5.,6.})) == Vector({5.,6.})); //.def("__add__", {}(const VectorVar& e1, const VectorVar& e2); CHECK(AnalyticFunction({v1,v2}, v1+v2).eval(m, Vector({5.,6.}),Vector({2.,3.})) == Vector({7.,9.})); //.def("__add__", {}(const VectorVar& e1, const IntervalVector& e2); - CHECK(AnalyticFunction({v1}, v1+IntervalVector({{2},{3}})).eval(m, Vector({5.,6.})) == IntervalVector({{7.},{9.}})); + CHECK(AnalyticFunction({v1}, v1+IntervalVector({2,3})).eval(m, Vector({5.,6.})) == IntervalVector({7.,9.})); //.def("__radd__", {}(const VectorVar& e1, const IntervalVector& e2); - CHECK(AnalyticFunction({v1}, IntervalVector({{2},{3}})+v1).eval(m, Vector({5.,6.})) == IntervalVector({{7.},{9.}})); + CHECK(AnalyticFunction({v1}, IntervalVector({2,3})+v1).eval(m, Vector({5.,6.})) == IntervalVector({7.,9.})); //.def("__neg__", {}(const VectorVar& e1); CHECK(AnalyticFunction({v1}, -v1).eval(m, Vector({5.,6.})) == -Vector({5.,6.})); //.def("__sub__", {}(const VectorVar& e1, const VectorVar& e2); CHECK(AnalyticFunction({v1,v2}, v1-v2).eval(m, Vector({5.,6.}),Vector({2.,3.})) == Vector({3.,3.})); //.def("__sub__", {}(const VectorVar& e1, const IntervalVector& e2); - CHECK(AnalyticFunction({v1}, v1-IntervalVector({{2},{3}})).eval(m, Vector({5.,6.})) == IntervalVector({{3.},{3.}})); + CHECK(AnalyticFunction({v1}, v1-IntervalVector({2,3})).eval(m, Vector({5.,6.})) == IntervalVector({3.,3.})); //.def("__rsub__", {}(const VectorVar& e1, const IntervalVector& e2); - CHECK(AnalyticFunction({v1}, IntervalVector({{2},{3}})-v1).eval(m, Vector({5.,6.})) == IntervalVector({{-3.},{-3.}})); + CHECK(AnalyticFunction({v1}, IntervalVector({2,3})-v1).eval(m, Vector({5.,6.})) == IntervalVector({-3.,-3.})); // ======> ScalarExpr @@ -178,7 +179,7 @@ TEST_CASE("AnalyticFunction") //.def("__rmul__", {}(const ScalarExpr& e1, const Interval& e2); CHECK(Approx(AnalyticFunction({x1}, Interval(10.)*cos(x1)).eval(m, codac2::pi),1e-9) == -10); //.def("__mul__", {}(const ScalarExpr& e1, const VectorExpr& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({codac2::pi,-1}),Vector({2,3})),1e-9) == IntervalVector({{-4},{-6}})); + CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({codac2::pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); //.def("__truediv__", {}(const ScalarExpr& e1, const ScalarExpr& e2); CHECK(Approx(AnalyticFunction({x1}, cos(x1)/cos(x1)).eval(m, Interval(0.))) == Interval(1.)); //.def("__truediv__", {}(const ScalarExpr& e1, const ScalarVar& e2); @@ -208,75 +209,75 @@ TEST_CASE("AnalyticFunction") CHECK(Approx(AnalyticFunction({v1}, -(v1+v1)).eval(m, IntervalVector({{0.},{-oo,5}}))) == (m == EvaluationMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-10,oo}}))); //.def(py::self - py::self); - CHECK(Approx(AnalyticFunction({v1,v2}, (v1-v2)).eval(m, IntervalVector({{2},{3}}),Vector({1,5}))) == IntervalVector({{1},{-2}})); + CHECK(Approx(AnalyticFunction({v1,v2}, (v1-v2)).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({1,-2})); //.def("__sub__", {}(const VectorExpr& e1, const VectorVar& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, (v1-v2)-v1).eval(m, IntervalVector({{2},{3}}),Vector({1,5}))) == IntervalVector({{-1},{-5}})); + CHECK(Approx(AnalyticFunction({v1,v2}, (v1-v2)-v1).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({-1,-5})); //.def("__rsub__", {}(const VectorExpr& e1, const VectorVar& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, v2-(v1-v2)).eval(m, IntervalVector({{2},{3}}),Vector({1,5}))) == IntervalVector({{0},{7}})); + CHECK(Approx(AnalyticFunction({v1,v2}, v2-(v1-v2)).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({0,7})); //.def("__sub__", {}(const VectorExpr& e1, const IntervalVector& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, (v1-v2)-IntervalVector({{2},{3}})).eval(m, IntervalVector({{2},{3}}),Vector({1,5}))) == IntervalVector({{-1},{-5}})); + CHECK(Approx(AnalyticFunction({v1,v2}, (v1-v2)-IntervalVector({2,3})).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({-1,-5})); //.def("__rsub__", {}(const VectorExpr& e1, const IntervalVector& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, Vector({1,5})-(v1-v2)).eval(m, IntervalVector({{2},{3}}),Vector({1,5}))) == IntervalVector({{0},{7}})); + CHECK(Approx(AnalyticFunction({v1,v2}, Vector({1,5})-(v1-v2)).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({0,7})); //.def("__rmul__", {}(const VectorExpr& e1, const ScalarExpr& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({codac2::pi,-1}),Vector({2,3})),1e-9) == IntervalVector({{-4},{-6}})); + CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({codac2::pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); //.def("__rmul__", {}(const VectorExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1*vec(3*x1,2*x1)).eval(m, 3),1e-9) == IntervalVector({{27},{18}})); + CHECK(Approx(AnalyticFunction({x1}, x1*vec(3*x1,2*x1)).eval(m, 3),1e-9) == IntervalVector({27,18})); } } - { - VectorVar x(2); - AnalyticFunction f({x}, x[0]*(x[0]+x[1])+sqr(x[1])); - CHECK(f.diff(Vector({2,3}))(0,0) == 7); - CHECK(f.diff(Vector({2,3}))(0,1) == 8); - } + { + VectorVar x(2); + AnalyticFunction f({x}, x[0]*(x[0]+x[1])+sqr(x[1])); + CHECK(f.diff(Vector({2,3}))(0,0) == 7); + CHECK(f.diff(Vector({2,3}))(0,1) == 8); + } - { // int values - ScalarVar x, y; - AnalyticFunction f({x,y}, x*(x+y)+sqr(y)); - CHECK(f.diff(2,3)(0,0) == 7); - CHECK(f.diff(2,3)(0,1) == 8); - } + { // int values + ScalarVar x, y; + AnalyticFunction f({x,y}, x*(x+y)+sqr(y)); + CHECK(f.diff(2,3)(0,0) == 7); + CHECK(f.diff(2,3)(0,1) == 8); + } - { // double values - ScalarVar x, y; - AnalyticFunction f({x,y}, x*(x+y)+sqr(y)); - CHECK(f.diff(2.,3.)(0,0) == 7); - CHECK(f.diff(2.,3.)(0,1) == 8); - } + { // double values + ScalarVar x, y; + AnalyticFunction f({x,y}, x*(x+y)+sqr(y)); + CHECK(f.diff(2.,3.)(0,0) == 7); + CHECK(f.diff(2.,3.)(0,1) == 8); + } - { // Interval values - ScalarVar x, y; - AnalyticFunction f({x,y}, x*(x+y)+sqr(y)); - CHECK(f.diff(Interval(2.),Interval(3.))(0,0) == 7); - CHECK(f.diff(Interval(2.),Interval(3.))(0,1) == 8); - } + { // Interval values + ScalarVar x, y; + AnalyticFunction f({x,y}, x*(x+y)+sqr(y)); + CHECK(f.diff(Interval(2.),Interval(3.))(0,0) == 7); + CHECK(f.diff(Interval(2.),Interval(3.))(0,1) == 8); + } - { - ScalarVar x; - AnalyticFunction f({x}, x-x); - CHECK(f.natural_eval(Interval(-1,1)) == Interval(-2,2)); - CHECK(f.centered_eval(Interval(-1,1)) == Interval(0)); - CHECK(f.eval(Interval(-1,1)) == Interval(0)); - } + { + ScalarVar x; + AnalyticFunction f({x}, x-x); + CHECK(f.natural_eval(Interval(-1,1)) == Interval(-2,2)); + CHECK(f.centered_eval(Interval(-1,1)) == Interval(0)); + CHECK(f.eval(Interval(-1,1)) == Interval(0)); + } - // Subvector on variables - { - VectorVar p(2); - VectorVar x(4); - AnalyticFunction f({p}, p[0]*p[1]); - AnalyticFunction g({x}, f(x.subvector(0,1)) + f(x.subvector(2,3))); + // Subvector on variables + { + VectorVar p(2); + VectorVar x(4); + AnalyticFunction f({p}, p[0]*p[1]); + AnalyticFunction g({x}, f(x.subvector(0,1)) + f(x.subvector(2,3))); - IntervalVector a(4); + IntervalVector a(4); - a = IntervalVector({{1},{2},{3},{4}}); - CHECK(g.natural_eval(a) == 14); - CHECK(g.centered_eval(a) == 14); - CHECK(g.eval(a) == 14); + a = IntervalVector({1,2,3,4}); + CHECK(g.natural_eval(a) == 14); + CHECK(g.centered_eval(a) == 14); + CHECK(g.eval(a) == 14); - a = IntervalVector({{0},{2},{5},{4}}); - CHECK(g.natural_eval(a) == 20); - CHECK(g.centered_eval(a) == 20); - CHECK(g.eval(a) == 20); - } + a = IntervalVector({0,2,5,4}); + CHECK(g.natural_eval(a) == 20); + CHECK(g.centered_eval(a) == 20); + CHECK(g.eval(a) == 20); + } } \ No newline at end of file diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py index 3ffeb800..2dc92337 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py @@ -96,7 +96,7 @@ def test_eval(f,*args): # .def("__rmul__", [](const ScalarVar& e1, const Interval& e2) self.assertTrue(test_eval(AnalyticFunction([x1], Interval(6.)*x1), 5.) == 30.) # .def("__mul__", [](const ScalarVar& e1, const VectorVar& e2) - self.assertTrue(test_eval(AnalyticFunction([v1,v2], v1[0]*v2), Vector([5.,10.]),IntervalVector(2,3.)) == Vector(2,15.)) + self.assertTrue(test_eval(AnalyticFunction([v1,v2], v1[0]*v2), Vector([5.,10.]),IntervalVector([[3],[3]])) == Vector([15,15])) # .def("__mul__", [](const ScalarVar& e1, const IntervalVector& e2) self.assertTrue(test_eval(AnalyticFunction([x1], x1*IntervalVector([[-2,3],[0,1]])), 5.) == IntervalVector([[-10,15],[0,5]])) # .def("__truediv__", [](const ScalarVar& e1, const ScalarVar& e2) diff --git a/tests/core/matrices/codac2_tests_Inversion.cpp b/tests/core/matrices/codac2_tests_Inversion.cpp new file mode 100644 index 00000000..26eb6b47 --- /dev/null +++ b/tests/core/matrices/codac2_tests_Inversion.cpp @@ -0,0 +1,54 @@ +/** + * Codac tests + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Damien Massé + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace codac2; + +TEST_CASE("Matrix") +{ + IntervalMatrix x({ + { {0.0,0.0}, {-0.1,-0.1}, {0.2,0.2} }, + { {0.0,0.0}, {-0.2,-0.2}, {0.1,0.1} }, + { {0.1,0.1}, {-0.1,-0.1}, {0.1,0.1} } + }); + + double a=0.0; + + IntervalMatrix y = infinite_sum_enclosure(x,a); + CHECK(Approx(Interval(a))==Interval(5.0)/Interval(2.0)); + + IntervalMatrix z = inverse_enclosure(x); + CHECK(z(1,2)==Interval(0)); + CHECK(Approx(z*x)==IntervalMatrix::Identity(3,3)); + + Matrix u( { + { 1,2,3 }, + { 1,3,5 }, + { 3,4,5 } + }); + + IntervalMatrix v=inverse_enclosure(u); + CHECK((u.template cast()*v).contains(Matrix::Identity(3,3))); + + Matrix w({ + { 1, 2, 0 }, + { 3, 4, 1 }, + { 0, 1, 0 }, + }); + + y = inverse_enclosure(w); + CHECK((w.template cast()*y).contains(Matrix::Identity(3,3))); +} diff --git a/tests/core/matrices/codac2_tests_Inversion.py b/tests/core/matrices/codac2_tests_Inversion.py new file mode 100644 index 00000000..eabad434 --- /dev/null +++ b/tests/core/matrices/codac2_tests_Inversion.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +# Codac tests +# ---------------------------------------------------------------------------- +# \date 2024 +# \author Damien Massé +# \copyright Copyright 2024 Codac Team +# \license GNU Lesser General Public License (LGPL) + + +import unittest +from codac import * + +class TestInversion(unittest.TestCase): + + def tests_Inversion_1(self): + + x = Matrix([ + [ 1, 2, 0 ], + [ 3, 4, 1 ], + [ 0, 1, 0 ], + ]) + + y = inverse_enclosure(x) + self.assertTrue((x*y).contains(Matrix.eye(3,3))) + + + def tests_Inversion_2(self): + + x = IntervalMatrix([ + [ [0.0,0.0], [-0.1,-0.1], [0.2,0.2] ], + [ [0.0,0.0], [-0.2,-0.2], [0.1,0.1] ], + [ [0.1,0.1], [-0.1,-0.1], [0.1,0.1] ] + ]) + + y = infinite_sum_enclosure(x) + #self.assertTrue(Approx(y.max_rad())==Interval(5.0)/Interval(2.0)) + + z = inverse_enclosure(x) + self.assertTrue(z(1,2)==Interval(0)) + self.assertTrue(Approx(z*x)==IntervalMatrix.eye(3,3)) + + + def tests_Inversion_3(self): + + u = Matrix([ + [ 1,2,3 ], + [ 1,3,5 ], + [ 3,4,5 ] + ]) + + v = inverse_enclosure(u) + self.assertTrue((u*v).contains(Matrix.eye(3,3))) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/core/matrices/codac2_tests_Matrix.cpp b/tests/core/matrices/codac2_tests_Matrix.cpp index 8d1a9704..b4f4f65d 100644 --- a/tests/core/matrices/codac2_tests_Matrix.cpp +++ b/tests/core/matrices/codac2_tests_Matrix.cpp @@ -10,7 +10,6 @@ #include #include #include -#include using namespace std; using namespace codac2; diff --git a/tests/core/matrices/codac2_tests_Vector.cpp b/tests/core/matrices/codac2_tests_Vector.cpp index 0be891f5..c34abe0a 100644 --- a/tests/core/matrices/codac2_tests_Vector.cpp +++ b/tests/core/matrices/codac2_tests_Vector.cpp @@ -9,12 +9,15 @@ #include #include -#include using namespace std; using namespace codac2; TEST_CASE("Vector") { - + size_t i = 0; + Vector a(3), b {{-1},{2},{-3}}; + for(const auto& bi : b) + a[i++] = bi; + CHECK(a == b); } \ No newline at end of file diff --git a/tests/core/matrices/codac2_tests_Vector.py b/tests/core/matrices/codac2_tests_Vector.py index eb85f873..c6a27a46 100644 --- a/tests/core/matrices/codac2_tests_Vector.py +++ b/tests/core/matrices/codac2_tests_Vector.py @@ -20,7 +20,7 @@ def tests_Vector(self): def tests_vector_specific_to_python(self): x = Vector([1,2,3]) - y = Vector.zeros(3) + y = Vector.zero(3) i = 0 for xi in x: # using __iter__ diff --git a/tests/core/matrices/codac2_tests_arithmetic_add.cpp b/tests/core/matrices/codac2_tests_arithmetic_add.cpp index aede6ceb..d9df0c02 100644 --- a/tests/core/matrices/codac2_tests_arithmetic_add.cpp +++ b/tests/core/matrices/codac2_tests_arithmetic_add.cpp @@ -8,9 +8,10 @@ */ #include +#include +#include #include #include -#include using namespace std; using namespace codac2; @@ -39,7 +40,7 @@ TEST_CASE("arithmetic add") CHECK(IntervalVector({{-1,1},{-2,2},{-3,3}})+Vector({1,2,3}) == IntervalVector({{0,2},{0,4},{0,6}})); // inline IntervalVector operator+(const IntervalVector& x1, const IntervalVector& x2) - CHECK(IntervalVector({{-1,1},{-2,2},{-3,3}})+IntervalVector({{1},{2},{3}}) == IntervalVector({{0,2},{0,4},{0,6}})); + CHECK(IntervalVector({{-1,1},{-2,2},{-3,3}})+IntervalVector({1,2,3}) == IntervalVector({{0,2},{0,4},{0,6}})); // IntervalMatrix operator+(const IM& x1, const M& x2) CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}})+Matrix({{1,2},{3,4}}) == IntervalMatrix({{{0,2},{0,4}},{{0,6},{0,8}}})); diff --git a/tests/core/matrices/codac2_tests_arithmetic_div.cpp b/tests/core/matrices/codac2_tests_arithmetic_div.cpp index cd8756ae..4eaf1372 100644 --- a/tests/core/matrices/codac2_tests_arithmetic_div.cpp +++ b/tests/core/matrices/codac2_tests_arithmetic_div.cpp @@ -8,9 +8,10 @@ */ #include +#include +#include #include #include -#include #include using namespace std; @@ -19,30 +20,30 @@ using namespace codac2; TEST_CASE("arithmetic div") { //inline Vector operator/(const Vector& x1, double x2) - CHECK(Approx(Vector({1,2,3})/10.) == Vector({.1,.2,.3})); + CHECK(Approx(Vector({1,2,3})/10.) == Vector({.1,.2,.3})); //inline IntervalVector operator/(const Vector& x1, const Interval& x2) - CHECK(Approx(Vector({1,2,3})/Interval(10.,oo)) == IntervalVector({{0,.1},{0,.2},{0,.3}})); + CHECK(Approx(Vector({1,2,3})/Interval(10.,oo)) == IntervalVector({{0,.1},{0,.2},{0,.3}})); //Matrix operator/(const M& x1, double x2) - CHECK(Approx(Matrix({{1,2},{3,4}})/10.) == Matrix({{.1,.2},{.3,.4}})); - CHECK(Approx(Matrix({{1,2},{3,4}}).block(0,0,2,2)/10.) == Matrix({{.1,.2},{.3,.4}})); + CHECK(Approx(Matrix({{1,2},{3,4}})/10.) == Matrix({{.1,.2},{.3,.4}})); + CHECK(Approx(Matrix({{1,2},{3,4}}).block(0,0,2,2)/10.) == Matrix({{.1,.2},{.3,.4}})); //IntervalMatrix operator/(const M& x1, const Interval& x2) - CHECK(Approx(Matrix({{1,2},{3,4}})/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); - CHECK(Approx(Matrix({{1,2},{3,4}}).block(0,0,2,2)/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); + CHECK(Approx(Matrix({{1,2},{3,4}})/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); + CHECK(Approx(Matrix({{1,2},{3,4}}).block(0,0,2,2)/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); //inline IntervalVector operator/(const IntervalVector& x1, double x2) - CHECK(Approx(IntervalVector({{1},{2},{3}})/10.) == IntervalVector({{.1},{.2},{.3}})); + CHECK(Approx(IntervalVector({1,2,3})/10.) == IntervalVector({0.1,0.2,0.3})); //inline IntervalVector operator/(const IntervalVector& x1, const Interval& x2) - CHECK(Approx(IntervalVector({{1},{2},{3}})/Interval(10.,oo)) == IntervalVector({{0,.1},{0,.2},{0,.3}})); + CHECK(Approx(IntervalVector({1,2,3})/Interval(10.,oo)) == IntervalVector({{0,.1},{0,.2},{0,.3}})); //IntervalMatrix operator/(const IM& x1, double x2) - CHECK(Approx(IntervalMatrix({{{1},{2}},{{3},{4}}})/10.) == IntervalMatrix({{{.1},{.2}},{{.3},{.4}}})); - CHECK(Approx(IntervalMatrix({{{1},{2}},{{3},{4}}}).block(0,0,2,2)/10.) == IntervalMatrix({{{.1},{.2}},{{.3},{.4}}})); + CHECK(Approx(IntervalMatrix({{1,2},{3,4}})/10.) == IntervalMatrix({{.1,.2},{.3,.4}})); + CHECK(Approx(IntervalMatrix({{1,2},{3,4}}).block(0,0,2,2)/10.) == IntervalMatrix({{.1,.2},{.3,.4}})); //IntervalMatrix operator/(const IM& x1, const Interval& x2) - CHECK(Approx(IntervalMatrix({{{1},{2}},{{3},{4}}})/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); - CHECK(Approx(IntervalMatrix({{{1},{2}},{{3},{4}}}).block(0,0,2,2)/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); + CHECK(Approx(IntervalMatrix({{1,2},{3,4}})/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); + CHECK(Approx(IntervalMatrix({{1,2},{3,4}}).block(0,0,2,2)/Interval(10.,oo)) == IntervalMatrix({{{0,.1},{0,.2}},{{0,.3},{0,.4}}})); } \ No newline at end of file diff --git a/tests/core/matrices/codac2_tests_arithmetic_mul.cpp b/tests/core/matrices/codac2_tests_arithmetic_mul.cpp index d75ad854..b2a84113 100644 --- a/tests/core/matrices/codac2_tests_arithmetic_mul.cpp +++ b/tests/core/matrices/codac2_tests_arithmetic_mul.cpp @@ -8,9 +8,10 @@ */ #include +#include +#include #include #include -#include using namespace std; using namespace codac2; @@ -65,19 +66,39 @@ TEST_CASE("arithmetic mul") // Matrix operator*(const M& x1, const M_& x2) CHECK(Matrix({{1,2},{3,4}})*Matrix({{5,6},{7,8}}) == Matrix({{19,22},{43,50}})); - CHECK(Matrix({{1,2},{3,4}}).block(0,0,2,2)*Matrix({{5,6},{7,8}}) == Matrix({{19,22},{43,50}})); - CHECK(Matrix({{1,2},{3,4}})*Matrix({{5,6},{7,8}}).block(0,0,2,2) == Matrix({{19,22},{43,50}})); - CHECK(Matrix({{1,2},{3,4}}).block(0,0,2,2)*Matrix({{5,6},{7,8}}).block(0,0,2,2) == Matrix({{19,22},{43,50}})); + CHECK( + Matrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}).block(0,0,2,2))*Matrix({{5,6},{7,8}}) == Matrix({{19,22},{43,50}})); + CHECK(Matrix({{1,2},{3,4}})* + Matrix( // <--- this explicit cast should be removed + Matrix({{5,6},{7,8}}).block(0,0,2,2)) == Matrix({{19,22},{43,50}})); + CHECK( + Matrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}).block(0,0,2,2))* + Matrix( // <--- this explicit cast should be removed + Matrix({{5,6},{7,8}}).block(0,0,2,2)) == Matrix({{19,22},{43,50}})); // IntervalVector operator*(const M& x1, const IntervalVector& x2) CHECK(Matrix({{1,2},{3,4}})*IntervalVector({5,6}) == IntervalVector({17,39})); - CHECK(Matrix({{1,2},{3,4}}).block(0,0,2,2)*IntervalVector({5,6}) == IntervalVector({17,39})); + CHECK( + Matrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}).block(0,0,2,2))*IntervalVector({5,6}) == IntervalVector({17,39})); // IntervalMatrix operator*(const M& x1, const IM& x2) - CHECK(Matrix({{1,2},{3,4}})*IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); - CHECK(Matrix({{1,2},{3,4}}).block(0,0,2,2)*IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); - CHECK(Matrix({{1,2},{3,4}})*IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); - CHECK(Matrix({{1,2},{3,4}}).block(0,0,2,2)*IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); + CHECK(IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}))*IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); + CHECK( + IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}).block(0,0,2,2))*IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); + CHECK(IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}))* + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2)) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); + CHECK( + IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}).block(0,0,2,2))* + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2)) == IntervalMatrix({{{19,22},{22,25}},{{43,50},{50,57}}})); // inline IntervalVector operator*(const IntervalVector& x1, double x2) CHECK(IntervalVector({{-1,1},{-2,2}})*2. == IntervalVector({{-2,2},{-4,4}})); @@ -94,14 +115,32 @@ TEST_CASE("arithmetic mul") CHECK(IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}).block(0,0,2,2)*Interval(-1,1) == IntervalMatrix({{{-2,2},{-3,3}},{{-4,4},{-5,5}}})); // IntervalVector operator*(const IM& x1, const Vector& x2) - CHECK(IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}})*Vector({5,6}) == IntervalVector({{17,28},{39,50}})); - CHECK(IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}).block(0,0,2,2)*Vector({5,6}) == IntervalVector({{17,28},{39,50}})); + CHECK(IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}})*Vector({5,6}) + .template cast() // <--- this explicit cast should be removed + == IntervalVector({{17,28},{39,50}})); + CHECK( + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}).block(0,0,2,2))*Vector({5,6}) + .template cast() // <--- this explicit cast should be removed + == IntervalVector({{17,28},{39,50}})); // IntervalMatrix operator*(const IM& x1, const M& x2) - CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})*Matrix({{1,2},{3,4}}) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); - CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2)*Matrix({{1,2},{3,4}}) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); - CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})*Matrix({{1,2},{3,4}}).block(0,0,2,2) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); - CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2)*Matrix({{1,2},{3,4}}).block(0,0,2,2) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); + CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})* + IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}})) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); + CHECK( + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2))* + IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}})) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); + CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})* + IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}).block(0,0,2,2)) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); + CHECK( + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2))* + IntervalMatrix( // <--- this explicit cast should be removed + Matrix({{1,2},{3,4}}).block(0,0,2,2)) == IntervalMatrix({{{23,27},{34,40}},{{31,35},{46,52}}})); // IntervalVector operator*(const IM& x1, const IntervalVector& x2) CHECK(IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}})*IntervalVector({{5,6},{7,8}}) == IntervalVector({{19,36},{43,64}})); @@ -109,7 +148,13 @@ TEST_CASE("arithmetic mul") // IntervalMatrix operator*(const IM& x1, const IM_& x2) CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})*IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}) == IntervalMatrix({{{23,40},{34,53}},{{31,52},{46,69}}})); - CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2)*IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}) == IntervalMatrix({{{23,40},{34,53}},{{31,52},{46,69}}})); - CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})*IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}).block(0,0,2,2) == IntervalMatrix({{{23,40},{34,53}},{{31,52},{46,69}}})); - CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2)*IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}).block(0,0,2,2) == IntervalMatrix({{{23,40},{34,53}},{{31,52},{46,69}}})); + CHECK( + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}}).block(0,0,2,2))*IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}) == IntervalMatrix({{{23,40},{34,53}},{{31,52},{46,69}}})); + CHECK(IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})* + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}).block(0,0,2,2)) == IntervalMatrix({{{23,40},{34,53}},{{31,52},{46,69}}})); + CHECK( + IntervalMatrix( // <--- this explicit cast should be removed + IntervalMatrix({{{5,6},{6,7}},{{7,8},{8,9}}})).block(0,0,2,2)*IntervalMatrix({{{1,2},{2,3}},{{3,4},{4,5}}}).block(0,0,2,2) == IntervalMatrix({{{23,40},{34,53}},{{31,52},{46,69}}})); } \ No newline at end of file diff --git a/tests/core/matrices/codac2_tests_arithmetic_sub.cpp b/tests/core/matrices/codac2_tests_arithmetic_sub.cpp index fa4ff0bf..7d125a1e 100644 --- a/tests/core/matrices/codac2_tests_arithmetic_sub.cpp +++ b/tests/core/matrices/codac2_tests_arithmetic_sub.cpp @@ -8,9 +8,10 @@ */ #include +#include +#include #include #include -#include using namespace std; using namespace codac2; @@ -39,7 +40,7 @@ TEST_CASE("arithmetic sub") CHECK(IntervalVector({{-1,1},{-2,2},{-3,3}})-Vector({1,2,3}) == IntervalVector({{-2,0},{-4,0},{-6,0}})); // inline IntervalVector operator-(const IntervalVector& x1, const IntervalVector& x2) - CHECK(IntervalVector({{-1,1},{-2,2},{-3,3}})-IntervalVector({{1},{2},{3}}) == IntervalVector({{-2,0},{-4,0},{-6,0}})); + CHECK(IntervalVector({{-1,1},{-2,2},{-3,3}})-IntervalVector({1,2,3}) == IntervalVector({{-2,0},{-4,0},{-6,0}})); // IntervalMatrix operator-(const IM& x1, const M& x2) CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}})-Matrix({{1,2},{3,4}}) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); @@ -48,8 +49,8 @@ TEST_CASE("arithmetic sub") CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}}).block(0,0,2,2)-Matrix({{1,2},{3,4}}).block(0,0,2,2) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); // IntervalMatrix operator-(const IM& x1, const IM_& x2) - CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}})-IntervalMatrix({{{1},{2}},{{3},{4}}}) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); - CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}}).block(0,0,2,2)-IntervalMatrix({{{1},{2}},{{3},{4}}}) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); + CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}})-IntervalMatrix({{1,2},{3,4}}) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); + CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}}).block(0,0,2,2)-IntervalMatrix({{1,2},{3,4}}) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}})-IntervalMatrix({{{1},{2}},{{3},{4}}}).block(0,0,2,2) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); CHECK(IntervalMatrix({{{-1,1},{-2,2}},{{-3,3},{-4,4}}}).block(0,0,2,2)-IntervalMatrix({{{1},{2}},{{3},{4}}}).block(0,0,2,2) == IntervalMatrix({{{-2,0},{-4,0}},{{-6,0},{-8,0}}})); } \ No newline at end of file diff --git a/tests/core/separators/codac2_tests_SepCtcBoundary.cpp b/tests/core/separators/codac2_tests_SepCtcBoundary.cpp index 6c668c22..5244e80c 100644 --- a/tests/core/separators/codac2_tests_SepCtcBoundary.cpp +++ b/tests/core/separators/codac2_tests_SepCtcBoundary.cpp @@ -28,12 +28,12 @@ BoolInterval test_inside_diamond(const Vector& x) TEST_CASE("SepCtcBoundary") { - auto ctc_diamond = CtcSegment({{-1},{0}}, {{0},{-1}}) | CtcSegment({{0},{-1}}, {{1},{0}}) - | CtcSegment({{1},{0}}, {{0},{1}}) | CtcSegment({{0},{1}}, {{-1},{0}}); + auto ctc_bound_diamond = CtcSegment({-1,0}, {0,-1}) | CtcSegment({0,-1}, {1,0}) + | CtcSegment({1,0}, {0,1}) | CtcSegment({0,1}, {-1,0}); - SepCtcBoundary sep_diamond(ctc_diamond,test_inside_diamond); + SepCtcBoundary sep_diamond(ctc_bound_diamond,test_inside_diamond); - //pave(IntervalVector({{-2,2},{-2,2}}), sep_diamond, 0.1); + //draw_while_paving(IntervalVector({{-2,2},{-2,2}}), sep_diamond, 0.1); IntervalVector x(2); auto xs = sep_diamond.separate(IntervalVector(2)); @@ -61,5 +61,5 @@ TEST_CASE("SepCtcBoundary") //DefaultView::draw_box(xs.inner,Color::dark_green()); //DefaultView::draw_box(xs.outer,Color::blue()); CHECK(xs.inner == x); - CHECK(xs.outer == IntervalVector({{0.5},{0.5}})); + CHECK(xs.outer == IntervalVector({0.5,0.5})); } \ No newline at end of file diff --git a/tests/core/separators/codac2_tests_SepCtcBoundary.py b/tests/core/separators/codac2_tests_SepCtcBoundary.py index cb0c4c49..830ea70c 100644 --- a/tests/core/separators/codac2_tests_SepCtcBoundary.py +++ b/tests/core/separators/codac2_tests_SepCtcBoundary.py @@ -22,11 +22,11 @@ class TestSepCtcBoundary(unittest.TestCase): def tests_SepCtcBoundary(self): - ctc_diamond = CtcSegment([[-1],[0]], [[0],[-1]]) | CtcSegment([[0],[-1]], [[1],[0]]) \ + ctc_bound_diamond = CtcSegment([[-1],[0]], [[0],[-1]]) | CtcSegment([[0],[-1]], [[1],[0]]) \ | CtcSegment([[1],[0]], [[0],[1]]) | CtcSegment([[0],[1]], [[-1],[0]]) - sep_diamond = SepCtcBoundary(ctc_diamond,test_inside_diamond) - #pave(IntervalVector([[-2,2],[-2,2]]), sep_diamond, 0.1) + sep_diamond = SepCtcBoundary(ctc_bound_diamond,test_inside_diamond) + #draw_while_paving(IntervalVector([[-2,2],[-2,2]]), sep_diamond, 0.1) x = IntervalVector(2) inner,outer = sep_diamond.separate(IntervalVector(2)) diff --git a/tests/core/separators/codac2_tests_SepPolygon.cpp b/tests/core/separators/codac2_tests_SepPolygon.cpp index b78db3a2..24c20be4 100644 --- a/tests/core/separators/codac2_tests_SepPolygon.cpp +++ b/tests/core/separators/codac2_tests_SepPolygon.cpp @@ -35,24 +35,24 @@ TEST_CASE("SepPolygon - tests from Codac1") { SepPolygon s({ // external border - {{6,-6},{7,9}}, - {{7,9},{0,5}}, - {{0,5},{-9,8}}, - {{-9,8},{-8,-9}}, - {{-8,-9},{6,-6}}, + Edge({{6,-6},{7,9}}), + Edge({{7,9},{0,5}}), + Edge({{0,5},{-9,8}}), + Edge({{-9,8},{-8,-9}}), + Edge({{-8,-9},{6,-6}}), // hole - {{-2,3},{3.5,2}}, - {{3.5,2},{1.5,0.5}}, - {{1.5,0.5},{3,-4}}, - {{3,-4},{-3,-3}}, - {{-3,-3},{-2,3}} + Edge({{-2,3},{3.5,2}}), + Edge({{3.5,2},{1.5,0.5}}), + Edge({{1.5,0.5},{3,-4}}), + Edge({{3,-4},{-3,-3}}), + Edge({{-3,-3},{-2,3}}) }); //pave(IntervalVector({{-10,10},{-10,10}}), s, 0.1); // Check a box inside the hole { - IntervalVector x = IntervalVector({{0},{0}}).inflate(0.5); + IntervalVector x = IntervalVector({0,0}).inflate(0.5); //DefaultView::draw_box(x,Color::purple()); auto xs = s.separate(x); CHECK(xs.inner == x); @@ -61,7 +61,7 @@ TEST_CASE("SepPolygon - tests from Codac1") // Check a box inside the polygon { - IntervalVector x = IntervalVector({{5},{-5}}).inflate(0.5); + IntervalVector x = IntervalVector({5,-5}).inflate(0.5); //DefaultView::draw_box(x,Color::purple()); auto xs = s.separate(x); CHECK(xs.inner.is_empty()); @@ -70,7 +70,7 @@ TEST_CASE("SepPolygon - tests from Codac1") // Check a box outside the polygon { - IntervalVector x = IntervalVector({{-1},{8}}).inflate(0.5); + IntervalVector x = IntervalVector({-1,8}).inflate(0.5); //DefaultView::draw_box(x,Color::purple()); auto xs = s.separate(x); CHECK(xs.inner == x); @@ -83,7 +83,7 @@ TEST_CASE("SepPolygon - tests from Codac1") // Check a box inside the polygon { - IntervalVector x = IntervalVector({{5},{-5}}).inflate(0.5); + IntervalVector x = IntervalVector({5,-5}).inflate(0.5); auto xs = s.separate(x); CHECK(xs.inner.is_empty()); CHECK(xs.outer == x); @@ -91,7 +91,7 @@ TEST_CASE("SepPolygon - tests from Codac1") // Check a box outside the polygon { - IntervalVector x = IntervalVector({{-1},{8}}).inflate(0.5); + IntervalVector x = IntervalVector({-1,8}).inflate(0.5); auto xs = s.separate(x); CHECK(xs.inner == x); CHECK(xs.outer.is_empty()); diff --git a/tests/core/tools/codac2_tests_Approx.cpp b/tests/core/tools/codac2_tests_Approx.cpp index 16d8ceed..d5d2d129 100644 --- a/tests/core/tools/codac2_tests_Approx.cpp +++ b/tests/core/tools/codac2_tests_Approx.cpp @@ -11,7 +11,6 @@ #include #include #include -#include using namespace std; using namespace codac2; @@ -21,8 +20,7 @@ TEST_CASE("Approx") CHECK(Interval(0.1) != Interval(1.)/Interval(10.)); CHECK(Approx(Interval(0.1)) == Interval(1.)/Interval(10.)); CHECK(Interval(0.1) == Approx(Interval(1.)/Interval(10.))); - - CHECK(IntervalVector({{0.1}}) != IntervalVector({{1.}})/Interval(10.)); - CHECK(Approx(IntervalVector({{0.1}})) == IntervalVector({{1.}})/Interval(10.)); - CHECK(IntervalVector({{0.1}}) == Approx(IntervalVector({{1.}})/Interval(10.))); + CHECK(IntervalVector({0.1}) != IntervalVector({1.})/Interval(10.)); + CHECK(Approx(IntervalVector({0.1})) == IntervalVector({1.})/Interval(10.)); + CHECK(IntervalVector({0.1}) == Approx(IntervalVector({1.})/Interval(10.))); } \ No newline at end of file diff --git a/tests/graphics/styles/codac2_tests_Color.cpp b/tests/graphics/styles/codac2_tests_Color.cpp new file mode 100644 index 00000000..8ae4e0dd --- /dev/null +++ b/tests/graphics/styles/codac2_tests_Color.cpp @@ -0,0 +1,87 @@ +/** + * Codac tests + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include + +using namespace std; +using namespace codac2; + +TEST_CASE("Color") +{ + { + // Red + + std::array d_rgb{255., 0., 0.}; + std::array d_rgba{255., 0., 0., 255.}; + std::array d_hsv{0., 100., 100.}; + std::array d_hsva{0., 100., 100., 100.}; + + vector v{ + Color(d_rgb, Model::RGB), + Color(d_rgba, Model::RGB), + Color(d_hsv, Model::HSV), + Color(d_hsva, Model::HSV), + Color("#FF0000")}; + + for (const auto &c : v) + { + CHECK(Approx(c.rgb().vec(),1.) == Color({255., 0., 0.}).vec()); + CHECK(Approx(c.rgb().vec(),1.) == Color({255., 0., 0., 255.}).vec()); + CHECK(Approx(c.hsv().vec(),1.) == Color({0., 100., 100.}, Model::HSV).vec()); + CHECK(Approx(c.hsv().vec(),1.) == Color({0., 100., 100., 100.}, Model::HSV).vec()); + } + } + + { + // Pink full opacity + + float a = 255.; + std::array d_rgb{229., 128., 255.}; + std::array d_rgba{229., 128., 255., a}; + std::array d_hsv{288., 50., 100.}; + std::array d_hsva{288., 50., 100., 100.}; + + vector v{ + Color(d_rgb, Model::RGB), + Color(d_rgba, Model::RGB), + Color(d_hsv, Model::HSV), + Color(d_hsva, Model::HSV), + Color("#e580ff")}; + + for (const auto &c : v) + { + CHECK(Approx(c.rgb().vec(),1.) == Color({229., 128., 255.}).vec()); + CHECK(Approx(c.rgb().vec(),1.) == Color({229., 128., 255., a}).vec()); + CHECK(Approx(c.hsv().vec(),1.) == Color({288., 50., 100.}, Model::HSV).vec()); + CHECK(Approx(c.hsv().vec(),1.) == Color({288., 50., 100., 100.}, Model::HSV).vec()); + } + } + + { + // Pink 40% opacity + + float a = 0.4*255.; + std::array d_rgba { 229.,128.,255.,a }; + std::array d_hsva { 288.,50.,100.,40. }; + + vector v { + Color(d_rgba, Model::RGB), + Color(d_hsva, Model::HSV), + Color("#e580ff66") + }; + + for(const auto& c : v) + { + CHECK(Approx(c.rgb().vec(),1.) == Color({229.,128.,255.,a}).vec()); + CHECK(Approx(c.hsv().vec(),1.) == Color({288.,50.,100.,40.},Model::HSV).vec()); + } + } +} \ No newline at end of file diff --git a/tests/graphics/styles/codac2_tests_Color.py b/tests/graphics/styles/codac2_tests_Color.py new file mode 100644 index 00000000..bd9e4c8e --- /dev/null +++ b/tests/graphics/styles/codac2_tests_Color.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# Codac tests +# ---------------------------------------------------------------------------- +# \date 2024 +# \author Simon Rohou, Maël Godard +# \copyright Copyright 2024 Codac Team +# \license GNU Lesser General Public License (LGPL) + +import unittest +from codac import * + + +class TestColor(unittest.TestCase): + + def test_Color(self): + # Red + + d_rgb = [255, 0, 0] + d_rgba = [255, 0, 0, 255] + d_hsv = [0, 100, 100] + d_hsva = [0, 100, 100, 100] + + + colors = [ + Color(d_rgb, Model.RGB), + Color(d_rgba, Model.RGB), + Color(d_hsv, Model.HSV), + Color(d_hsva, Model.HSV), + Color("#FF0000") + ] + + for c in colors: + self.assertTrue(Approx(c.rgb().vec(), 1.0)==Color([255, 0, 0]).rgb().vec()) + self.assertTrue(Approx(c.rgb().vec(), 1.0)==Color([255, 0, 0, 255]).rgb().vec()) + self.assertTrue(Approx(c.hsv().vec(), 1.0)==Color([0, 100, 100],Model.HSV).hsv().vec()) + self.assertTrue(Approx(c.hsv().vec(), 1.0)==Color([0, 100, 100, 100],Model.HSV).hsv().vec()) + + # Pink full opacity + + d_rgb = [229,128,255] + d_rgba = [229,128,255,255] + d_hsv = [288,50,100] + d_hsva = [288,50,100,100] + + colors = [ + Color(d_rgb, Model.RGB), + Color(d_rgba, Model.RGB), + Color(d_hsv, Model.HSV), + Color(d_hsva, Model.HSV), + Color("#E580FF") + ] + + for c in colors: + self.assertTrue(Approx(c.rgb().vec(), 1.0)==Color([229,128,255]).rgb().vec()) + self.assertTrue(Approx(c.rgb().vec(), 1.0)==Color([229,128,255,255]).rgb().vec()) + self.assertTrue(Approx(c.hsv().vec(), 1.0)==Color([288,50,100],Model.HSV).hsv().vec()) + self.assertTrue(Approx(c.hsv().vec(), 1.0)==Color([288,50,100,100],Model.HSV).hsv().vec()) + + # Pink 40% opacity + + a_rgb=102 + a_hsv=40 + d_rgba = [229,128,255,a_rgb] + d_hsva = [288,50,100,a_hsv] + + + colors = [ + Color(d_rgba, Model.RGB), + Color(d_hsva, Model.HSV), + Color("#E580FF66") + ] + for c in colors: + self.assertTrue(Approx(c.rgb().vec(), 1.0)==Color([229,128,255,a_rgb]).rgb().vec()) + self.assertTrue(Approx(c.hsv().vec(), 1.0)==Color([288,50,100,a_hsv],Model.HSV).hsv().vec()) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/test_codac/CMakeLists.txt b/tests/test_codac/CMakeLists.txt index e65acc82..8841c252 100644 --- a/tests/test_codac/CMakeLists.txt +++ b/tests/test_codac/CMakeLists.txt @@ -19,16 +19,6 @@ ibex_init_common() # IBEX should have installed this function message(STATUS "Found IBEX version ${IBEX_VERSION}") -# Adding Eigen3 - - # In case you installed Eigen3 in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option, e.g. - # set(CMAKE_PREFIX_PATH "~/eigen/build_install") - set(CMAKE_PREFIX_PATH "../eigen") - - find_package(Eigen3 3.4 REQUIRED NO_MODULE) - message(STATUS "Found Eigen3 version ${Eigen3_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -44,4 +34,4 @@ add_executable(${PROJECT_NAME} main.cpp) target_compile_options(${PROJECT_NAME} PUBLIC ${CODAC_CXX_FLAGS}) target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CODAC_INCLUDE_DIRS}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex Eigen3::Eigen) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file