Skip to content

feat: support optional complex scalar arguments#372

Open
krystophny wants to merge 1 commit into
jameskermode:masterfrom
krystophny:fix-optional-complex-scalar
Open

feat: support optional complex scalar arguments#372
krystophny wants to merge 1 commit into
jameskermode:masterfrom
krystophny:fix-optional-complex-scalar

Conversation

@krystophny

@krystophny krystophny commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #371.

UnwrappablesRemover.visit_Argument dropped every optional complex scalar argument, so present(z) could never be exercised from Python. Required complex scalars were wrapped normally. This removes that restriction, after which the f2py path handles optional complex scalars directly.

For --direct-c, two further gaps are fixed so complex scalar values work:

  • the scalar argument parser had no complex case; it now reads a Python complex via PyComplex_AsCComplex.
  • default complex mapped to double _Complex / NPY_CDOUBLE, a different size than Fortran's single-precision default, which dropped the imaginary part. It now maps to float _Complex / NPY_COMPLEX64, mirroring default real -> float. double complex and complex(8) still map to double; complex(dp) via the kind map is unchanged.

Verification

  • test/test_transform.py::TestTransform::test_optional_complex_scalar_kept asserts the optional complex argument survives the transform. On master it fails: AssertionError: 'z' not found in ['flag'].
  • test/test_directc.py complex mapping tests updated to the corrected single-precision defaults (and double complex / complex(4) added); 29 tests pass.
  • /tmp/f90wrap371-venv/bin/python -m pytest --import-mode=importlib -q /home/ert/code/f90wrap-dev/f90wrap/test/test_transform.py::TestTransform::test_optional_complex_scalar_kept /home/ert/code/f90wrap-dev/f90wrap/test/test_directc.py: 30 passed in 0.27s.
  • examples/issue371_optional_complex round-trips a complex value through present(z) on both the f2py and --direct-c paths.

Compiler matrix for examples/issue371_optional_complex, using make -f Makefile.meson test with DIRECTC=no and DIRECTC=yes:

Compiler Version f2py direct-C
gfortran GCC 16.1.1 pass, Ran 2 tests ... OK pass, Ran 2 tests ... OK
flang LLVM flang 22.1.6 pass, Ran 2 tests ... OK pass, Ran 2 tests ... OK
ifx 2025.0.4 pass, Ran 2 tests ... OK pass, Ran 2 tests ... OK
nvfortran 26.3 pass, Ran 2 tests ... OK pass, Ran 2 tests ... OK

The ifx runs need Intel's runtime library directory on the link path: LIBRARY_PATH=/opt/intel/oneapi/compiler/2025.0/lib.

Note

The absent-argument case for optional scalars under --direct-c (passing None so present() is .false.) is handled by a separate change for #369.

UnwrappablesRemover dropped every optional complex scalar argument, so
present(z) could never be exercised from Python; required complex scalars
were wrapped normally. Remove that restriction so the f2py path handles
optional complex scalars directly.

For --direct-c, two further gaps are fixed so complex scalar values work:
- the scalar argument parser had no complex case; read a Python complex
  via PyComplex_AsCComplex.
- default complex mapped to double _Complex / NPY_CDOUBLE, a different
  size than Fortran's single-precision default. Map it to float _Complex /
  NPY_COMPLEX64, mirroring default real -> float. double complex and
  complex(8) still map to double; complex(dp) via the kind map is unchanged.

Add a transform regression test (the optional complex argument survives),
update the direct-C complex mapping tests to the corrected defaults, and
add examples/issue371_optional_complex covering both backends.
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.

Optional complex scalar arguments are silently dropped

1 participant