Skip to content

Complex numbers#3892

Open
scimind2460 wants to merge 40 commits intorust-lang:masterfrom
scimind2460:master
Open

Complex numbers#3892
scimind2460 wants to merge 40 commits intorust-lang:masterfrom
scimind2460:master

Conversation

@scimind2460
Copy link

@scimind2460 scimind2460 commented Dec 2, 2025

This RFC proposes FFI-compatible complex numbers to help scientific computing library authors use non-indirected complexes.

I apologise in advance to num-complex

Rendered

@ehuss ehuss added the T-libs-api Relevant to the library API team, which will review and decide on the RFC. label Dec 2, 2025
@joshtriplett joshtriplett added the T-lang Relevant to the language team, which will review and decide on the RFC. label Dec 2, 2025
@joshtriplett
Copy link
Member

Labeling this T-lang because the desire to make this FFI-compatible is a lang matter.

@joshtriplett joshtriplett added the I-libs-api-nominated Indicates that an issue has been nominated for prioritizing at the next libs-api team meeting. label Dec 2, 2025
@clarfonthey
Copy link

clarfonthey commented Dec 2, 2025

It's worth pointing out another big issue with this is that the canonical a+bi is not actually the best representation of complex numbers in all cases, and so deciding on this is making a decision that might make life harder for external complex-numeric libraries out there.

In particular, while a+bi (orthogonal) representation is efficient for addition, r*(iθ).exp() is more efficient for multiplication, and depending on the equation you're using, it may be advantageous to switch between the two to reduce the number of arithmetic operations needed.

I'm not super compelled by the argument that C supports this, therefore the standard library needs to support this. I think that guaranteeing a std::ffi::Complex representation would be desirable, but there's no saying that we need to make this a canonical type in, say, std::num.

@tgross35
Copy link
Contributor

tgross35 commented Dec 2, 2025

It's worth pointing out another big issue with this is that the canonical a+bi is not actually the best representation of complex numbers in all cases, and so deciding on this is making a decision that might make life harder for external complex-numeric libraries out there.

In particular, while a+bi (orthogonal) representation is efficient for addition, r*(iθ).exp() is more efficient for multiplication, and depending on the equation you're using, it may be advantageous to switch between the two to reduce the number of arithmetic operations needed.

I think that polar form almost always is the more optimal form, at least in my experience. But the ABIs do use rectangular, e.g. from x86:

Arguments of complex T where T is one of the types float or double are treated as if they are implemented as:

struct complexT {
  T real;
  T imag;
};

so it makes sense that an interchange type matches that, and users can translate to/from a polar repr at the FFI boundary if needed. But this reasoning is definitely something to have in the RFC's rationale & alternatives.

@clarfonthey
Copy link

clarfonthey commented Dec 2, 2025

Right: I guess my main clarification here was that due to the polar-orthogonal discrepancy, it shouldn't be a canonical Rust type (e.g. std::num::Complex shouldn't be making a decision on which is more-canonical), but I do think that having extra FFI-compatibility types is reasonable and this shouldn't prevent us from adding std::ffi::Complex which is orthogonal.

@scimind2460
Copy link
Author

scimind2460 commented Dec 3, 2025

Thanks everyone for the feedback! I have incorporated as much as I can into the RFC.
@clarfonthey I do think that the orthogonal representation is more "canonical", especially as it is the most commonly used one in crates.io and across languages. So I'm not sure if we can consider this an issue, especially as there are polar conversion methods in the RFC.

Clarify the rationale behind complex number implementation alternatives.
Expanded on the limitations of polar complex numbers and the need for a standard type for FFI with C. Discussed alternatives to complex number representation and their implications.
Added a section discussing alternatives to complex number implementations, including polar layout and non-generic primitive types, while emphasizing the importance of FFI compatibility.
Add considerations for complex number features and compatibility.
@scimind2460
Copy link
Author

Commenting on #793 as prior art (it wishes to achieve the same objective, but is largely dead)

@scottmcm
Copy link
Member

Having something to match C99 _Complex seems entirely lang-reasonable to me. I'm happy to see this not proposing a new repr; if things outside core want something with that layout/ABI they can repr(transparent) the canonical one.

@rfcbot reviewed

(I didn't pay much attention to the API. I trust libs-api will handle that appropriately.)

@cuviper
Copy link
Member

cuviper commented Feb 1, 2026

if things outside core want something with that layout/ABI they can repr(transparent) the canonical one.

I'm ok with this, but I do want to note that this is not seamless. For example, num_complex::Complex would not be able to keep its pub fields, only to pub expose that it's wrapping the core type that has pub fields itself.

(I probably won't bother with that at all -- just recommending the core type directly if you want C-ABI compatibility.)

@comex
Copy link

comex commented Feb 1, 2026

Will there be impls for fN: Mul<Complex<fN>>, fN: Add<Complex<fN>>, and the reverses of those? That would make it possible to write e.g. 1.0 + 2.0 * f32::i(). Seems like it should be either part of the RFC or a future possibility, or explicitly rejected.

Clarify the potential benefits of simplifying Complex number creation and discuss future support for Imaginary and Gaussian integers.
Clarify suggestions for complex number operations and future support.
@scimind2460
Copy link
Author

scimind2460 commented Feb 1, 2026

Will there be impls for fN: Mul<Complex<fN>>, fN: Add<Complex<fN>>, and the reverses of those? That would make it possible to write e.g. 1.0 + 2.0 * f32::i(). Seems like it should be either part of the RFC or a future possibility, or explicitly rejected.

It was there in an earlier draft, but I decided to relegate it to a future possibility. However, you can see that a related possibility such as the fn i(self) was discussed.

Clarified the implementation details of complex number operations and their calling conventions with C. Added explanations for arithmetic operations and discussed the drawbacks of alternative representations.
@scimind2460
Copy link
Author

@tmandry I hope that all issues are sufficiently resolved?

Copy link
Member

@tmandry tmandry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lokyhark
Copy link

lokyhark commented Mar 4, 2026

Just a remark about potential c32 and c64 aliases. I assume they refer to Complex<f32> and Complex<f64> respectively.

I like the idea that i32 is 32 bits, u64 is 64 bits etc. Using c32 for a type with a size of 64 bits may be confusing or at least, error prone for users.

For instance numpy use complex128 for Complex<64>. However it may be a bigger transition from well established complex number crates that rely on c32 = Complex<f32>.

Choosing the most appropriate one may require additional discussion.

@scimind2460
Copy link
Author

I like the idea that i32 is 32 bits, u64 is 64 bits etc. Using c32 for a type with a size of 64 bits may be confusing or at least, error prone for users.

To be fair, one could also argue the other way, that it may be confusing for users who may think c64 is actually Complex<f64> instead of Complex<f32> due to them sharing the same number. It really is a matter of perspective.

We could theoretically discuss which one is better here, but I don't think this should block the RFC.

Thanks for raising the point @lokyhark!

@kennytm
Copy link
Member

kennytm commented Mar 5, 2026

It really is a matter of perspective.

We could theoretically discuss which one is better here,

If one needs a discussion to determine whether c64 means Complex<f64> or Complex<f32> perhaps it's the best not to introduce such type alias to avoid ambiguity at all.

Also most prior art that provides such an alias uses complex128 to refer to Complex<f64>. I think num-complex is the only packages that uses "64" alone in a type name to refer to Complex<f64>.

Library Named by total size Named by component Generic only
C - - double _Complex
C++ - - std::complex<double>
Fortran - COMPLEX(8) -
Haskell - - Complex Double
D - cdouble Complex!double
Go complex128 - -
numpy (Python) complex128 cdouble -
Mathematica Complex128 ComplexReal64 -
swift-numerics (Swift) - - Complex<Double>
num-complex (Rust) - Complex64 Complex<f64>

@scimind2460
Copy link
Author

If one needs a discussion to determine whether c64 means Complex<f64> or Complex<f32> perhaps it's the best not to introduce such type alias to avoid ambiguity at all.

Yes, I agree. It would essentially be clear looking at the generic type.

Besides, we should have this discussion later, given that it's mentioned in the RFC as a future possibility.

@nikomatsakis
Copy link
Contributor

@rfcbot reviewed

@scimind2460
Copy link
Author

Thanks @nikomatsakis for the review!

By the way, is rfcbot bugged? It hasn't acknowledged the review yet.

@rust-rfcbot rust-rfcbot added the final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. label Mar 6, 2026
@rust-rfcbot
Copy link
Collaborator

🔔 This is now entering its final comment period, as per the review above. 🔔

@rust-rfcbot rust-rfcbot removed the proposed-final-comment-period Currently awaiting signoff of all team members in order to enter the final comment period. label Mar 6, 2026
@traviscross
Copy link
Contributor

@rfcbot reviewed

Thanks @scimind2460 for putting in the work on this.

@rustbot

This comment was marked as resolved.

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

Labels

disposition-merge This RFC is in PFCP or FCP with a disposition to merge it. final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. I-lang-nominated Indicates that an issue has been nominated for prioritizing at the next lang team meeting. P-lang-drag-2 Lang team prioritization drag level 2. T-lang Relevant to the language team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC.

Projects

None yet

Development

Successfully merging this pull request may close these issues.