Skip to content

Enhance Windows compatibility and update CI configurations#212

Open
hkmoon wants to merge 187 commits intobertiniteam:developfrom
hkmoon:develop
Open

Enhance Windows compatibility and update CI configurations#212
hkmoon wants to merge 187 commits intobertiniteam:developfrom
hkmoon:develop

Conversation

@hkmoon
Copy link
Copy Markdown

@hkmoon hkmoon commented Mar 28, 2026

This pull request introduces significant improvements to the build system and release workflow for the project, especially focusing on cross-platform compatibility and automated Python package publishing. The main highlights include the addition of a comprehensive GitHub Actions workflow for building and publishing Python wheels to PyPI/TestPyPI, enhancements for Windows compatibility, and updates to documentation and changelogs to reflect these changes.

Automated Build and Release Workflow:

  • Added a new GitHub Actions workflow (.github/workflows/build-and-publish-to-pypi.yml) to automate building Python wheels for Linux, macOS, and Windows, and to publish them to PyPI, TestPyPI, and GitHub Releases. This workflow includes environment setup, dependency installation, platform-specific build steps, artifact uploading, and release signing.

Windows Compatibility Improvements:

  • Updated CMake modules (cmake/FindGMP.cmake, cmake/FindMPFR.cmake, cmake/FindMPC.cmake) to correctly locate and link against Windows-specific library filenames, improving build reliability on Windows. [1] [2] [3]
  • Modified core/CMakeLists.txt to set appropriate build flags and shared library options for MSVC, and improved Boost/Eigen3 detection and linking for cross-platform builds. [1] [2] [3] [4]

Documentation and Changelog Updates:

  • Added a detailed CHANGELOG.md documenting recent changes, release preparations, and platform-specific notes, including new contributor acknowledgments.
  • Updated the README.md with clear installation instructions for Linux, macOS, and Windows, and clarified wheel/platform support.

CMake Modernization and Refactoring:

  • Refactored the top-level CMakeLists.txt to use modern CMake practices, improved project metadata, integrated jrl-cmakemodules for streamlined dependency management, and added options for documentation and testing.
  • Temporarily disabled the addition of the python subdirectory in the build to avoid issues during the transition.

These changes collectively streamline the build, test, and release process, making it easier to maintain and distribute the package across all major platforms.

References:
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]

Check the github workflow: https://github.com/hkmoon/b2/actions/runs/23671693162

Use https://pypi.org/manage/project/pybertini/release/1.0.9/ for testing.

image

hkmoon and others added 30 commits May 6, 2025 14:03
There are some compiling errors while being compiled in windows

* `size_t` is translated into `unsigned long` in linux, mac while `unsigned long long` in windows 10: `core/include/bertini2/eigen_extensions.hpp` and `core/test/classes/start_system_test.cpp` are modified
* use `clang` of LLVM in Windows since MSVC has different compiling way for `template`
* use `--no-isolation` for `scikit-build` in Windows

For linux wheel naming convention, we cannot use x86_64, x86_i386 anymore for pypi repository. https://peps.python.org/pep-0600/

* use `auditwheel` for it

Co-authored-by: HongKee Moon <moon@mpi-cbg.de>
the default branch is changed to 'develop'
additionally, fix ctest folder
additionally, fix ctest folder
* chore: test for win32

* chore: use Release libraries for linking in windows

* chore: use 1e-14 instead of 1e-15

* 1e-15 doesn't work in windows

* chore: remove docker-compose.yml

* chore: revert test list

---------

Co-authored-by: HongKee Moon <moon@mpi-cbg.de>
hkmoon and others added 6 commits April 2, 2026 15:28
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Needed the flags in all windows, not just MSVC compiler.

found mistaken s in variable name, removed it

test pool wasnt using the correct source list.
gave warning on Windows clang.  using explicit namespace silences warning
was getting warning for extra tokens.  compiling with clang on windows, there was no need for the win32 part of the ifndef, so i left it commented out.  at some point, the commented-out should be removed.
Similar to a few commits ago.  That was for core, this is for the bindings.
@ofloveandhate
Copy link
Copy Markdown
Contributor

Using the environment yaml file at root level to provide dependencies via micromamba, together with an install of Visual Studio C++ (to resolve a linking problem with clang on windows), i was able to get it built and all core unit tests passed on Windows.

# one time
micromamba install -f .\environment-win.yml  
# every time
micromamba activate b2-windows

$env:CMAKE_PREFIX_PATH="$env:CONDA_PREFIX\Library" 
$env:CC='clang-cl' 
$env:CXX='clang-cl'
$env:CMAKE_GENERATOR='Ninja' 

cmake -DENABLE_UNIT_TESTING=ON -B bld -S .
-- Building for: Ninja
-- JRL cmakemodules not found. Let's fetch it.
-- The CXX compiler identification is Clang 19.1.7 with MSVC-like command-line
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Users/bertini/micromamba/envs/b2-windows/Library/bin/clang-cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring "bertini2" (https://github.com/bertiniteam/b2)
-- Package version (git describe): 1.0.0-3-g144e
-- Found PkgConfig: C:/Users/bertini/micromamba/envs/b2-windows/Library/bin/pkg-config.exe (found version "0.29.2")
-- Performing Test res_-D_SCL_SECURE_NO_WARNINGS
-- Performing Test res_-D_SCL_SECURE_NO_WARNINGS - Success
-- Performing Test res_-D_CRT_SECURE_NO_WARNINGS
-- Performing Test res_-D_CRT_SECURE_NO_WARNINGS - Success
-- Performing Test res_-D_CRT_SECURE_NO_DEPRECATE
-- Performing Test res_-D_CRT_SECURE_NO_DEPRECATE - Success
-- Performing Test res_/wd4101
-- Performing Test res_/wd4101 - Success
-- Performing Test res_/wd4250
-- Performing Test res_/wd4250 - Success
-- Performing Test res_/wd4251
-- Performing Test res_/wd4251 - Success
-- Performing Test res_/wd4275
-- Performing Test res_/wd4275 - Success
-- Performing Test res_/wd4355
-- Performing Test res_/wd4355 - Success
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Failed to find Doxygen, documentation will not be generated.
-- Default C++ standard: 201703
-- Minimal C++ standard upgraded to 11
-- C++ standard sufficient: Minimal required 11, currently defined: 17
-- Checking for NumPy
--   NUMPY_INCLUDE_DIRS=C:/Users/bertini/micromamba/envs/b2-windows/Lib/site-packages/numpy/_core/include
--   NUMPY_VERSION=2.4.3
-- Found Python3: C:/Users/bertini/micromamba/envs/b2-windows/python.exe (found version "3.11.15") found components: Interpreter Development.Module NumPy
-- PythonLibraryDirs: C:/Users/bertini/micromamba/envs/b2-windows/libs
-- PythonLibVersionString: 3.11.15
-- Python site lib: lib/python3.11/site-packages
-- Python include dirs: C:/Users/bertini/micromamba/envs/b2-windows/Include
-- Checking for NumPy
--   NUMPY_INCLUDE_DIRS=C:/Users/bertini/micromamba/envs/b2-windows/Lib/site-packages/numpy/_core/include
--   NUMPY_VERSION=2.4.3
-- NumPy include dir: C:/Users/bertini/micromamba/envs/b2-windows/Lib/site-packages/numpy/_core/include
-- The C compiler identification is Clang 19.1.7 with MSVC-like command-line
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Users/bertini/micromamba/envs/b2-windows/Library/bin/clang-cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Build type: Debug
-- ENABLE_UNIT_TESTING: ON
-- Found GMP: C:/Users/bertini/micromamba/envs/b2-windows/Library/include
-- Found MPFR: C:/Users/bertini/micromamba/envs/b2-windows/Library/include (Required is at least version "1.0.0")
-- Found MPC: C:/Users/bertini/micromamba/envs/b2-windows/Library/include
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - not found
-- Found Threads: TRUE
-- Build type: Debug
-- eigenpy.lib FOUND. eigenpy.lib at C:/Users/bertini/micromamba/envs/b2-windows/Library/lib/eigenpy.lib
-- C++ standard sufficient: Minimal required 11, currently defined: 17
-- Found Python: C:/Users/bertini/micromamba/envs/b2-windows/python.exe (found version "3.11.15") found components: Interpreter Development.Module NumPy
-- SKBUILD=""
-- Configuring done (29.1s)
-- Generating done (0.3s)
-- Build files have been written to: C:/Users/bertini/projects/b2_bertiniteam/bld
(b2-windows) PS C:\Users\bertini\projects\b2_bertiniteam> cmake -DENABLE_UNIT_TESTING=ON -B bld -S .
-- JRL cmakemodules not found. Let's fetch it.
-- Configuring "bertini2" (https://github.com/bertiniteam/b2)
-- Package version (git describe): 1.0.0-3-g144e
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Failed to find Doxygen, documentation will not be generated.
-- Default C++ standard: 201703
-- C++ standard sufficient: Minimal required 11, currently defined: 17
-- Checking for NumPy
--   NUMPY_INCLUDE_DIRS=C:/Users/bertini/micromamba/envs/b2-windows/Lib/site-packages/numpy/_core/include
--   NUMPY_VERSION=2.4.3
-- PythonLibraryDirs: C:/Users/bertini/micromamba/envs/b2-windows/libs
-- PythonLibVersionString: 3.11.15
-- Python site lib: lib/python3.11/site-packages
-- Python include dirs: C:/Users/bertini/micromamba/envs/b2-windows/Include
-- Checking for NumPy
--   NUMPY_INCLUDE_DIRS=C:/Users/bertini/micromamba/envs/b2-windows/Lib/site-packages/numpy/_core/include
--   NUMPY_VERSION=2.4.3
-- NumPy include dir: C:/Users/bertini/micromamba/envs/b2-windows/Lib/site-packages/numpy/_core/include
-- Build type: Debug
-- ENABLE_UNIT_TESTING: ON
-- Build type: Debug
-- eigenpy.lib FOUND. eigenpy.lib at C:/Users/bertini/micromamba/envs/b2-windows/Library/lib/eigenpy.lib
-- C++ standard sufficient: Minimal required 11, currently defined: 17
-- SKBUILD=""
-- Configuring done (7.2s)
-- Generating done (0.2s)
-- Build files have been written to: C:/Users/bertini/projects/b2_bertiniteam/bld
(b2-windows) PS C:\Users\bertini\projects\b2_bertiniteam> cmake --build bld
[428/428] Linking CXX executable core\test_nag_datatypes.exe
(b2-windows) PS C:\Users\bertini\projects\b2_bertiniteam> cd bld
(b2-windows) PS C:\Users\bertini\projects\b2_bertiniteam\bld> ninja test
[0/1] Running tests...Test project C:/Users/bertini/projects/b2_bertiniteam/bld
      Start  1: test_classes
 1/10 Test  #1: test_classes .....................   Passed    0.44 sec
      Start  2: test_blackbox
 2/10 Test  #2: test_blackbox ....................   Passed    0.34 sec
      Start  3: test_classic
 3/10 Test  #3: test_classic .....................   Passed    0.25 sec
      Start  4: test_endgames
 4/10 Test  #4: test_endgames ....................   Passed   32.88 sec
      Start  5: test_generating
 5/10 Test  #5: test_generating ..................   Passed    0.25 sec
      Start  6: test_nag_algorithms
 6/10 Test  #6: test_nag_algorithms ..............   Passed   63.48 sec
      Start  7: test_nag_datatypes
 7/10 Test  #7: test_nag_datatypes ...............   Passed    0.26 sec
      Start  8: test_pool
 8/10 Test  #8: test_pool ........................   Passed    0.24 sec
      Start  9: test_settings
 9/10 Test  #9: test_settings ....................   Passed    0.25 sec
      Start 10: test_tracking_basics
10/10 Test #10: test_tracking_basics .............   Passed    0.52 sec

100% tests passed, 0 tests failed out of 10

Total Test time (real) = 100.50 sec

@ofloveandhate
Copy link
Copy Markdown
Contributor

ofloveandhate commented Apr 8, 2026

remaining before I accept:

  • make sure the python unit tests also pass.
  • double check documentation generation. deprecate the site i've been using, at doc.bertini2.org? i no longer have the build server that automatically updated the server with the docs, so going somewhere else with them with automatic building would be fantastic. at least the python documentation should be automatically updated at readthedocs, if not the c++.
  • check CI testing setup
  • switch branch to main from develop? main hasn't been updated in sooooo long.
  • double check installation via pip from root level of repo

@hkmoon
Copy link
Copy Markdown
Author

hkmoon commented Apr 9, 2026

@ofloveandhate That sounds reasonable. If you want me to work for them, just let me know. ;)

@ofloveandhate
Copy link
Copy Markdown
Contributor

I think the most difficult part is the python tests. They're also the most important. They're failing because of numpy data type stuff. So it's not trivial. If I remember correctly, it's a type registration thing, so that numpy knows what to do with the custom data types I'm using (variable precision complex and real numbers provided via Boost.Multiprecision).

@hkmoon
Copy link
Copy Markdown
Author

hkmoon commented Apr 9, 2026

Hope it's helpful.

np.sqrt is implemented for the tests. If you need to add other function-call ufuncs (e.g., abs, log, exp). You can use that pattern in eigenpy_interaction.hpp.

In the project folder:
python -m pytest python/test/ -v

b2 on develop [$!?] via v3.13.3+ (venv) took 4s
❯ python -m pytest python/test/ -v
====================================================== test session starts ======================================================
platform darwin -- Python 3.13.3+, pytest-9.0.3, pluggy-1.6.0 -- /Users/moon/Projects/git-projects/Harrington/b2/venv/bin/python
cachedir: .pytest_cache
rootdir: /Users/moon/Projects/git-projects/Harrington/b2/python
configfile: pyproject.toml
collected 49 items

python/test/classes/differentiation_test.py::DiffTest::test_power_rule PASSED                                             [  2%]
python/test/classes/differentiation_test.py::DiffTest::test_prod_rule PASSED                                              [  4%]
python/test/classes/differentiation_test.py::DiffTest::test_sum_rule PASSED                                               [  6%]
python/test/classes/differentiation_test.py::DiffTest::test_trancendental PASSED                                          [  8%]
python/test/classes/function_tree_test.py::SymbolTest::test_E_construct PASSED                                            [ 10%]
python/test/classes/function_tree_test.py::SymbolTest::test_Float_construct PASSED                                        [ 12%]
python/test/classes/function_tree_test.py::SymbolTest::test_Float_eval PASSED                                             [ 14%]
python/test/classes/function_tree_test.py::SymbolTest::test_Float_funcs PASSED                                            [ 16%]
python/test/classes/function_tree_test.py::SymbolTest::test_I_construct PASSED                                            [ 18%]
python/test/classes/function_tree_test.py::SymbolTest::test_Pi_construct PASSED                                           [ 20%]
python/test/classes/function_tree_test.py::SymbolTest::test_Variable_construct PASSED                                     [ 22%]
python/test/classes/function_tree_test.py::SymbolTest::test_Variable_eval PASSED                                          [ 24%]
python/test/classes/function_tree_test.py::SymbolTest::test_Variable_funcs PASSED                                         [ 26%]
python/test/classes/function_tree_test.py::OperatorTest::test_Homogenize PASSED                                           [ 28%]
python/test/classes/function_tree_test.py::OperatorTest::test_Operator_degree PASSED                                      [ 30%]
python/test/classes/function_tree_test.py::OperatorTest::test_Operator_ishom PASSED                                       [ 32%]
python/test/classes/function_tree_test.py::OperatorTest::test_Operator_ispoly PASSED                                      [ 34%]
python/test/classes/function_tree_test.py::OperatorTest::test_num_times_var PASSED                                        [ 36%]
python/test/classes/function_tree_test.py::OperatorTest::test_plus PASSED                                                 [ 38%]
python/test/classes/function_tree_test.py::OperatorTest::test_power PASSED                                                [ 40%]
python/test/classes/function_tree_test.py::OperatorTest::test_sub PASSED                                                  [ 42%]
python/test/classes/function_tree_test.py::OperatorTest::test_trans_funcs PASSED                                          [ 44%]
python/test/classes/function_tree_test.py::OperatorTest::test_var_div_var PASSED                                          [ 46%]
python/test/classes/function_tree_test.py::OperatorTest::test_var_times_var PASSED                                        [ 48%]
python/test/classes/mpfr_test.py::MPFRFloat::test_arith_int PASSED                                                        [ 51%]
python/test/classes/mpfr_test.py::MPFRFloat::test_arith_mpfr PASSED                                                       [ 53%]
python/test/classes/mpfr_test.py::MPFRFloat::test_change_prec PASSED                                                      [ 55%]
python/test/classes/mpfr_test.py::MPFRFloat::test_trancendentals PASSED                                                   [ 57%]
python/test/classes/mpfr_test.py::MPFRComplex::test_arith_mp_complex PASSED                                               [ 59%]
python/test/classes/mpfr_test.py::MPFRComplex::test_arith_mp_float PASSED                                                 [ 61%]
python/test/classes/mpfr_test.py::MPFRComplex::test_change_prec PASSED                                                    [ 63%]
python/test/classes/mpfr_test.py::MPFRComplex::test_complex_abs PASSED                                                    [ 65%]
python/test/classes/mpfr_test.py::MPFRComplex::test_complex_arg PASSED                                                    [ 67%]
python/test/classes/mpfr_test.py::MPFRComplex::test_complex_conj PASSED                                                   [ 69%]
python/test/classes/mpfr_test.py::MPFRComplex::test_complex_construct_from_polar PASSED                                   [ 71%]
python/test/classes/mpfr_test.py::MPFRComplex::test_construct PASSED                                                      [ 73%]
python/test/classes/mpfr_test.py::MPFRComplex::test_mp_complex_precision PASSED                                           [ 75%]
python/test/classes/mpfr_test.py::MPFRComplex::test_trancendentals PASSED                                                 [ 77%]
python/test/classes/parser_test.py::ParserTest::test_create_system PASSED                                                 [ 79%]
python/test/classes/system_test.py::SystemTest::test_add_systems PASSED                                                   [ 81%]
python/test/classes/system_test.py::SystemTest::test_mult_system_node PASSED                                              [ 83%]
python/test/classes/system_test.py::SystemTest::test_system_Jac PASSED                                                    [ 85%]
python/test/classes/system_test.py::SystemTest::test_system_create PASSED                                                 [ 87%]
python/test/classes/system_test.py::SystemTest::test_system_eval PASSED                                                   [ 89%]
python/test/tracking/amptracking_test.py::AMPTrackingTest::test_tracker_linear PASSED                                     [ 91%]
python/test/tracking/amptracking_test.py::AMPTrackingTest::test_tracker_quad PASSED                                       [ 93%]
python/test/tracking/amptracking_test.py::AMPTrackingTest::test_tracker_singular_start PASSED                             [ 95%]
python/test/tracking/amptracking_test.py::AMPTrackingTest::test_tracker_sqrt PASSED                                       [ 97%]
python/test/tracking/endgame_test.py::EndgameTest::test_using_total_degree_ss PASSED                                      [100%]

====================================================== 49 passed in 4.62s =======================================================

@ofloveandhate
Copy link
Copy Markdown
Contributor

There are some tests yet failing. I don't know why your report didn't run them. Here's my output, from running python python/test/test_all.py from root in directory. I'm using a pyenv, with Python installed from Homebrew. My numpy version is 2.4.4.

python test_all.py 
(<module 'classes.mpfr_test' from '/Users/amethyst/repo/b2_bertiniteam/python/test/classes/mpfr_test.py'>, <module 'bertini.function_tree' from '/Users/amethyst/env/b2/lib/python3.14/site-packages/bertini/function_tree/__init__.py'>, <module 'bertini.function_tree' from '/Users/amethyst/env/b2/lib/python3.14/site-packages/bertini/function_tree/__init__.py'>, <module 'bertini.function_tree' from '/Users/amethyst/env/b2/lib/python3.14/site-packages/bertini/function_tree/__init__.py'>, <module 'classes.parser_test' from '/Users/amethyst/repo/b2_bertiniteam/python/test/classes/parser_test.py'>, <module 'classes.eigenpy_numpy' from '/Users/amethyst/repo/b2_bertiniteam/python/test/classes/eigenpy_numpy.py'>)
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<classes.mpfr_test.MPFRComplex testMethod=test_arith_mp_complex>, <classes.mpfr_test.MPFRComplex testMethod=test_arith_mp_float>, <classes.mpfr_test.MPFRComplex testMethod=test_change_prec>, <classes.mpfr_test.MPFRComplex testMethod=test_complex_abs>, <classes.mpfr_test.MPFRComplex testMethod=test_complex_arg>, <classes.mpfr_test.MPFRComplex testMethod=test_complex_conj>, <classes.mpfr_test.MPFRComplex testMethod=test_complex_construct_from_polar>, <classes.mpfr_test.MPFRComplex testMethod=test_construct>, <classes.mpfr_test.MPFRComplex testMethod=test_mp_complex_precision>, <classes.mpfr_test.MPFRComplex testMethod=test_trancendentals>]>, <unittest.suite.TestSuite tests=[<classes.mpfr_test.MPFRFloat testMethod=test_arith_int>, <classes.mpfr_test.MPFRFloat testMethod=test_arith_mpfr>, <classes.mpfr_test.MPFRFloat testMethod=test_change_prec>, <classes.mpfr_test.MPFRFloat testMethod=test_trancendentals>]>]>
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<bertini.function_tree.OperatorTest testMethod=test_Homogenize>, <bertini.function_tree.OperatorTest testMethod=test_Operator_degree>, <bertini.function_tree.OperatorTest testMethod=test_Operator_ishom>, <bertini.function_tree.OperatorTest testMethod=test_Operator_ispoly>, <bertini.function_tree.OperatorTest testMethod=test_num_times_var>, <bertini.function_tree.OperatorTest testMethod=test_plus>, <bertini.function_tree.OperatorTest testMethod=test_power>, <bertini.function_tree.OperatorTest testMethod=test_sub>, <bertini.function_tree.OperatorTest testMethod=test_trans_funcs>, <bertini.function_tree.OperatorTest testMethod=test_var_div_var>, <bertini.function_tree.OperatorTest testMethod=test_var_times_var>]>, <unittest.suite.TestSuite tests=[<bertini.function_tree.SymbolTest testMethod=test_E_construct>, <bertini.function_tree.SymbolTest testMethod=test_Float_construct>, <bertini.function_tree.SymbolTest testMethod=test_Float_eval>, <bertini.function_tree.SymbolTest testMethod=test_Float_funcs>, <bertini.function_tree.SymbolTest testMethod=test_I_construct>, <bertini.function_tree.SymbolTest testMethod=test_Pi_construct>, <bertini.function_tree.SymbolTest testMethod=test_Variable_construct>, <bertini.function_tree.SymbolTest testMethod=test_Variable_eval>, <bertini.function_tree.SymbolTest testMethod=test_Variable_funcs>]>]>
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<bertini.function_tree.DiffTest testMethod=test_power_rule>, <bertini.function_tree.DiffTest testMethod=test_prod_rule>, <bertini.function_tree.DiffTest testMethod=test_sum_rule>, <bertini.function_tree.DiffTest testMethod=test_trancendental>]>]>
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<bertini.function_tree.SystemTest testMethod=test_add_systems>, <bertini.function_tree.SystemTest testMethod=test_mult_system_node>, <bertini.function_tree.SystemTest testMethod=test_system_Jac>, <bertini.function_tree.SystemTest testMethod=test_system_create>, <bertini.function_tree.SystemTest testMethod=test_system_eval>]>]>
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<classes.parser_test.ParserTest testMethod=test_create_system>]>]>
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<classes.eigenpy_numpy.TestComplex testMethod=test_make_array_empty>, <classes.eigenpy_numpy.TestComplex testMethod=test_make_array_ones>, <classes.eigenpy_numpy.TestComplex testMethod=test_make_array_ones_with_conversion>, <classes.eigenpy_numpy.TestComplex testMethod=test_make_array_ones_with_conversion_and_astype_int64>, <classes.eigenpy_numpy.TestComplex testMethod=test_make_array_zeros>, <classes.eigenpy_numpy.TestComplex testMethod=test_make_array_zeros_with_conversion>, <classes.eigenpy_numpy.TestComplex testMethod=test_make_array_zeros_with_conversion_and_astype_int64>]>, <unittest.suite.TestSuite tests=[<classes.eigenpy_numpy.TestFloat testMethod=test_make_array_empty>, <classes.eigenpy_numpy.TestFloat testMethod=test_make_array_ones>, <classes.eigenpy_numpy.TestFloat testMethod=test_make_array_ones_with_conversion>, <classes.eigenpy_numpy.TestFloat testMethod=test_make_array_ones_with_conversion_and_astype_int64>, <classes.eigenpy_numpy.TestFloat testMethod=test_make_array_zeros>, <classes.eigenpy_numpy.TestFloat testMethod=test_make_array_zeros_with_conversion>, <classes.eigenpy_numpy.TestFloat testMethod=test_make_array_zeros_with_conversion_and_astype_int64>]>]>
test_arith_mp_complex (classes.mpfr_test.MPFRComplex.test_arith_mp_complex) ... ok
test_arith_mp_float (classes.mpfr_test.MPFRComplex.test_arith_mp_float) ... ok
test_change_prec (classes.mpfr_test.MPFRComplex.test_change_prec) ... ok
test_complex_abs (classes.mpfr_test.MPFRComplex.test_complex_abs) ... ok
test_complex_arg (classes.mpfr_test.MPFRComplex.test_complex_arg) ... ok
test_complex_conj (classes.mpfr_test.MPFRComplex.test_complex_conj) ... ok
test_complex_construct_from_polar (classes.mpfr_test.MPFRComplex.test_complex_construct_from_polar) ... ok
test_construct (classes.mpfr_test.MPFRComplex.test_construct) ... ok
test_mp_complex_precision (classes.mpfr_test.MPFRComplex.test_mp_complex_precision) ... ok
test_trancendentals (classes.mpfr_test.MPFRComplex.test_trancendentals) ... ok
test_arith_int (classes.mpfr_test.MPFRFloat.test_arith_int) ... ok
test_arith_mpfr (classes.mpfr_test.MPFRFloat.test_arith_mpfr) ... ok
test_change_prec (classes.mpfr_test.MPFRFloat.test_change_prec) ... ok
test_trancendentals (classes.mpfr_test.MPFRFloat.test_trancendentals) ... ok
test_Homogenize (bertini.function_tree.OperatorTest.test_Homogenize) ... ok
test_Operator_degree (bertini.function_tree.OperatorTest.test_Operator_degree) ... ok
test_Operator_ishom (bertini.function_tree.OperatorTest.test_Operator_ishom) ... ok
test_Operator_ispoly (bertini.function_tree.OperatorTest.test_Operator_ispoly) ... ok
test_num_times_var (bertini.function_tree.OperatorTest.test_num_times_var) ... ok
test_plus (bertini.function_tree.OperatorTest.test_plus) ... ok
test_power (bertini.function_tree.OperatorTest.test_power) ... ok
test_sub (bertini.function_tree.OperatorTest.test_sub) ... ok
test_trans_funcs (bertini.function_tree.OperatorTest.test_trans_funcs) ... ok
test_var_div_var (bertini.function_tree.OperatorTest.test_var_div_var) ... ok
test_var_times_var (bertini.function_tree.OperatorTest.test_var_times_var) ... ok
test_E_construct (bertini.function_tree.SymbolTest.test_E_construct) ... ok
test_Float_construct (bertini.function_tree.SymbolTest.test_Float_construct) ... ok
test_Float_eval (bertini.function_tree.SymbolTest.test_Float_eval) ... ok
test_Float_funcs (bertini.function_tree.SymbolTest.test_Float_funcs) ... ok
test_I_construct (bertini.function_tree.SymbolTest.test_I_construct) ... ok
test_Pi_construct (bertini.function_tree.SymbolTest.test_Pi_construct) ... ok
test_Variable_construct (bertini.function_tree.SymbolTest.test_Variable_construct) ... ok
test_Variable_eval (bertini.function_tree.SymbolTest.test_Variable_eval) ... ok
test_Variable_funcs (bertini.function_tree.SymbolTest.test_Variable_funcs) ... ok
test_power_rule (bertini.function_tree.DiffTest.test_power_rule) ... ok
test_prod_rule (bertini.function_tree.DiffTest.test_prod_rule) ... ok
test_sum_rule (bertini.function_tree.DiffTest.test_sum_rule) ... ok
test_trancendental (bertini.function_tree.DiffTest.test_trancendental) ... ok
test_add_systems (bertini.function_tree.SystemTest.test_add_systems) ... ok
test_mult_system_node (bertini.function_tree.SystemTest.test_mult_system_node) ... ok
test_system_Jac (bertini.function_tree.SystemTest.test_system_Jac) ... ok
test_system_create (bertini.function_tree.SystemTest.test_system_create) ... ok
test_system_eval (bertini.function_tree.SystemTest.test_system_eval) ... ok
test_create_system (classes.parser_test.ParserTest.test_create_system) ... ok
test_make_array_empty (classes.eigenpy_numpy.TestComplex.test_make_array_empty) ... ok
test_make_array_ones (classes.eigenpy_numpy.TestComplex.test_make_array_ones) ... ok
test_make_array_ones_with_conversion (classes.eigenpy_numpy.TestComplex.test_make_array_ones_with_conversion) ... ERROR
test_make_array_ones_with_conversion_and_astype_int64 (classes.eigenpy_numpy.TestComplex.test_make_array_ones_with_conversion_and_astype_int64) ... ok
test_make_array_zeros (classes.eigenpy_numpy.TestComplex.test_make_array_zeros) ... ok
test_make_array_zeros_with_conversion (classes.eigenpy_numpy.TestComplex.test_make_array_zeros_with_conversion) ... ERROR
test_make_array_zeros_with_conversion_and_astype_int64 (classes.eigenpy_numpy.TestComplex.test_make_array_zeros_with_conversion_and_astype_int64) ... ok
test_make_array_empty (classes.eigenpy_numpy.TestFloat.test_make_array_empty) ... ok
test_make_array_ones (classes.eigenpy_numpy.TestFloat.test_make_array_ones) ... ok
test_make_array_ones_with_conversion (classes.eigenpy_numpy.TestFloat.test_make_array_ones_with_conversion) ... ERROR
test_make_array_ones_with_conversion_and_astype_int64 (classes.eigenpy_numpy.TestFloat.test_make_array_ones_with_conversion_and_astype_int64) ... ok
test_make_array_zeros (classes.eigenpy_numpy.TestFloat.test_make_array_zeros) ... ok
test_make_array_zeros_with_conversion (classes.eigenpy_numpy.TestFloat.test_make_array_zeros_with_conversion) ... ERROR
test_make_array_zeros_with_conversion_and_astype_int64 (classes.eigenpy_numpy.TestFloat.test_make_array_zeros_with_conversion_and_astype_int64) ... ok

======================================================================
ERROR: test_make_array_ones_with_conversion (classes.eigenpy_numpy.TestComplex.test_make_array_ones_with_conversion)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/amethyst/repo/b2_bertiniteam/python/test/classes/eigenpy_numpy.py", line 101, in test_make_array_ones_with_conversion
    A = np.array( np.ones(self.shape), dtype = mp.Complex)
TypeError: Cannot cast array data from dtype('float64') to dtype(Complex) according to the rule 'unsafe'

======================================================================
ERROR: test_make_array_zeros_with_conversion (classes.eigenpy_numpy.TestComplex.test_make_array_zeros_with_conversion)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/amethyst/repo/b2_bertiniteam/python/test/classes/eigenpy_numpy.py", line 90, in test_make_array_zeros_with_conversion
    A = np.array( np.zeros(self.shape), dtype = mp.Complex)
TypeError: Cannot cast array data from dtype('float64') to dtype(Complex) according to the rule 'unsafe'

======================================================================
ERROR: test_make_array_ones_with_conversion (classes.eigenpy_numpy.TestFloat.test_make_array_ones_with_conversion)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/amethyst/repo/b2_bertiniteam/python/test/classes/eigenpy_numpy.py", line 67, in test_make_array_ones_with_conversion
    A = np.array( np.ones(self.shape), dtype = mp.Float)
TypeError: Cannot cast array data from dtype('float64') to dtype(Float) according to the rule 'unsafe'

======================================================================
ERROR: test_make_array_zeros_with_conversion (classes.eigenpy_numpy.TestFloat.test_make_array_zeros_with_conversion)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/amethyst/repo/b2_bertiniteam/python/test/classes/eigenpy_numpy.py", line 56, in test_make_array_zeros_with_conversion
    A = np.array( np.zeros(self.shape), dtype = mp.Float)
TypeError: Cannot cast array data from dtype('float64') to dtype(Float) according to the rule 'unsafe'

----------------------------------------------------------------------
Ran 58 tests in 0.006s

FAILED (errors=4)
test_tracker_linear (bertini.tracking.config.AMPTrackingTest.test_tracker_linear) ... ok
test_tracker_quad (bertini.tracking.config.AMPTrackingTest.test_tracker_quad) ... ok
test_tracker_singular_start (bertini.tracking.config.AMPTrackingTest.test_tracker_singular_start) ... ok
test_tracker_sqrt (bertini.tracking.config.AMPTrackingTest.test_tracker_sqrt) ... ok
test_using_total_degree_ss (bertini.endgame.config.EndgameTest.test_using_total_degree_ss) ... ok

----------------------------------------------------------------------
Ran 5 tests in 1.416s

OK
test_can_solve_multiple_times (zero_dim.basics.ZeroDimBasicsTest.test_can_solve_multiple_times)
This test is here because multiple calls to solver.solve() during ... ok

----------------------------------------------------------------------
Ran 1 test in 0.283s

OK

So the failing familiy tests have names like test_make_array_zeros_with_conversion, and the code for the failing tests looks like

A = np.array( np.zeros(self.shape), dtype = mp.Complex) 

As I understand it, the default np.zeros call makes float64's. And since I have implicit conversion from double precision to variable precision disabled (to prevent accidental pollution of high-precision numbers with things like 0.1, which is NOT 0.10000000000000000..., but rather 0.099999999999999 and some noise, because it can't be exactly represented). the test fails. Hence the user, to make zeros in Bertini, has to pass through another type.


I'm not going to enable automatic/implicit conversion from double to variable precision. I do note that

A = np.ones(self.shape, dtype = mp.Float) 

works, so variable precision can be directly constructed into numpy arrays, making these conversion tests kind of useless.


  • Should I remove these tests since they're expected to fail? Or
  • should I re-write them so the unit tests expect them to fail?

@ofloveandhate
Copy link
Copy Markdown
Contributor

Still wondering why these specific tests didn't run for you.

@ofloveandhate
Copy link
Copy Markdown
Contributor

I'm also struggling to use pytest with my unit tests. (They are admittedly written with unittest, not pytest, but pytest is capable of running unittest). For example, i'm in b2/python, and I run-and-get:

 python -m pytest test/classes/differentiation_test.py
====================================== test session starts ======================================
platform darwin -- Python 3.14.3, pytest-9.0.3, pluggy-1.6.0
rootdir: /Users/amethyst/repo/b2_bertiniteam/python
configfile: pyproject.toml
collected 0 items / 1 error                                                                     

============================================ ERRORS =============================================
_____________________ ERROR collecting test/classes/differentiation_test.py _____________________
ImportError while importing test module '/Users/amethyst/repo/b2_bertiniteam/python/test/classes/differentiation_test.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/opt/homebrew/Cellar/python@3.14/3.14.3_1/Frameworks/Python.framework/Versions/3.14/lib/python3.14/importlib/__init__.py:88: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
test/classes/differentiation_test.py:34: in <module>
    from bertini import *
bertini/__init__.py:65: in <module>
    import bertini.function_tree as function_tree
bertini/function_tree/__init__.py:31: in <module>
    import bertini._pybertini
E   ModuleNotFoundError: No module named 'bertini._pybertini'
==================================== short test summary info ====================================
ERROR test/classes/differentiation_test.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Is this a my-computer thing, or a setup problem with the unit tests?

Please build and install it again:
`pip install dist/bertini-1.0.0-cp313-cp313-macosx_14_0_arm64.whl --force-reinstall --no-deps`

Then run `python python/test/test_all.py`
@hkmoon
Copy link
Copy Markdown
Author

hkmoon commented Apr 13, 2026

Maybe I install bertini with python.

# in the project root
rm -rf b2/bld && python -m build --wheel

# *** Making wheel...
# *** Created bertini-1.0.0-cp313-cp313-macosx_14_0_arm64.whl
# Successfully built bertini-1.0.0-cp313-cp313-macosx_14_0_arm64.whl

# please change the python version according to yours or use the wheel output
pip install dist/bertini-1.0.0-cp313-cp313-macosx_14_0_arm64.whl --force-reinstall --no-deps

python python/test/test_all.py

@ofloveandhate
Copy link
Copy Markdown
Contributor

I saw the last commit. I don't think it's right. It allows implicit conversion from double to variable precision. I want to allow conversion, but only explicit.

@hkmoon
Copy link
Copy Markdown
Author

hkmoon commented Apr 14, 2026

It makes sense. IMPLICITLY_CONVERTIBLE(double,T) is a Boost.Python way, not for NumPy array and it is used for Python float to mpfr_float auto-converts. If you want explicit conversion for this case, you can remove those lines.

@ofloveandhate
Copy link
Copy Markdown
Contributor

Adding more. Here's an explicit failing unit test, that cannot possibly ever succeed.

    def test_make_array_point_one(self):
        """ 
        check that if we make an array of variable precision reals from doubles, we get what we expected.
        """
        A = np.array( 0.1 * np.ones(self.shape), dtype = mp.Float) 

        self.assertTrue(np.all(A==mp.Float('0.1')));

Furthermore, I think it is very likely that a user tries to do

x = bertini.Variable('x')
y = 0.1 * x

But they'll never get good results from high-precision evaluation of this, because the 0.1 is hanging out stinking up the place.

x.set_current_value(bertini.multiprec.Complex('1'))
y.reset()
y.eval_mp()

will NOT give 0.1 to D digits. Instead, it will give whatever double(0.1) --> Complex gives.


I just want to help my users do the right thing, and keep them from accidentally using low-precision types where a high-precision type is expected. I'm still thinking about the right thing to do...

@ofloveandhate
Copy link
Copy Markdown
Contributor

Disabling the IMPLICITLY_CONVERTIBLE calls restores some sanity back to what I expect:

x = bertini.Variable('x')
y = 0.1*x
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell line 1
----> 1 y = 0.1*x

TypeError: unsupported operand type(s) for *: 'float' and 'Variable'

This is desirable.

@ofloveandhate
Copy link
Copy Markdown
Contributor

I have a much better understanding of what explicit vs implicit conversion means in numpy now.

This is considered an explicit conversion:

np.array( 0.1 * np.ones(self.shape), dtype = mp.Float) 

I guess I want my users to be able to explicitly convert like this. I added a test that it produces "expected" values, in the sense that you do NOT get the same values as constructing variable-precision number from string, eg Float('0.1')

@ofloveandhate
Copy link
Copy Markdown
Contributor

I wrote a test to make sure that implicit conversion from double to float is disabled, particularly when forming systems / expressions

@ofloveandhate
Copy link
Copy Markdown
Contributor

I feel like I'm probably missing a whole bunch of tests, but it'll do for now.

@ofloveandhate
Copy link
Copy Markdown
Contributor

But i'm still having trouble with Pytest.

The Python tests are passing when calling python python/test/test_all.py. But not, on my machine, when I use pytest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants