# Complex Numbers (Pre-ACP)

**URL:** https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769
**Category:** language design
**Created:** [November 25, 2025, 10:15am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769 "2025-11-25T10:15:03Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 25, 2025, 10:15am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/1 "2025-11-25T10:15:03Z")

</div>

Continuing the discussion from [Standard complex number in std library](https://internals.rust-lang.org/t/standard-complex-number-in-std-library/23748)

# Proposal

## Problem statement

Currently, there is no stable counterpart to the C `_Complex` types, and a myriad of implementations exist on [crates.io](http://crates.io). Popular crates like `num-complex` exist, but more often there are implementations defined by the crates themselves, which, while compatible with the other types in having the exact same implementation, require a myriad of conversion functions to convert with each other. Additionally, there is no syntax supported like `1+2i` or `1+2j` for complex numbers. (This ACP doesn't cover this, but it does lay ground for future work in this area)

## Motivating examples or use cases

A scientific computing library's functions (can be written in C):

```c
// in comp
extern double _Complex computes_function(x: double _Complex);

```

can be represented in Rust without the need of complex structs and the like:

```rust
extern "C" {
  fn computes_function(x: c64) -> c64;
}
fn main() {
  let returned_value = computes_function(c32::new(3, 4))
}

```

with the special repr that only the standard library can provide. (This would, however, require that the complex numbers become lang items.)

## Solution sketch

Complex numbers will have a implementation similar to this:

```rust
// c16, c32, c64, c128 to be defined this way using f16, f32, f64 and f128 respectively
#[lang = "complex"] // defines a special C-compatible repr which matches the ABI
struct c32 {
  re: f32,
  im: f32
}

impl c32 {
  fn conjugate() { ... }
  // more function impls as desired
}
// All the trait impls as per LLVM intrinsics
impl Add for c32 {}
impl Sub for c32 {}
impl Mul for c32 {}
impl Div for c32 {}

// syntax can be changed to use j
// in main.rs
fn main() {
  println!("{}", Complex(1, 2); 
}

```

The complex numbers will serve as structs and all operations will be defined as a struct operation.

## Alternatives

### Don't put it into the std (status quo)

We could just not put complex numbers in the std and let the popular libraries work. This would be acceptable if not for improving FFI with C, as it already implements the \_Complex types and adding them to Rust would significantly improve the FFI experience with libraries already in C. I do not recommend this yet.

## Links and related work

[Standard complex number in std library](https://internals.rust-lang.org/t/standard-complex-number-in-std-library/23748)

## What happens now?

This issue contains an API change proposal (or ACP) and is part of the libs-api team [feature lifecycle](https://std-dev-guide.rust-lang.org/development/feature-lifecycle.html). Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.

## Possible responses

The libs team may respond in various different ways. First, the team will consider the _problem_ (this doesn't require any concrete solution or alternatives to have been proposed):

- We think this problem seems worth solving, and the standard library might be the right place to solve it.
- We think that this probably doesn't belong in the standard library.

Second, if there's a concrete solution:

- We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
- We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.

Edit: [The ACP transitioned into an RFC which is uploaded on GitHub here](https://github.com/rust-lang/rfcs/pull/3892)

Update: The RFC has been accepted! [Tracking issue here!](https://github.com/rust-lang/rust/issues/154023)

---

<div class="post-metadata">

### Author: ![R081n](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/r081n/32/12214_2.png) [@R081n](https://internals.rust-lang.org/u/R081n)
#### Post date: [November 25, 2025, 10:49am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/2 "2025-11-25T10:49:12Z")

</div>

A problem i see for FFI is that in C a complex number is not always passed as a struct.

On GNU \_Complex is sometimes passed in SSE registers, but sometimes also passed as two separate parameters, sometimes also like a normal struct.

But MSVC does not actually support \_Complex [Ms docs](https://learn.microsoft.com/en-us/cpp/c-runtime-library/complex-math-support?view=msvc-170)

---

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 25, 2025, 10:52am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/3 "2025-11-25T10:52:13Z")

</div>

AFAIK it is a part of the C99 standard ([Arithmetic types - cppreference.com](https://en.cppreference.com/w/c/language/arithmetic_types.html)) so I think that we can create a primitive that will have the implementation-specific FFI? MSVC does have \_FComplex and the like so I think we can get away with doing FFI on that front.

---

<div class="post-metadata">

### Author: ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)
#### Post date: [November 25, 2025, 4:47pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/4 "2025-11-25T16:47:11Z")

</div>

> [@R081n](#):
>
> A problem i see for FFI is that in C a complex number is not always passed as a struct.

This is not a problem — Rust itself also sometimes passes structs of two elements as separate values that may be in registers (a “scalar pair”). If compatibility with C is desired, the `Complex` struct can be given a special `#[repr]` which promises to match the C `_Complex` ABI when the generic parameter is a primitive float. It may technically be a new compiler feature, but all the pieces are (probably) already there.

---

<div class="post-metadata">

### Author: ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)
#### Post date: [November 25, 2025, 5:38pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/5 "2025-11-25T17:38:17Z")

</div>

> [@SciMind2460](#):
>
> ```rust
> impl Mul for Complex<T> {
> fn mul(self, other: Self) {
> Complex {
> re: self.re * other.re - self.im * other.im,
> im: self.im * other.re + self.re * other.im,
> }
> }
> }
> 
> ```

This formula for complex multiplication doesn't handle "intermediate overflow" correctly; there are situations where the mathematically correct result (computed in infinite precision) _would_ fit in T, but one or more of the intermediate products doesn't, so you don't get the right answer. Similar problems exist for division and complex norm. How do you plan to address this?

---

<div class="post-metadata">

### Author: ![toc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toc/32/6692_2.png) [@toc](https://internals.rust-lang.org/u/toc)
#### Post date: [November 26, 2025, 3:16am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/6 "2025-11-26T03:16:03Z")

</div>

> [@zackw](#):
>
> How do you plan to address this?

Answering out of turn, but is it by using the llvm intrinsics instead?

---

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 26, 2025, 8:07am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/7 "2025-11-26T08:07:05Z")

</div>

Yep, that was my idea. It's just that I was wondering if we wanted this as a primitive or a struct so I left it like that. Edited my post to use LLVM intrinsics instead.

(BTW, since this adds a new primitive to rust, would this technically not come under the scope of an ACP?)

---

<div class="post-metadata">

### Author: ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)
#### Post date: [November 26, 2025, 3:30pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/8 "2025-11-26T15:30:11Z")

</div>

This doesn't add a new primitive, unless you're talking about the syntax. But that can always be added later.

---

<div class="post-metadata">

### Author: ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)
#### Post date: [November 26, 2025, 7:24pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/9 "2025-11-26T19:24:02Z")

</div>

I'm not sure LLVM _does_ implement numerically safe complex multiply, at least not in all cases.\[1\] Still, "this is the compiler's job" is a good answer to the question I asked, and "the compiler has intrinsics for complex arithmetic that (in principle) handle all the floating-point corner cases and are legible to optimization, but Rust doesn't expose them" is IMO a stronger argument for including complex numbers in the stdlib than just "there are a lot of crates already that define complex types and they're not interoperable". (You do mention that LLVM has these intrinsics in your problem statement, but you don't, IMO, give that the importance it deserves.)

* * *

1. for example, [llvm-project/compiler-rt/lib/builtins/muldc3.c at 5017370a1ce5009aed2855b645194bc141f72a2d · llvm/llvm-project · GitHub](https://github.com/llvm/llvm-project/blob/5017370a1ce5009aed2855b645194bc141f72a2d/compiler-rt/lib/builtins/muldc3.c) handles the naive formula producing a NaN that ought to be Inf, but it doesn't look like it even tries to detect the situation where the difference of two infinite-precision intermediates would be in the _finite_ representable range of IEEE double.

---

<div class="post-metadata">

### Author: ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)
#### Post date: [November 26, 2025, 7:29pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/10 "2025-11-26T19:29:27Z")

</div>

> [@SciMind2460](#):
>
> LLVM has a intrinsic for this, but it is not used in Rust as yet.

Can you link where that is in the langref? None of the places it says "complex" (that I found) are about complex _numbers_.

---

<div class="post-metadata">

### Author: ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)
#### Post date: [November 26, 2025, 8:35pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/11 "2025-11-26T20:35:35Z")

</div>

For the purposes of making the simplest possible ACP, please leave out the bits involving new custom lang syntax, and assume that this will have a constructor like `c32::new(2.0, 4.0)`.

---

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 26, 2025, 10:31pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/12 "2025-11-26T22:31:44Z")

</div>

[MLIR does](https://mlir.llvm.org/docs/Dialects/ComplexOps/)

---

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 26, 2025, 10:34pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/13 "2025-11-26T22:34:01Z")

</div>

I agree. I'll add it as a major factor in the ACP and will change it as soon as I can.

---

<div class="post-metadata">

### Author: ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)
#### Post date: [November 27, 2025, 12:47am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/14 "2025-11-27T00:47:46Z")

</div>

Well rust doesn't use MLIR, so that's not particularly relevant? (MLIR has all kinds of dialects, like sparse tensors for example.)

Whereas if there was, say, a `llvm.complex.mul.f32` intrinsic that handled complex multiplication properly for us, that would be a stronger reason to have it built-in in some way, as it would be something a crate wouldn't use. (Like how [https://doc.rust-lang.org/std/primitive.u128.html#method.carrying\_mul\_add](https://doc.rust-lang.org/std/primitive.u128.html#method.carrying_mul_add) is implemented on LLVM in a way not possible in a crate, which is one reason it's nice to have as a `core` method.)

---

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 27, 2025, 8:09am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/15 "2025-11-27T08:09:48Z")

</div>

Hmm... It appears that [there were] ([⚙ D119284 [IR] Add intrinsics to represent complex multiply and divide instructions.](https://reviews.llvm.org/D119284)) [some plans](https://github.com/llvm/llvm-project/issues/5698) for complex numbers, but they are not entirely supported for now. It's odd because I thought there were some plans for doing so. I don't think this is a problem, as we can now use a platform dependent representation as a struct for the complex types. The advantage is still C FFI.

---

<div class="post-metadata">

### Author: ![user16251](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/user16251/32/10186_2.png) [@user16251](https://internals.rust-lang.org/u/user16251)
#### Post date: [November 28, 2025, 1:04pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/16 "2025-11-28T13:04:14Z")

</div>

Is there a standard ABI for complex numbers in FORTRAN?

---

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 28, 2025, 1:38pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/17 "2025-11-28T13:38:30Z")

</div>

[I don't think so](https://gitlab.com/x86-psABIs/x86-64-ABI/-/blob/master/x86-64-ABI/fortran.tex) since Fortran itself does not have a well defined ABI.

---

<div class="post-metadata">

### Author: ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)
#### Post date: [November 30, 2025, 3:55am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/18 "2025-11-30T03:55:03Z")

</div>

The ACP is very nearly complete. If there are no changes requested here, I'll submit it to the libs team. This is a final request for any additional feedback or changes I can incorporate.

---

<div class="post-metadata">

### Author: ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)
#### Post date: [November 30, 2025, 8:13am UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/19 "2025-11-30T08:13:00Z")

</div>

It's not clear from what you've written if the type is generic. It seems like it should be a generic `Complex<T>`, with optional type aliases `type c32 = Complex<f32>` and `type c64 = Complex<f64>`.

---

<div class="post-metadata">

### Author: ![tczajka](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tczajka/32/8923_2.png) [@tczajka](https://internals.rust-lang.org/u/tczajka)
#### Post date: [December 1, 2025, 6:20pm UTC](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769/20 "2025-12-01T18:20:44Z")

</div>

> [@josh](#):
>
> It seems like it should be a generic `Complex<T>` , with optional type aliases `type c32 = Complex<f32>` and `type c64 = Complex<f64>` .

Integral `T`, such as `Complex<i64>`, are also sometimes useful. These are [Gaussian integers](https://en.wikipedia.org/wiki/Gaussian_integer), useful for all kinds of things in number theory, and can be used for geometry when you're dealing with integral coordinates.

[Next page](https://internals.rust-lang.org/t/complex-numbers-pre-acp/23769.md?page=2)
