Skip to content

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
Comment on lines 40 to 46
```rust
let y = Complex::from_array([3, 4]);
```
or as a tuple:
```rust
let z = Complex::from_tuple((3, 4));
```
Copy link
Member

Choose a reason for hiding this comment

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

i think impl<T> From<(T, T)> for Complex<T> and impl<T> From<[T; 2]> for Complex<T> would be sufficient. it's like there is no SocketAddr::from_tuple.

Copy link
Contributor

Choose a reason for hiding this comment

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

This still exists. @scimind2460 please make sure you adequately address review concerns before marking topics as resolved, or leave them open for the the commenter to mark resolved themselves. If you're not sure, leave a comment.

@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.

Comment on lines 167 to 174
impl Complex<f64> {
fn angle(self) {
f32::atan2(self.re(), self.im())
}
fn from_polar(modulus: f32, angle: f32) -> Complex<f32> {
Complex::new(modulus * f32::cos(angle), modulus * f32::sin(angle))
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably want to return something here? And not use the f32 types for f64

That being said: I think polar conversions should be put into "future possibilities" since they aren't needed for basic support.

Copy link
Author

Choose a reason for hiding this comment

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

I was trying to write something to help with @clarfonthey's polar proposal, but if they are fine with this becoming a future possibility, then OK!

Copy link
Member

@joshtriplett joshtriplett Dec 9, 2025

Choose a reason for hiding this comment

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

Agreed that they should be moved to "future possibilities" for now.

Clarify future support for Gaussian integers and floating point types in the RFC.
scimind2460 and others added 4 commits December 16, 2025 08:20
Clarified the rationale for a unified API for complex numbers and addressed compatibility issues with C libraries. Updated examples and alternatives to improve understanding of complex number implementations.
Co-authored-by: Kevin Reid <[email protected]>
@Amanieu
Copy link
Member

Amanieu commented Dec 16, 2025

I would like @cuviper (as the author of num-complex) to review the proposed API here.

scimind2460 and others added 2 commits December 17, 2025 09:20
Refactor Complex struct to have public fields and update methods for real and imaginary parts. Added notes on future considerations for polar conversions and arithmetic implementations.
Copy link
Member

@cuviper cuviper left a comment

Choose a reason for hiding this comment

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

I apologise in advance to num-complex

No worries! There are definitely things that a compiler-integrated implementation can do better, especially with ABI as you've highlighted. A lot of the num-complex API is also limited by trying to be so generic, whereas the standard library can choose to keep all the implementation flexibility for itself.

Comment on lines 40 to 46
```rust
let y = Complex::from_array([3, 4]);
```
or as a tuple:
```rust
let z = Complex::from_tuple((3, 4));
```
Copy link
Contributor

Choose a reason for hiding this comment

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

This still exists. @scimind2460 please make sure you adequately address review concerns before marking topics as resolved, or leave them open for the the commenter to mark resolved themselves. If you're not sure, leave a comment.

Comment on lines 62 to 66
You can even calculate the complex sine, cosine and more:
```rust
let val = Complex::new(3.0, 4.0);
let sine_cmplx = csin(val); // 3.8537380379 - 27.016813258i
```
Copy link
Contributor

Choose a reason for hiding this comment

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

Delete this, mention trig and further functions in future possibilities instead. We wouldn't have a freestanding csin function anyway.

fn div(self, other: Self) -> Self::Output;
}
```
The floating point numbers shall have sine and cosine and tangent functions, their inverses, their hyperbolic variants, and their inverses defined as per the C standard and with Infinity and NaN values defined as per the C standard.
Copy link
Contributor

Choose a reason for hiding this comment

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

Move this to future possibilities.

@joshtriplett
Copy link
Member

I'd love to see an FCP kicked off for this, as soon as the open comments are addressed on the RFC (extra functions that need to move to future possibilities, and the inaccurate background information on nalgebra).

scimind2460 and others added 4 commits January 7, 2026 16:18
Removed redundant statement about overhead from libgcc calls and clarified the purpose of the Complex type.
@scimind2460
Copy link
Author

Hopefully I've cleared up everything to satisfaction. I suppose it's broadly reasonable to FCP?

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

Labels

I-libs-api-nominated Indicates that an issue has been nominated for prioritizing at the next libs-api team meeting. 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.