-
-
Notifications
You must be signed in to change notification settings - Fork 17.3k
add Div and Mul for Complex<{float}>
#162832
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
Changes from all commits
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,32 @@ | ||
| From 20d296e9a8b837e586fcc8fc648d4ab9687a2a47 Mon Sep 17 00:00:00 2001 | ||
| From: Folkert de Vries <folkert@folkertdev.nl> | ||
| Date: Mon, 28 Sep 2026 19:14:22 +0200 | ||
| Subject: [PATCH] sysroot_tests: Disable complex type tests | ||
|
|
||
| --- | ||
| coretests/tests/num/complex.rs | 2 ++ | ||
| 1 file changed, 2 insertions(+) | ||
|
|
||
| diff --git a/coretests/tests/num/complex.rs b/coretests/tests/num/complex.rs | ||
| index d73d04b1afc..289c0baec17 100644 | ||
| --- a/coretests/tests/num/complex.rs | ||
| +++ b/coretests/tests/num/complex.rs | ||
| @@ -75,6 +75,7 @@ fn complex_negation() { | ||
| } | ||
|
|
||
| #[test] | ||
| +#[cfg_attr(target_os = "windows", ignore = "hits an ABI issue with cranelift on windows")] | ||
| fn complex_multiplication() { | ||
| #[cfg(target_has_reliable_f16)] | ||
| assert_eq!(Complex::new(1.0f16, 2.0) * Complex::new(3.0, 4.0), Complex::new(-5.0, 10.0)); | ||
| @@ -105,6 +106,7 @@ fn complex_multiplication() { | ||
| } | ||
|
|
||
| #[test] | ||
| +#[cfg_attr(target_os = "windows", ignore = "hits an ABI issue with cranelift on windows")] | ||
| fn complex_div() { | ||
| #[cfg(target_has_reliable_f16)] | ||
| assert_eq!(Complex::new(2.0f16, 11.0) / Complex::new(2.0, 1.0), Complex::new(3.0, 4.0)); | ||
| -- | ||
| 2.43.0 | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| use crate::ops::{Add, Neg, Sub}; | ||
| use crate::num::imp::libm::complex::*; | ||
| use crate::ops::{Add, Div, Mul, Neg, Sub}; | ||
|
|
||
| /// A complex number. | ||
| #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
|
|
@@ -91,3 +92,54 @@ impl<T: Sub<Output = T>> Sub<T> for Complex<T> { | |
| Complex::new(self.re - rhs, self.im) | ||
| } | ||
| } | ||
|
|
||
| macro_rules! impl_complex_mul_div { | ||
| ($ty:ty, $mul:ident, $div:ident) => { | ||
| #[unstable(feature = "complex_numbers", issue = "154023")] | ||
| impl Mul for Complex<$ty> { | ||
| type Output = Self; | ||
|
|
||
| #[inline] | ||
| fn mul(self, rhs: Self) -> Self::Output { | ||
| let Complex { re: a, im: b } = self; | ||
| let Complex { re: c, im: d } = rhs; | ||
|
|
||
| let ac = a * c; | ||
| let bd = b * d; | ||
| let ad = a * d; | ||
| let bc = b * c; | ||
|
|
||
| let z = Complex::new(ac - bd, ad + bc); | ||
|
|
||
| // Only call the libcall when both components are NaN. | ||
| // | ||
| // The naive algorithm would return NaN + NaNi for an input like | ||
| // (1 + 0i) * (inf + infi). The libcall instead returns inf + infi. | ||
| // | ||
| // We duplicate the fast path here so that it can be inlined. We use a libcall | ||
| // for the NaN correction to reduce the size of `core`. | ||
| if z.re.is_nan() && z.im.is_nan() { | ||
| crate::hint::cold_path(); | ||
| $mul(a, b, c, d) | ||
| } else { | ||
| z | ||
| } | ||
| } | ||
|
Comment on lines
+102
to
+127
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. The comment says pretty much the same thing as the code, it would be helpful to explain why. Also mild preference for I think the optimization may pay off but it's unfortunate it means repeated work. Not too bad for hard floats but this means e.g. 12 additional function calls if you hit a NaN with f16. I wonder if there's a case to be made that these (and possibly other) libcalls should be
Contributor
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 wrote something, and now use And, this ABI etc was designed way before
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. I did mean more of a comment about the optimization going on here, i.e. why are we doing some things inline rather than going directly to the libcall |
||
| } | ||
|
|
||
| #[unstable(feature = "complex_numbers", issue = "154023")] | ||
| impl Div for Complex<$ty> { | ||
| type Output = Self; | ||
|
|
||
| #[inline] | ||
| fn div(self, rhs: Self) -> Self::Output { | ||
| $div(self.re, self.im, rhs.re, rhs.im) | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| impl_complex_mul_div!(f16, __rust_mulhc3, __rust_divhc3); | ||
| impl_complex_mul_div!(f32, __mulsc3, __divsc3); | ||
| impl_complex_mul_div!(f64, __muldc3, __divdc3); | ||
| impl_complex_mul_div!(f128, __rust_multc3, __rust_divtc3); | ||
Uh oh!
There was an error while loading. Please reload this page.
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.
Would it make sense to use algebraic operators here in case
$tyis{float}? This would make it possible to use FMA and FMS instructions on architectures which have those, such as ARM.View changes since the review
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 think we should go with algebraic operators here - it is good to limit the maximum possible error, and algebraic operators don't have any accuracy guarantees at all.
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.
mul_add_relaxedcould technically be used once that PR lands. But I think it's good to have a consistent result across platforms until we figure out exactly what we can say about allowed imprecision.