diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index d35535996..9c5bb18f7 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -31,7 +31,7 @@ jobs: - { os: windows-11-vs2026-arm, shell: cmd , arch: arm64 , bitness: 64, runtime: vc18 , cmake_params: '-G "Visual Studio 18" -T v145 -A arm64', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2026 arm64' } - { os: windows-2025-vs2026 , shell: cmd , arch: x64 , bitness: 64, runtime: vc18 , cmake_params: '-G "Visual Studio 18" -T v145 -A x64' , cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2026 x64' } - { os: windows-2025-vs2026 , shell: cmd , arch: x86 , bitness: 32, runtime: vc18 , cmake_params: '-G "Visual Studio 18" -T v145 -A Win32', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2026 x86' } - - { os: windows-11-arm , shell: cmd , arch: arm64 , bitness: 64, runtime: vc17 , cmake_params: '-G "Visual Studio 17" -T v143 -A arm64', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2022 arm64' } + - { os: windows-11-arm , shell: cmd , arch: arm64 , bitness: 64, runtime: vc17 , cmake_params: '-G "Visual Studio 18 2026" -T v143 -A arm64', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2026 arm64 (v143)' } - { os: windows-2022 , shell: cmd , arch: x64 , bitness: 64, runtime: vc17 , cmake_params: '-G "Visual Studio 17" -T v143 -A x64' , cmake_flags: ' /MP4 /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: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2022 x86' } # Problems related to C++20 for Visual Studio 2019 and earlier? diff --git a/.github/workflows/vcmatrix.yml b/.github/workflows/vcmatrix.yml index 27ac4fd0c..e7997f6d3 100644 --- a/.github/workflows/vcmatrix.yml +++ b/.github/workflows/vcmatrix.yml @@ -26,10 +26,10 @@ jobs: - { 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-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 17" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 14, desc: 'Windows Visual Studio 2022 arm64 Python 3.14' } - - { os: windows-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 17" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 13, desc: 'Windows Visual Studio 2022 arm64 Python 3.13' } - - { os: windows-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 17" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 12, desc: 'Windows Visual Studio 2022 arm64 Python 3.12' } - - { os: windows-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 17" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 11, desc: 'Windows Visual Studio 2022 arm64 Python 3.11' } + - { os: windows-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 18 2026" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 14, desc: 'Windows Visual Studio 2026 arm64 Python 3.14' } + - { os: windows-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 18 2026" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 13, desc: 'Windows Visual Studio 2026 arm64 Python 3.13' } + - { os: windows-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 18 2026" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 12, desc: 'Windows Visual Studio 2026 arm64 Python 3.12' } + - { os: windows-11-arm , shell: cmd , arch: arm64 , runtime: vc17 , cmake_params: '-G "Visual Studio 18 2026" -T v143 -A arm64', cpcfg: '-win_arm64', py_v_maj: 3, py_v_min: 11, desc: 'Windows Visual Studio 2026 arm64 Python 3.11' } - { 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: 14, desc: 'Windows Visual Studio 2022 x64 Python 3.14' } - { 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' } diff --git a/.gitignore b/.gitignore index 64523ced0..d4f0b655a 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ .cproject .settings .project +.pydevproject # waf generated stuff .waf* @@ -56,6 +57,7 @@ doc/doxygen/xml/* build/ build_*/ build-*/ +CMakePresets.json # Latex files *.aux diff --git a/CMakeLists.txt b/CMakeLists.txt index f65251466..61dfcb8f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,7 +138,11 @@ message(STATUS "Found Eigen3 version ${Eigen3_VERSION} in ${Eigen3_DIR}") else() message(STATUS "Attempt to install custom Eigen3 automatically...") - FetchContent_Declare(Eigen3 URL http://github.com/codac-team/eigen/archive/refs/heads/eigen-5.0.zip) + # Over HTTPS, not plain HTTP: the connections to port 80 of github.com timed + # out now and then on the GitHub Actions runners, failing the whole job at + # configuration time ("Failed to connect to github.com port 80"), and HTTPS + # also guarantees that the archive comes from GitHub unaltered. + FetchContent_Declare(Eigen3 URL https://github.com/codac-team/eigen/archive/refs/heads/eigen-5.0.zip) #FetchContent_Declare(Eigen3 URL ${CMAKE_CURRENT_SOURCE_DIR}/3rd/eigen-a0dc3994bd5d4e804dab58decb78c56a5af516ba.zip) # If needed to be self-contained... FetchContent_MakeAvailable(Eigen3) endif() diff --git a/README.md b/README.md index b6c20bc7a..2e6b43720 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ This list is in alphabetical order by surname. - [Morgan Louédec](https://morgan-louedec.fr) - [Damien Massé](https://lab-sticc.univ-brest.fr/~dmasse) - [Bertrand Neveu](http://imagine.enpc.fr/~neveub) +- [Jordan Ninin](https://sites.google.com/site/jordanninin) - Verlein Radwan - [Andreas Rauh](https://www.interval-methods.de) - [Simon Rohou](http://simon-rohou.fr/research) diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 50cc9462f..eef4f56f0 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -149,6 +149,7 @@ This list is in alphabetical order by surname. * `Morgan Louédec `_ * `Damien Massé `_ * `Bertrand Neveu `_ + * `Jordan Ninin `_ * Verlein Radwan * `Andreas Rauh `_ * `Simon Rohou `_ diff --git a/doc/manual/manual/references/logos.rst b/doc/manual/manual/references/logos.rst index 419547286..ab7593d8d 100644 --- a/doc/manual/manual/references/logos.rst +++ b/doc/manual/manual/references/logos.rst @@ -35,11 +35,11 @@ Available Files - :download:`logo_codac_transparent.png ` * - .. image:: /_static/logos/logo_codac_transparent.svg - :alt: Codac Logo Transparent PDF + :alt: Codac Logo Transparent SVG :class: reveal-bg :width: 120px - Logo with transparent background (SVG). - - :download:`logo_codac_transparent.pdf ` + - :download:`logo_codac_transparent.svg ` * - .. image:: /_static/logos/qr_code_codac.png :alt: Codac QR Code diff --git a/python/src/core/contractors/codac2_py_CtcInverse.h b/python/src/core/contractors/codac2_py_CtcInverse.h index 46a5b5fa9..4bada2e13 100644 --- a/python/src/core/contractors/codac2_py_CtcInverse.h +++ b/python/src/core/contractors/codac2_py_CtcInverse.h @@ -81,7 +81,7 @@ void export_CtcInverse(py::module& m, }; if(xs.size() == 0) - assert_release(false && "contract() expects at least one argument"); + assert_release_unreachable("contract() expects at least one argument"); // Fast paths already consistent with the typed overloads @@ -114,7 +114,7 @@ void export_CtcInverse(py::module& m, has_tube_args = true; else { - assert_release(false && "contract(): variadic mode only supports " + assert_release_unreachable("contract(): variadic mode only supports " "Interval / IntervalVector / SlicedTube / SlicedTube"); } } diff --git a/python/src/core/trajectory/codac2_py_SampledTraj.cpp b/python/src/core/trajectory/codac2_py_SampledTraj.cpp index 546aeced3..140a657e2 100644 --- a/python/src/core/trajectory/codac2_py_SampledTraj.cpp +++ b/python/src/core/trajectory/codac2_py_SampledTraj.cpp @@ -52,7 +52,7 @@ py::class_> _export_SampledTraj(py::module& m, const string& clas exported_class .def(py::init( - [](const py::array_t& l_t, const py::array_t& l_x) + [](const py::array_t& l_t, const py::array_t& l_x) { if constexpr(std::is_same_v) { diff --git a/src/core/domains/interval/codac2_Interval_impl.h b/src/core/domains/interval/codac2_Interval_impl.h index 8e2bd0cfc..33c3120b5 100644 --- a/src/core/domains/interval/codac2_Interval_impl.h +++ b/src/core/domains/interval/codac2_Interval_impl.h @@ -75,7 +75,7 @@ namespace codac2 else { - assert_release("'Interval' can only be defined by one or two 'double' values."); + assert_release_unreachable("'Interval' can only be defined by one or two 'double' values."); } return *this; @@ -152,7 +152,7 @@ namespace codac2 inline double Interval::smag() const { - return (abs(lb()) > abs(ub())) ? lb() : ub(); + return (std::abs(lb()) > std::abs(ub())) ? lb() : ub(); } inline double Interval::smig() const diff --git a/src/core/functions/analytic/codac2_analytic_flat_input_layout.cpp b/src/core/functions/analytic/codac2_analytic_flat_input_layout.cpp index 31365483d..57352603e 100644 --- a/src/core/functions/analytic/codac2_analytic_flat_input_layout.cpp +++ b/src/core/functions/analytic/codac2_analytic_flat_input_layout.cpp @@ -55,7 +55,7 @@ namespace codac2 } else - assert_release(false && "FlatInputLayout: unsupported variable type in function argument list"); + assert_release_unreachable("FlatInputLayout: unsupported variable type in function argument list"); } _size = flat; diff --git a/src/core/geometry/codac2_Polygon.cpp b/src/core/geometry/codac2_Polygon.cpp index efdc4ec8c..a7f909549 100644 --- a/src/core/geometry/codac2_Polygon.cpp +++ b/src/core/geometry/codac2_Polygon.cpp @@ -239,8 +239,7 @@ namespace codac2 return { {p[0],prev_float(oo)}, p }; default: { - assert_release(false && - "failed to test if the point is contained in polygon"); + assert_release_unreachable("failed to test if the point is contained in polygon"); return Segment(IntervalVector(2),IntervalVector(2)); } } diff --git a/src/core/tools/codac2_assert.h b/src/core/tools/codac2_assert.h index 18d5bc891..68334785e 100644 --- a/src/core/tools/codac2_assert.h +++ b/src/core/tools/codac2_assert.h @@ -20,6 +20,7 @@ namespace codac2 #define assert_release(ignore_test) ((void)0) #define assert_release_constexpr(ignore_test) ((void)0) + #define assert_release_unreachable(ignore_msg) ((void)0) #else @@ -52,6 +53,13 @@ namespace codac2 } \ } while (0) + // For a branch that must never be reached. + // To be used instead of assert_release(false && "...") + #define assert_release_unreachable(msg) \ + do { \ + CODAC_ASSERT_MESSAGE(msg, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + } while (0) + #else #define assert_release(test) \ @@ -68,6 +76,11 @@ namespace codac2 } \ } while (0) + #define assert_release_unreachable(msg) \ + do { \ + CODAC_ASSERT_MESSAGE(msg, __FILE__, __LINE__, __func__); \ + } while (0) + #endif #endif diff --git a/src/extensions/sympy/codac2_sympy_bridge.cpp b/src/extensions/sympy/codac2_sympy_bridge.cpp index 38799f90e..1da249ac4 100644 --- a/src/extensions/sympy/codac2_sympy_bridge.cpp +++ b/src/extensions/sympy/codac2_sympy_bridge.cpp @@ -238,7 +238,7 @@ namespace codac2 continue; } - assert_release(false && "Unsupported variable type in FlatSymbolTable"); + assert_release_unreachable("Unsupported variable type in FlatSymbolTable"); } } @@ -492,7 +492,7 @@ namespace codac2 return export_matrix_component(child_at(ch,0), op->i(), op->j()); } - assert_release(false && "Unsupported Codac scalar node in SympyExporter"); + assert_release_unreachable("Unsupported Codac scalar node in SympyExporter"); return pybind11::none(); } @@ -509,8 +509,7 @@ namespace codac2 return export_node(child_at(children,i)); } - assert_release(false - && "Unsupported vector-component expression. Supported cases: direct VectorVar components, or vector expressions exposing scalar children via children_expr_base()."); + assert_release_unreachable("Unsupported vector-component expression. Supported cases: direct VectorVar components, or vector expressions exposing scalar children via children_expr_base()."); return pybind11::none(); } @@ -528,8 +527,7 @@ namespace codac2 return export_vector_component(child_at(children,j), i); } - assert_release(false - && "Unsupported matrix-component expression. Supported cases: direct MatrixVar components, or matrix expressions exposing column children via children_expr_base()."); + assert_release_unreachable("Unsupported matrix-component expression. Supported cases: direct MatrixVar components, or matrix expressions exposing column children via children_expr_base()."); return pybind11::none(); } @@ -681,7 +679,7 @@ namespace codac2 if(func.is(sympy.attr("atan2"))) return atan2(x1, x2); } - assert_release(false && "Unsupported SymPy node in importer"); + assert_release_unreachable("Unsupported SymPy node in importer"); return const_value(0.); } } diff --git a/tests/core/domains/interval/codac2_tests_Interval.cpp b/tests/core/domains/interval/codac2_tests_Interval.cpp index e98d6ca55..76c673f4f 100644 --- a/tests/core/domains/interval/codac2_tests_Interval.cpp +++ b/tests/core/domains/interval/codac2_tests_Interval.cpp @@ -16,6 +16,7 @@ #include #include #include +#include using namespace std; using namespace codac2; @@ -53,6 +54,19 @@ TEST_CASE("Interval - tests from IBEX") Interval x, y, z; + // An interval is a point or a pair of bounds; any other list length is a + // caller error and is reported through the assertion layer. A FAST_RELEASE + // build compiles that layer out, which is the one configuration where + // nothing is raised -- the guard mirrors the one in codac2_assert.h. +#if !(defined(FAST_RELEASE) && defined(NDEBUG)) + { + Interval from_list(0.,1.); + CHECK_THROWS_AS(from_list.init_from_list({1.,2.,3.}), std::invalid_argument); + CHECK_THROWS_AS(from_list.init_from_list({}), std::invalid_argument); + CHECK_THROWS_AS(Interval({1.,2.,3.}), std::invalid_argument); + } +#endif + x = Interval(0,1); x.set_empty(); CHECK(x == Interval::empty()); CHECK(x.is_empty()); diff --git a/tests/core/domains/interval/codac2_tests_Interval.py b/tests/core/domains/interval/codac2_tests_Interval.py index 9a505e469..01222b996 100644 --- a/tests/core/domains/interval/codac2_tests_Interval.py +++ b/tests/core/domains/interval/codac2_tests_Interval.py @@ -45,6 +45,21 @@ def test_interval(self): self.assertTrue(Interval([-oo,oo]) == Interval(-oo,oo)); self.assertTrue(Interval([oo,-oo]) == Interval.empty()); + # An interval is a point or a pair of bounds; any other list length is a + # caller error, reported by the C++ assertion layer as a + # std::invalid_argument, which pybind11 surfaces as a ValueError. A + # FAST_RELEASE build compiles that layer out and leaves the interval + # untouched instead; Python cannot see that switch, so both outcomes are + # accepted here and only the one that actually happened is checked. + for bad_list in ([1.,2.,3.], []): + x = Interval(0.,1.) + try: + x.init_from_list(bad_list) + except ValueError: + pass + else: + self.assertTrue(x == Interval(0.,1.)) + x = Interval() ; y = Interval() ; z = Interval() x = Interval(0,1); x.set_empty()