-
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 2 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,214 @@ | ||||
| - 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(x: double _Complex); | ||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
| ``` | ||||
| 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, 4); // this instantiates them as integers, not floats! | ||||
| ``` | ||||
| They can even be passed as an array: | ||||
| ```rust | ||||
| let y = Complex::from_array([3, 4]); | ||||
| ``` | ||||
| or as a tuple: | ||||
| ```rust | ||||
| let z = Complex::from_tuple((3, 4)); | ||||
| ``` | ||||
SciMind2460 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
| 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); | ||||
| ``` | ||||
| But the easiest way to usually instantiate them is by using them like this: | ||||
| ```rust | ||||
| let easy = 1 + 2.i() | ||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
| ``` | ||||
| where .i() turns a real number into a complex one transposing the real value to a complex value. | ||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
|
|
||||
| They are added and multiplied as complexes are: | ||||
| ```rust | ||||
| let first = 1 + 2.i() | ||||
| let second = 3 + 4.i(); | ||||
| let added = first + second; // 4 + 6.i() | ||||
| let multiplied = first * second; // -4 + 10.i() | ||||
| ``` | ||||
|
|
||||
| They can be divided using Gaussian division (if integers) and normal division (if floats): | ||||
| ```rust | ||||
| let first = 1 + 2.i(); | ||||
| let second = 3 + 4.i(); | ||||
| let divided = second / first; // 2 + 0.i() | ||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
| let float_first = 1.0 + 2.0.i(); | ||||
| let float_second = 3.0 + 4.0.i(); | ||||
| let divided = float_second / float_first; // 2.4 - 0.2.i() | ||||
| ``` | ||||
|
|
||||
| If the values are floating point, you can even calculate the complex sine, cosine and more: | ||||
| ```rust | ||||
| let val = 3 + 4.i(); | ||||
| let sine_cmplx = csin(3+4.i()); // 3.8537380379 - 27.016813258i | ||||
| ``` | ||||
| It's not too much of a problem to print them: | ||||
| ``` | ||||
| println!("{}, 1 + 2.i()); // prints 1 + 2i | ||||
| ``` | ||||
| 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(x: double _Complex); | ||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
| ``` | ||||
| ```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, 4)) | ||||
| } | ||||
| ``` | ||||
|
|
||||
| ## Reference-level explanation | ||||
| [reference-level-explanation]: #reference-level-explanation | ||||
|
|
||||
| Complex numbers will be implemented by using public traits in the `core` crate that implement as an abstraction numeric features such as: | ||||
| ``` | ||||
| trait PrimNum: Add + Sub + Mul + Div + Neg + SimdElement + Copy + Clone { | ||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
| fn zero(); | ||||
| fn one(); | ||||
| } | ||||
| trait PrimFloat: PrimNum { | ||||
| fn sin(); | ||||
| fn cos(); | ||||
| fn tan(); | ||||
| // etc! | ||||
| } | ||||
SciMind2460 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
| ``` | ||||
|
||||
| ``` |
Uh oh!
There was an error while loading. Please reload this page.