-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Complex numbers #3892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Complex numbers #3892
Changes from 15 commits
ba634bb
0f4d922
863794c
60465d0
66b4a8e
e6a51ea
f63d8e6
8033da5
d86a918
4add4e1
5aceb3e
94dece5
0cf423a
512a3be
ca8f9ba
23f1e67
c055e1a
e438f35
d2c671a
3911071
73f823f
e69a67f
d1e41cb
a1774ac
6851400
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,252 @@ | ||||||
| - Feature Name: complex-numbers | ||||||
| - Start Date: 2025-12-02 | ||||||
| - RFC PR: [rust-lang/rfcs#3892](https://github.com/rust-lang/rfcs/pull/3892) | ||||||
| - Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | ||||||
|
|
||||||
| ## Summary | ||||||
| [summary]: #summary | ||||||
|
|
||||||
| FFI-compatible and calling-convention-compatible complex types are to be introduced into `core` to ensure synchronity with C primitives. | ||||||
|
|
||||||
| ## Motivation | ||||||
| [motivation]: #motivation | ||||||
|
|
||||||
| The definition of complex numbers in the C99 standard defines the _memory layout_ of a complex number but not its _calling convention_. | ||||||
| This makes crates like `num-complex` untenable for calling C FFI functions containing complex numbers without at least a level of indirection (`*const Complex`) or the like. | ||||||
| Only in `std` is it possible to make an additional repr to match the calling convention that C uses across FFI boundaries. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is FFI compatibility limited to std only? It's just like how we have all the types in
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's like |
||||||
| In essence, this RFC makes code like this: | ||||||
SciMind2460 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| ```C | ||||||
| extern double _Complex computes_function(double _Complex x); | ||||||
| ``` | ||||||
| callable in Rust without indirection: | ||||||
| ```rust | ||||||
| extern "C" { | ||||||
| fn computes_function(x: Complex<f64>) -> Complex<f64>; | ||||||
| } | ||||||
| fn main() { | ||||||
| let returned_value = computes_function(Complex<f64>::new(3, 4)) | ||||||
SciMind2460 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
| ``` | ||||||
| using the standard library's FFI-compatible complex numbers. | ||||||
|
|
||||||
| ## Guide-level explanation | ||||||
| [guide-level-explanation]: #guide-level-explanation | ||||||
|
|
||||||
| `Complex<T>` numbers can be instantiated as of any type using `Complex::new(re, im)` where `re` and `im` are of the same type (this includes all numbers). | ||||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| ```rust | ||||||
| let x = Complex::new(3.0, 4.0); | ||||||
| ``` | ||||||
|
Comment on lines
32
to
38
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussion: where should this type live? (redirecting discussion from the main PR thread to keep things organized)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe it should live in |
||||||
| They can even be passed as an array: | ||||||
| ```rust | ||||||
| let y = Complex::from([3.0, 4.0]); | ||||||
| ``` | ||||||
| or as a tuple: | ||||||
| ```rust | ||||||
| let z = Complex::from((3.0, 4.0)); | ||||||
| ``` | ||||||
| They can even be passed in polar form (but only as a float): | ||||||
| ```rust | ||||||
| let polar = Complex::from_polar(3.0, f32::PI/2.0); | ||||||
| ``` | ||||||
| They are added and multiplied as complexes are: | ||||||
| ```rust | ||||||
| let first = Complex::new(1.0, 2.0); | ||||||
| let second = Complex::new(3.0, 4.0); | ||||||
| let added = first + second; // 4 + 6i | ||||||
| let multiplied = first * second; // -4 + 10i | ||||||
| ``` | ||||||
|
|
||||||
| They can be divided using normal floating-point division | ||||||
| ```rust | ||||||
| let float_first = Complex::new(1.0, 2.0); | ||||||
| let float_second = Complex::new(3.0, 4.0); | ||||||
| let divided = float_second / float_first; // 2.4 - 0.2i | ||||||
| ``` | ||||||
|
|
||||||
| 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 | ||||||
| ``` | ||||||
| If you want to call certain C libraries with complex numbers, you use this type: | ||||||
| ```C | ||||||
| // in the C library | ||||||
| extern double _Complex computes_function(double _Complex x); | ||||||
| ``` | ||||||
| ```rust | ||||||
| // in YOUR Rust code | ||||||
| extern "C" { | ||||||
| fn computes_function(x: Complex<f64>) -> Complex<f64>; | ||||||
| } | ||||||
| fn main() { | ||||||
| let returned_value = computes_function(Complex::<f64>::new(3.0, 4.0)) | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Reference-level explanation | ||||||
| [reference-level-explanation]: #reference-level-explanation | ||||||
|
|
||||||
| Complex numbers will be implemented by using traits in the `core` crate: | ||||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| ``` | ||||||
| trait Float: Copy + Clone {} | ||||||
| impl Float for f32 {} | ||||||
| impl Float for f64 {} | ||||||
| ``` | ||||||
| Calls to some `libgcc` functions will also be needed and will be emitted by the backend via compiler-builtins, specifically `__mulsc3`, `__muldc3`, `__divsc3` and `__divdc3` for the proper and complete implementation of these types. | ||||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| ``` | ||||||
|
||||||
| ``` |
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No calculation is involved – the values are returned verbatim.
| have methods to calculate their real and imaginary part (`.re()` and `.im()`): | |
| have methods to return their real and imaginary parts (`.re()` and `.im()`): |
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These will all forward from std to external libraries as well?
(the incoherent bit is ok for inherent methods though, just like we do for regular floats)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they will be forwarded from Std and not core (if that's what you mean)
SciMind2460 marked this conversation as resolved.
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand what exactly this means. Who would want to rush to include complex numbers in their code? And who would be be left behind?
I think the biggest downside here is the increased complexity and API surface and implementation maintenance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
github put this reply in the wrong thread, afaict it was intended to be here.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other languages, where modules using a C API are possible, may also benefit, I think. If Rust modules can provide functionality handling complex numbers for those using a common ABI, it's a win-win for Rust and the other language.
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll note GCC has integer complex numbers as a C extension, which I think Rust should eventually support FFI with.
Uh oh!
There was an error while loading. Please reload this page.