Skip to content

Convert Python complex values in symbolic interface expressions - #42618

Open
cxzhong wants to merge 3 commits into
sagemath:developfrom
cxzhong:agent/gh-42608-python-complex-interface
Open

Convert Python complex values in symbolic interface expressions#42618
cxzhong wants to merge 3 commits into
sagemath:developfrom
cxzhong:agent/gh-42608-python-complex-interface

Conversation

@cxzhong

@cxzhong cxzhong commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #42608.

What changed

  • Convert Python complex values wrapped in symbolic expressions through CDF before generating interface input.
  • Add regression tests for direct Maxima serialization and inversion of a symbolic matrix created from a NumPy complex array.

Why

NumPy converts complex scalars to built-in Python complex objects when a complex array becomes an object array during symbolic multiplication. InterfaceInit.pyobject() previously fell back to repr(), which emitted Python's j notation. Maxima cannot parse that notation, so symbolic matrix inversion failed while testing a pivot.

Converting the value through CDF reuses the existing interface-specific complex-number serialization, including Maxima's %i notation.

User impact

Symbolic expressions containing Python complex values can now be passed safely to external interfaces. In particular, matrix(x * numpy_array).inverse() no longer raises the MACSYMA-QUIT error for NumPy complex arrays.

Testing

@cxzhong
cxzhong marked this pull request as ready for review August 3, 2026 13:29
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Documentation preview for this PR (built with commit 94b6cb0; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

@cxzhong
cxzhong requested a review from dimpase August 3, 2026 15:09
Comment thread src/sage/symbolic/expression_conversions.py Outdated
@vivek41-glitch

Copy link
Copy Markdown
Contributor

@cxzhong The fix converts Python complex through CDF before serializing to Maxima. But CDF uses double precision (53-bit). Since this is a symbolic operation, wouldn't it be more semantically correct to use CC (which is also 53-bit but respects Sage's precision model) or even SR's own complex conversion to avoid any potential precision loss when the complex values come from arbitrary-precision contexts? Also, what happens if someone passes complex(1e-400, 1e-400)—does CDF underflow before Maxima sees it?

@cxzhong

cxzhong commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@vivek41-glitch Thanks for checking this. This branch only handles built-in Python complex objects. Their real and imaginary parts are already stored as C doubles, so any precision from an arbitrary-precision source has been lost before InterfaceInit.pyobject() receives them. Sage arbitrary-precision complex elements are not instances of Python complex and therefore do not enter this branch.

Similarly, complex(1e-400, 1e-400) is already 0j in Python, before conversion to CDF, so CDF does not introduce that underflow. For Maxima specifically, CDF._maxima_init_() delegates to ComplexField()(self)._maxima_init_(), and CDF(1, 2) and CC(1, 2) produce the same serialized value. Converting directly to CC therefore cannot recover any additional precision.

For these reasons, I think CDF is the appropriate bridge for the native Python type and no code change is needed.

@vivek41-glitch

Copy link
Copy Markdown
Contributor

That make sense and also could u plss tell me whether the CI faillings r related to this file ? And one suggestions from my side is given that the fix routes through CDF's maxima_init(), would it be worth adding a doctest that explicitly shows SR(complex(1,2)).maxima() returns the expected %i format? That would make the behavior explicit for future developers and catch any regressions.

@cxzhong

cxzhong commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@vivek41-glitch I checked both failing jobs. Neither is related to this PR:

In that failing macOS job, src/sage/symbolic/expression_conversions.py itself completed all 421 doctests successfully in 3.16 seconds. The Linux p-z job containing src/sage/symbolic also passed.

Regarding the additional doctest, the existing regression test already constructs z = SR(complex(1, 2)) and checks (z * x)._maxima_init_() against the exact %i serialization. This exercises InterfaceInit inside a symbolic expression, which is the path that originally failed. SR(complex(1, 2))._maxima_() instead starts a Maxima session and renders 2.0*%i+1.0, so adding it would mostly duplicate the existing coverage while testing more integration than the serializer changed here. I would therefore prefer to keep the current focused doctest.

@cxzhong

cxzhong commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@vivek41-glitch So do you agree this? If you agree this, I can change the label

@vivek41-glitch

Copy link
Copy Markdown
Contributor

Yes, I agree—your reasoning is sound. The existing doctest covers the serializer path, and the CI failures are clearly unrelated to this PR. Thanks for checking the logs and explaining the rationale.

@dimpase

dimpase commented Aug 5, 2026

Copy link
Copy Markdown
Member

the real brother of CDF is RDF. For consistency one might want Python reals to go to RDF, and Python complex numbers to go to CDF

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inverting symbolic matrix from NumPy complex array raises MACSYMA-QUIT error

3 participants