1use core::marker::PhantomData;
12use core::ops::{Add, Div, Mul, Rem, Sub};
13
14use num_traits::Bounded;
15
16use thermite::Swizzle;
17use thermite::element::{Element, FloatElement, SignedElement};
18use thermite::generic_array::{GenericArray, IntoArrayLength, typenum::Const};
19use thermite::mask::{GenericMask, GenericSelectable};
20use thermite::math::RealMathWithPolicy;
21use thermite::math::algorithms::reduce_in_place;
22use thermite::math::policy::DefaultPolicy;
23use thermite::register::SwizzleIndices;
24use thermite::vector::ops::{AddSubExt, AddSubExtMasked, NegMasked, Square, SquareMasked};
25use thermite::vector::{NewConst, NewVector, SplatConst, SplatVector, VectorValue, const_new, const_splat};
26use thermite::{LargeInt, features, prelude::*};
27
28use crate::{Complex, RealValue};
29
30pub trait RealFloatVector:
37 RealValue + FloatVector<Element: RealValue> + CastVector<Self> + RealMathWithPolicy + SwizzleVector
38{
39}
40
41impl<V> RealFloatVector for V where
42 V: RealValue + FloatVector<Element: RealValue> + CastVector<V> + RealMathWithPolicy + SwizzleVector
43{
44}
45
46impl<V: RealFloatVector> Swizzle<V::Lanes> for Complex<V> {
50 #[inline(always)]
51 fn swizzle(self, other: Self, indices: GenericArray<u32, V::Lanes>) -> Self {
52 Self {
53 re: self.re.swizzle(other.re, indices.clone()),
54 im: self.im.swizzle(other.im, indices),
55 }
56 }
57
58 #[inline(always)]
59 fn permute(self, indices: GenericArray<u32, V::Lanes>) -> Self {
60 Self {
61 re: self.re.permute(indices.clone()),
62 im: self.im.permute(indices),
63 }
64 }
65
66 #[inline(always)]
70 fn swizzle_const<I: SwizzleIndices<V::Lanes>>(self, other: Self) -> Self {
71 Self {
72 re: self.re.swizzle_const::<I>(other.re),
73 im: self.im.swizzle_const::<I>(other.im),
74 }
75 }
76
77 #[inline(always)]
78 fn permute_const<I: SwizzleIndices<V::Lanes>>(self) -> Self {
79 Self {
80 re: self.re.permute_const::<I>(),
81 im: self.im.permute_const::<I>(),
82 }
83 }
84}
85
86#[rustfmt::skip]
89impl<E: RealValue + Element> Element for Complex<E> {
90 type Signed = <E as Element>::Signed;
91 type Unsigned = <E as Element>::Unsigned;
92
93 const ZERO: Self = Self::ZERO;
94 const ONE: Self = Self::ONE;
95
96 const ORDER_MAX: Self = Self { re: E::ORDER_MAX, im: E::ORDER_MAX };
101 const ORDER_MIN: Self = Self { re: E::ORDER_MIN, im: E::ORDER_MIN };
102 const HAS_UNORDERED: bool = E::HAS_UNORDERED;
103
104 #[inline(always)] fn from_i8(value: i8) -> Self { Self::real(E::from_i8(value)) }
105 #[inline(always)] fn from_u8(value: u8) -> Self { Self::real(E::from_u8(value)) }
106 #[inline(always)] fn from_u16(value: u16) -> Self { Self::real(E::from_u16(value)) }
107}
108
109impl<E: RealValue + FloatElement> Complex<E> {
110 #[inline(always)]
113 fn elem_modulus(self) -> E {
114 E::sqrt(self.re.mul_add(self.re, self.im * self.im))
115 }
116}
117
118impl<E: RealValue + FloatElement> SignedElement for Complex<E> {
119 #[inline(always)]
121 fn abs(self) -> Self {
122 Self::real(self.elem_modulus())
123 }
124
125 #[inline(always)]
127 fn signum(self) -> Self {
128 let m = self.elem_modulus();
129
130 if m == E::ZERO {
131 return Self::ZERO;
132 }
133
134 Self::new(self.re / m, self.im / m)
135 }
136}
137
138pub struct ComplexIntConst<E, const VAL: LargeInt>(PhantomData<E>);
140
141pub struct ComplexRatioConst<E, const NUM: LargeInt, const DEN: LargeInt>(PhantomData<E>);
143
144impl<E: RealValue + FloatElement, const VAL: LargeInt> SplatConst<Complex<E>> for ComplexIntConst<E, VAL> {
145 const VALUE: Complex<E> = Complex::real(<E::ConstInt<VAL> as SplatConst<E>>::VALUE);
146}
147
148impl<E: RealValue + FloatElement, const NUM: LargeInt, const DEN: LargeInt> SplatConst<Complex<E>>
149 for ComplexRatioConst<E, NUM, DEN>
150{
151 const VALUE: Complex<E> = Complex::real(<E::ConstRatio<NUM, DEN> as SplatConst<E>>::VALUE);
152}
153
154#[rustfmt::skip]
155impl<E: RealValue + FloatElement> FloatElement for Complex<E> {
156 #[inline(always)]
159 fn sqrt(this: Self) -> Self {
160 let half = E::from_ratio(1, 2);
161
162 let t = E::sqrt((SignedElement::abs(this.re) + this.elem_modulus()) * half);
163
164 if t == E::ZERO {
165 return Self::ZERO;
166 }
167
168 let half_im = this.im * half;
169
170 if this.re >= E::ZERO {
171 Self::new(t, half_im / t)
172 } else {
173 let i = if this.im < E::ZERO { -t } else { t };
174
175 Self::new(SignedElement::abs(half_im) / t, i)
176 }
177 }
178
179 #[inline(always)] fn floor(this: Self) -> Self { Self::new(E::floor(this.re), E::floor(this.im)) }
181 #[inline(always)] fn ceil(this: Self) -> Self { Self::new(E::ceil(this.re), E::ceil(this.im)) }
182 #[inline(always)] fn round(this: Self) -> Self { Self::new(E::round(this.re), E::round(this.im)) }
183 #[inline(always)] fn trunc(this: Self) -> Self { Self::new(E::trunc(this.re), E::trunc(this.im)) }
184
185 #[inline(always)] fn next_up(this: Self) -> Self { Self::new(E::next_up(this.re), E::next_up(this.im)) }
186 #[inline(always)] fn next_down(this: Self) -> Self { Self::new(E::next_down(this.re), E::next_down(this.im)) }
187
188 #[inline(always)]
189 fn try_from_int(value: LargeInt) -> Option<Self> {
190 E::try_from_int(value).map(Self::real)
191 }
192
193 #[inline(always)]
194 fn try_from_ratio(n: LargeInt, d: LargeInt) -> Option<Self> {
195 E::try_from_ratio(n, d).map(Self::real)
196 }
197
198 const HAS_INFINITY: bool = E::HAS_INFINITY;
199 const HAS_SIGNED_ZERO: bool = E::HAS_SIGNED_ZERO;
200 const HAS_SUBNORMALS: bool = E::HAS_SUBNORMALS;
201
202 type ConstInt<const VAL: LargeInt> = ComplexIntConst<E, VAL>;
203 type ConstRatio<const NUM: LargeInt, const DEN: LargeInt> = ComplexRatioConst<E, NUM, DEN>;
204}
205
206impl<V: thermite::simd::HasIsa> thermite::simd::HasIsa for Complex<V> {
209 type Native = V::Native;
210
211 const ISA: thermite::isa::InstructionSet = V::ISA;
212}
213
214impl<V: RealFloatVector> GenericSelectable for Complex<V> {
215 type SelectableMask = <V as GenericSelectable>::SelectableMask;
216
217 #[inline(always)]
218 fn select<M>(mask: M, t: Self, f: Self) -> Self
219 where
220 Self::SelectableMask: CastMask<M>,
221 {
222 let mask = <Self::SelectableMask as CastMask<M>>::mask_from(mask);
223
224 Self::new(mask.select(t.re, f.re), mask.select(t.im, f.im))
225 }
226}
227
228#[rustfmt::skip]
229impl<V: RealFloatVector> Interleave for Complex<V> {
230 #[inline(always)]
231 fn interleave(self, other: Self) -> (Self, Self) {
232 let (re_lo, re_hi) = self.re.interleave(other.re);
233 let (im_lo, im_hi) = self.im.interleave(other.im);
234
235 (Self::new(re_lo, im_lo), Self::new(re_hi, im_hi))
236 }
237
238 #[inline(always)]
239 fn deinterleave(self, other: Self) -> (Self, Self) {
240 let (re_lo, re_hi) = self.re.deinterleave(other.re);
241 let (im_lo, im_hi) = self.im.deinterleave(other.im);
242
243 (Self::new(re_lo, im_lo), Self::new(re_hi, im_hi))
244 }
245}
246
247struct ComplexReSplat<E, V>(PhantomData<(E, V)>);
251struct ComplexImSplat<E, V>(PhantomData<(E, V)>);
252
253impl<E, V: RealFloatVector> SplatConst<V::Element> for ComplexReSplat<E, V>
254where
255 E: SplatConst<Complex<V::Element>>,
256{
257 const VALUE: V::Element = <E as SplatConst<Complex<V::Element>>>::VALUE.re;
258}
259
260impl<E, V: RealFloatVector> SplatConst<V::Element> for ComplexImSplat<E, V>
261where
262 E: SplatConst<Complex<V::Element>>,
263{
264 const VALUE: V::Element = <E as SplatConst<Complex<V::Element>>>::VALUE.im;
265}
266
267impl<V: RealFloatVector> SplatVector<Complex<V::Element>> for Complex<V> {
268 type Splat<T: SplatConst<Complex<V::Element>>> = Self;
269}
270
271impl<V: RealFloatVector, E: SplatConst<Complex<V::Element>>> VectorValue<E, Complex<V>> for Complex<V> {
272 const VALUE: Complex<V> = Complex {
273 re: const_splat::<V, ComplexReSplat<E, V>>(),
274 im: const_splat::<V, ComplexImSplat<E, V>>(),
275 };
276}
277
278struct ComplexReNew<C, V>(PhantomData<(C, V)>);
280struct ComplexImNew<C, V>(PhantomData<(C, V)>);
281
282macro_rules! impl_new_const {
283 ($($carrier:ident => $field:ident),* $(,)?) => {$(
284 impl<C, V: RealFloatVector> NewConst<V::Element, V::Lanes> for $carrier<C, V>
285 where
286 C: NewConst<Complex<V::Element>, V::Lanes>,
287 {
288 const VALUES: GenericArray<V::Element, V::Lanes> = const {
289 let c_vals = C::VALUES;
290 let src = c_vals.as_slice();
291 let mut out: GenericArray<V::Element, V::Lanes> = unsafe { core::mem::zeroed() };
292 let dst = out.as_mut_slice();
293 let mut i = 0;
294 while i < V::LANES {
295 dst[i] = src[i].$field;
296 i += 1;
297 }
298 core::mem::forget(c_vals);
299 out
300 };
301 }
302 )*};
303}
304
305impl_new_const!(ComplexReNew => re, ComplexImNew => im);
306
307pub struct ComplexNewImpl;
309
310impl<T, V: RealFloatVector> VectorValue<T, Complex<V>> for ComplexNewImpl
311where
312 T: NewConst<Complex<V::Element>, V::Lanes>,
313{
314 const VALUE: Complex<V> = Complex {
315 re: const_new::<V, V::Lanes, ComplexReNew<T, V>>(),
316 im: const_new::<V, V::Lanes, ComplexImNew<T, V>>(),
317 };
318}
319
320impl<V: RealFloatVector> NewVector<Complex<V::Element>, V::Lanes> for Complex<V> {
321 type New<T: NewConst<Complex<V::Element>, V::Lanes>> = ComplexNewImpl;
322}
323
324impl<FROM, TO> CastVector<Complex<FROM>> for Complex<TO>
327where
328 FROM: RealFloatVector + CastVector<TO>,
329 TO: RealFloatVector + CastVector<FROM>,
330{
331 #[inline(always)]
332 fn cast_into(self) -> Complex<FROM> {
333 Complex::<FROM>::cast_from(self)
334 }
335
336 #[inline(always)]
337 fn cast_from(from: Complex<FROM>) -> Self {
338 Complex::new(TO::cast_from(from.re), TO::cast_from(from.im))
339 }
340}
341
342#[rustfmt::skip]
345impl<V: RealFloatVector> crate::math::specialized::ComplexVector for Complex<V> {
346 type Real = V;
347
348 #[inline(always)] fn re(self) -> V { self.re }
349 #[inline(always)] fn im(self) -> V { self.im }
350 #[inline(always)] fn from_parts(re: V, im: V) -> Self { Complex::new(re, im) }
351
352 #[inline(always)]
353 unsafe fn store_streaming_block(self, ptr: *mut Self) {
354 unsafe {
360 self.re.store_streaming((&raw mut (*ptr).re).cast());
361 self.im.store_streaming((&raw mut (*ptr).im).cast());
362 }
363 }
364
365 #[inline(always)] fn conj(self) -> Self { Complex::conj(self) }
368 #[inline(always)] fn norm_sqr(self) -> V { Complex::norm_sqr(self) }
369 #[inline(always)] fn inv(self) -> Self { Complex::inv(self) }
370
371 #[inline(always)] fn norm_l1(self) -> V { self.re.abs() + self.im.abs() }
372}
373
374#[inline(always)]
383fn radix_per_component<V: RealFloatVector, const N: usize>(
384 inputs: [Complex<V>; N],
385 f: impl Fn([V; N]) -> [V; N],
386) -> [Complex<V>; N] {
387 let (mut re, mut im) = ([V::EMPTY; N], [V::EMPTY; N]);
388
389 let mut i = 0;
390 while i < N {
391 re[i] = inputs[i].re;
392 im[i] = inputs[i].im;
393 i += 1;
394 }
395
396 let re = f(re);
397 let im = f(im);
398
399 let mut out = [Complex::<V>::EMPTY; N];
400
401 let mut i = 0;
402 while i < N {
403 out[i] = Complex::new(re[i], im[i]);
404 i += 1;
405 }
406
407 out
408}
409
410impl<V: RealFloatVector> Complex<V> {
411 #[inline(always)]
413 pub fn splat_parts(re: V::Element, im: V::Element) -> Self {
414 Self::new(V::splat(re), V::splat(im))
415 }
416}
417
418impl<V: RealFloatVector> GenericVector for Complex<V> {
419 type Element = Complex<V::Element>;
420
421 const EMPTY: Self = Self::ZERO;
422 const LANES: usize = V::LANES;
423
424 type Lanes = V::Lanes;
425
426 type Unsigned = V::Unsigned;
427 type Signed = V::Signed;
428 type Mask = V::Mask;
429
430 #[inline(always)]
431 fn new<const N: usize>(value: [Self::Element; N]) -> Self
432 where
433 Const<N>: IntoArrayLength<ArrayLength = Self::Lanes>,
434 {
435 let mut re = [<V::Element as Element>::ZERO; N];
436 let mut im = [<V::Element as Element>::ZERO; N];
437
438 let mut i = 0;
439 while i < N {
440 re[i] = value[i].re;
441 im[i] = value[i].im;
442 i += 1;
443 }
444
445 Complex::new(V::new(re), V::new(im))
446 }
447
448 #[inline(always)]
449 fn into_array(self) -> GenericArray<Self::Element, Self::Lanes> {
450 let mut arr = GenericArray::default();
451
452 for i in 0..Self::LANES {
453 arr[i] = Complex::new(self.re.extractv(i), self.im.extractv(i));
454 }
455
456 arr
457 }
458
459 #[inline(always)]
460 fn splat(value: Self::Element) -> Self {
461 Self::splat_parts(value.re, value.im)
462 }
463
464 #[inline(always)]
465 fn single(value: Self::Element) -> Self {
466 Complex::new(V::single(value.re), V::single(value.im))
467 }
468
469 #[inline(always)]
472 unsafe fn load(ptr: *const Self::Element) -> Self {
473 unsafe { Self::load_unaligned(ptr) }
474 }
475
476 #[inline(always)]
480 unsafe fn load_unaligned(ptr: *const Self::Element) -> Self {
481 let [out] = unsafe { Self::load_deinterleaved::<1>(ptr) };
482 out
483 }
484
485 #[inline(always)]
486 unsafe fn load_streaming(ptr: *const Self::Element) -> Self {
487 unsafe { Self::load(ptr) }
488 }
489
490 #[inline(always)]
491 fn interleave_by<const GROUP: usize>(self, other: Self) -> (Self, Self) {
492 let (re_lo, re_hi) = self.re.interleave_by::<GROUP>(other.re);
493 let (im_lo, im_hi) = self.im.interleave_by::<GROUP>(other.im);
494 (Self::new(re_lo, im_lo), Self::new(re_hi, im_hi))
495 }
496
497 #[inline(always)]
498 fn deinterleave_by<const GROUP: usize>(self, other: Self) -> (Self, Self) {
499 let (re_lo, re_hi) = self.re.deinterleave_by::<GROUP>(other.re);
500 let (im_lo, im_hi) = self.im.deinterleave_by::<GROUP>(other.im);
501 (Self::new(re_lo, im_lo), Self::new(re_hi, im_hi))
502 }
503
504 #[inline(always)]
505 fn interleave_radix<const N: usize>(inputs: [Self; N]) -> [Self; N] {
506 radix_per_component::<V, N>(inputs, V::interleave_radix::<N>)
507 }
508
509 #[inline(always)]
510 fn deinterleave_radix<const N: usize>(inputs: [Self; N]) -> [Self; N] {
511 radix_per_component::<V, N>(inputs, V::deinterleave_radix::<N>)
512 }
513
514 #[inline(always)]
515 fn deinterleave_radix_by<const N: usize, const GROUP: usize>(inputs: [Self; N]) -> [Self; N] {
516 radix_per_component::<V, N>(inputs, V::deinterleave_radix_by::<N, GROUP>)
517 }
518
519 #[inline(always)]
520 fn interleave_radix_by<const N: usize, const GROUP: usize>(inputs: [Self; N]) -> [Self; N] {
521 radix_per_component::<V, N>(inputs, V::interleave_radix_by::<N, GROUP>)
522 }
523
524 #[inline(always)]
529 unsafe fn load_deinterleaved<const M: usize>(ptr: *const Self::Element) -> [Self; M] {
530 let groups = unsafe { V::load_deinterleaved_grouped::<M, 1>(ptr as *const V::Element) };
531
532 let mut out = [Self::EMPTY; M];
533 let mut j = 0;
534 while j < M {
535 out[j] = Complex::new(groups[j].head, groups[j].tail[0]);
536 j += 1;
537 }
538 out
539 }
540
541 #[inline(always)]
543 unsafe fn store_interleaved<const M: usize>(ptr: *mut Self::Element, values: [Self; M]) {
544 let mut groups = [StreamGroup {
545 head: V::ZERO,
546 tail: [V::ZERO; 1],
547 }; M];
548
549 let mut j = 0;
550 while j < M {
551 groups[j] = StreamGroup {
552 head: values[j].re,
553 tail: [values[j].im],
554 };
555 j += 1;
556 }
557
558 unsafe { V::store_interleaved_grouped::<M, 1>(ptr as *mut V::Element, groups) }
559 }
560
561 #[inline(always)]
562 unsafe fn load_m(src: Self, mask: Self::Mask, ptr: *const Self::Element) -> Self {
563 let ptr = ptr as *const V::Element;
564
565 let (a_mask, b_mask) = mask.interleave(mask);
568 let (src_a, src_b) = src.re.interleave(src.im);
569
570 let a = unsafe { V::load_m(src_a, a_mask, ptr) };
571 let b = unsafe { V::load_m(src_b, b_mask, ptr.add(V::LANES)) };
572
573 let (re, im) = a.deinterleave(b);
574 Complex::new(re, im)
575 }
576
577 #[inline(always)]
578 unsafe fn load_z(mask: Self::Mask, ptr: *const Self::Element) -> Self {
579 unsafe { Self::load_m(Self::EMPTY, mask, ptr) }
580 }
581
582 #[inline(always)]
584 unsafe fn store(self, ptr: *mut Self::Element) {
585 unsafe { self.store_unaligned(ptr) }
586 }
587
588 #[inline(always)]
589 unsafe fn store_unaligned(self, ptr: *mut Self::Element) {
590 unsafe { Self::store_interleaved::<1>(ptr, [self]) }
591 }
592
593 #[inline(always)]
594 unsafe fn store_streaming(self, ptr: *mut Self::Element) {
595 unsafe { self.store(ptr) }
596 }
597
598 #[inline(always)]
599 unsafe fn store_masked(self, mask: Self::Mask, ptr: *mut Self::Element) {
600 let ptr = ptr as *mut V::Element;
601
602 let (a_mask, b_mask) = mask.interleave(mask);
603 let (a, b) = self.re.interleave(self.im);
604
605 unsafe {
606 a.store_masked(a_mask, ptr);
607 b.store_masked(b_mask, ptr.add(V::LANES));
608 }
609 }
610
611 #[inline(always)]
612 unsafe fn lookup_unchecked(values: &[Self::Element], indices: Self::Unsigned) -> Self {
613 let floats = unsafe { core::slice::from_raw_parts(values.as_ptr() as *const V::Element, values.len() * 2) };
617
618 let re_idx = indices << 1;
619 let im_idx = re_idx + Self::Unsigned::ONE;
620
621 let re = unsafe { V::lookup_unchecked(floats, re_idx) };
622 let im = unsafe { V::lookup_unchecked(floats, im_idx) };
623
624 Complex::new(re, im)
625 }
626
627 #[inline(always)]
628 fn broadcast<const I: usize>(self) -> Self {
629 Complex::new(V::broadcast::<I>(self.re), V::broadcast::<I>(self.im))
630 }
631
632 #[inline(always)]
633 fn broadcastv(self, idx: usize) -> Self {
634 Complex::new(self.re.broadcastv(idx), self.im.broadcastv(idx))
635 }
636
637 #[inline(always)]
638 fn extract<const I: usize>(self) -> Self::Element {
639 Complex::new(V::extract::<I>(self.re), V::extract::<I>(self.im))
640 }
641
642 #[inline(always)]
643 fn extractv(self, idx: usize) -> Self::Element {
644 Complex::new(self.re.extractv(idx), self.im.extractv(idx))
645 }
646
647 #[inline(always)]
648 fn insert<const I: usize>(self, value: Self::Element) -> Self {
649 Complex::new(V::insert::<I>(self.re, value.re), V::insert::<I>(self.im, value.im))
650 }
651
652 #[inline(always)]
653 fn insertv(self, idx: usize, value: Self::Element) -> Self {
654 Complex::new(self.re.insertv(idx, value.re), self.im.insertv(idx, value.im))
655 }
656
657 #[inline(always)]
658 fn reverse(self) -> Self {
659 Complex::new(self.re.reverse(), self.im.reverse())
660 }
661
662 #[inline(always)]
663 fn swap_bytes(self) -> Self {
664 Complex::new(self.re.swap_bytes(), self.im.swap_bytes())
665 }
666
667 #[inline(always)]
668 fn zz(self, mask: Self::Mask) -> Self {
669 Complex::new(self.re.zz(mask), self.im.zz(mask))
670 }
671
672 #[inline(always)]
673 fn nz(self, mask: Self::Mask) -> Self {
674 Complex::new(self.re.nz(mask), self.im.nz(mask))
675 }
676
677 #[inline(always)]
678 fn compress(self, mask: Self::Mask) -> Self {
679 Complex::new(self.re.compress(mask), self.im.compress(mask))
680 }
681
682 #[inline(always)]
683 fn compress_z(self, mask: Self::Mask) -> Self {
684 Complex::new(self.re.compress_z(mask), self.im.compress_z(mask))
685 }
686
687 #[inline(always)]
692 fn compress_m(self, src: Self, mask: Self::Mask) -> Self {
693 Complex::new(self.re.compress_m(src.re, mask), self.im.compress_m(src.im, mask))
694 }
695
696 #[inline(always)]
697 fn expand(self, mask: Self::Mask) -> Self {
698 Complex::new(self.re.expand(mask), self.im.expand(mask))
699 }
700
701 #[inline(always)]
702 fn expand_z(self, mask: Self::Mask) -> Self {
703 Complex::new(self.re.expand_z(mask), self.im.expand_z(mask))
704 }
705
706 #[inline(always)]
707 fn expand_m(self, src: Self, mask: Self::Mask) -> Self {
708 Complex::new(self.re.expand_m(src.re, mask), self.im.expand_m(src.im, mask))
709 }
710
711 #[inline(always)]
712 fn align<const OFFSET: usize>(self, other: Self) -> Self {
713 Complex::new(self.re.align::<OFFSET>(other.re), self.im.align::<OFFSET>(other.im))
714 }
715
716 const HAS_NATIVE_ALIGN: bool = V::HAS_NATIVE_ALIGN;
718
719 #[inline(always)]
720 fn map<F>(mut self, f: F) -> Self
721 where
722 F: Fn(Self::Element) -> Self::Element,
723 {
724 for i in 0..Self::LANES {
725 self = self.insertv(i, f(self.extractv(i)));
726 }
727 self
728 }
729
730 #[inline(always)]
731 fn fold<F>(self, mut init: Self::Element, f: F) -> Self::Element
732 where
733 F: Fn(Self::Element, Self::Element) -> Self::Element,
734 {
735 for i in 0..Self::LANES {
736 init = f(init, self.extractv(i));
737 }
738 init
739 }
740
741 #[inline(always)]
742 fn reduce<F>(self, f: F) -> Self::Element
743 where
744 F: Fn(Self::Element, Self::Element) -> Self::Element,
745 {
746 let mut result = self.extractv(0);
747 for i in 1..Self::LANES {
748 result = f(result, self.extractv(i));
749 }
750 result
751 }
752
753 #[rustfmt::skip]
754 #[inline(always)] fn splat_m(src: Self, mask: Self::Mask, value: Self::Element) -> Self { mask.select(Self::splat(value), src) }
755 #[rustfmt::skip]
756 #[inline(always)] fn splat_z(mask: Self::Mask, value: Self::Element) -> Self { mask.select(Self::splat(value), Self::EMPTY) }
757 #[rustfmt::skip]
758 #[inline(always)] fn broadcast_c<const I: usize>(self, mask: Self::Mask) -> Self { mask.select(self.broadcast::<I>(), self) }
759 #[rustfmt::skip]
760 #[inline(always)] fn broadcast_m<const I: usize>(self, src: Self, mask: Self::Mask) -> Self { mask.select(self.broadcast::<I>(), src) }
761 #[rustfmt::skip]
762 #[inline(always)] fn broadcast_z<const I: usize>(self, mask: Self::Mask) -> Self { mask.select(self.broadcast::<I>(), Self::EMPTY) }
763 #[rustfmt::skip]
764 #[inline(always)] fn broadcastv_c(self, mask: Self::Mask, idx: usize) -> Self { mask.select(self.broadcastv(idx), self) }
765 #[rustfmt::skip]
766 #[inline(always)] fn broadcastv_m(self, src: Self, mask: Self::Mask, idx: usize) -> Self { mask.select(self.broadcastv(idx), src) }
767 #[rustfmt::skip]
768 #[inline(always)] fn broadcastv_z(self, mask: Self::Mask, idx: usize) -> Self { mask.select(self.broadcastv(idx), Self::EMPTY) }
769 #[rustfmt::skip]
770 #[inline(always)] fn reverse_c(self, mask: Self::Mask) -> Self { mask.select(self.reverse(), self) }
771 #[rustfmt::skip]
772 #[inline(always)] fn reverse_m(self, src: Self, mask: Self::Mask) -> Self { mask.select(self.reverse(), src) }
773 #[rustfmt::skip]
774 #[inline(always)] fn reverse_z(self, mask: Self::Mask) -> Self { mask.select(self.reverse(), Self::EMPTY) }
775 #[rustfmt::skip]
776 #[inline(always)] fn swap_bytes_c(self, mask: Self::Mask) -> Self { mask.select(self.swap_bytes(), self) }
777 #[rustfmt::skip]
778 #[inline(always)] fn swap_bytes_m(self, src: Self, mask: Self::Mask) -> Self { mask.select(self.swap_bytes(), src) }
779 #[rustfmt::skip]
780 #[inline(always)] fn swap_bytes_z(self, mask: Self::Mask) -> Self { mask.select(self.swap_bytes(), Self::EMPTY) }
781}
782
783#[rustfmt::skip]
786impl<V: RealFloatVector> PartialOrdVector for Complex<V> {
787 #[inline(always)]
788 fn cmp_eq(self, other: Self) -> Self::Mask {
789 self.re.cmp_eq(other.re) & self.im.cmp_eq(other.im)
790 }
791
792 #[inline(always)]
793 fn cmp_ne(self, other: Self) -> Self::Mask {
794 self.re.cmp_ne(other.re) | self.im.cmp_ne(other.im)
795 }
796
797 #[inline(always)]
799 fn cmp_lt(self, other: Self) -> Self::Mask {
800 let re_lt = self.re.cmp_lt(other.re);
801 let re_eq = self.re.cmp_eq(other.re);
802 let im_lt = self.im.cmp_lt(other.im);
803
804 GenericMask::ternlog::<{ thermite::ternlog_imm!(A | (B & C)) }>(re_lt, re_eq, im_lt)
805 }
806
807 #[inline(always)]
808 fn cmp_gt(self, other: Self) -> Self::Mask {
809 let re_gt = self.re.cmp_gt(other.re);
810 let re_eq = self.re.cmp_eq(other.re);
811 let im_gt = self.im.cmp_gt(other.im);
812
813 GenericMask::ternlog::<{ thermite::ternlog_imm!(A | (B & C)) }>(re_gt, re_eq, im_gt)
814 }
815
816 #[inline(always)]
817 fn cmp_le(self, other: Self) -> Self::Mask {
818 let re_lt = self.re.cmp_lt(other.re);
819 let re_eq = self.re.cmp_eq(other.re);
820 let im_le = self.im.cmp_le(other.im);
821
822 GenericMask::ternlog::<{ thermite::ternlog_imm!(A | (B & C)) }>(re_lt, re_eq, im_le)
823 }
824
825 #[inline(always)]
826 fn cmp_ge(self, other: Self) -> Self::Mask {
827 let re_gt = self.re.cmp_gt(other.re);
828 let re_eq = self.re.cmp_eq(other.re);
829 let im_ge = self.im.cmp_ge(other.im);
830
831 GenericMask::ternlog::<{ thermite::ternlog_imm!(A | (B & C)) }>(re_gt, re_eq, im_ge)
832 }
833}
834
835macro_rules! impl_masked {
838 (MUL_ADD: $($method:ident),*) => {paste::paste! {
839 impl<V: RealFloatVector, A, B> thermite::vector::ops::MulAddExtMasked<V::Mask, A, B> for Complex<V>
840 where
841 Complex<V>: thermite::vector::ops::MulAddExt<A, B, Output = Self>,
842 {
843 $(
844 #[inline(always)]
845 fn [<$method _c>](self, mask: V::Mask, a: A, b: B) -> Self {
846 mask.select(self.$method(a, b), self)
847 }
848 #[inline(always)]
849 fn [<$method _m>](self, src: Self, mask: V::Mask, a: A, b: B) -> Self {
850 mask.select(self.$method(a, b), src)
851 }
852 #[inline(always)]
853 fn [<$method _z>](self, mask: V::Mask, a: A, b: B) -> Self {
854 mask.select(self.$method(a, b), Self::EMPTY)
855 }
856 )*
857 }
858
859 impl<V: RealFloatVector, A, B> thermite::vector::ops::MulAddAssignExtMasked<V::Mask, A, B> for Complex<V>
860 where
861 Complex<V>: thermite::vector::ops::MulAddExt<A, B, Output = Self>,
862 {
863 $(
864 #[inline(always)]
865 fn [<$method _assign_c>](&mut self, mask: V::Mask, a: A, b: B) {
866 *self = mask.select(self.$method(a, b), *self);
867 }
868 #[inline(always)]
869 fn [<$method _assign_m>](&mut self, src: Self, mask: V::Mask, a: A, b: B) {
870 *self = mask.select(self.$method(a, b), src);
871 }
872 #[inline(always)]
873 fn [<$method _assign_z>](&mut self, mask: V::Mask, a: A, b: B) {
874 *self = mask.select(self.$method(a, b), Self::EMPTY);
875 }
876 )*
877 }
878 }};
879
880 ($trait:ident::$method:ident) => {paste::paste! {
881 impl<V: RealFloatVector, Rhs> thermite::vector::ops::[<$trait Masked>]<V::Mask, Rhs> for Complex<V>
882 where
883 Complex<V>: core::ops::$trait<Rhs, Output = Self>,
884 {
885 #[inline(always)]
886 fn [<$method _c>](self, mask: V::Mask, rhs: Rhs) -> Self {
887 mask.select(self.$method(rhs), self)
888 }
889 #[inline(always)]
890 fn [<$method _m>](self, src: Self, mask: V::Mask, rhs: Rhs) -> Self {
891 mask.select(self.$method(rhs), src)
892 }
893 #[inline(always)]
894 fn [<$method _z>](self, mask: V::Mask, rhs: Rhs) -> Self {
895 mask.select(self.$method(rhs), Self::EMPTY)
896 }
897 }
898
899 impl<V: RealFloatVector, Rhs> thermite::vector::ops::[<$trait AssignMasked>]<V::Mask, Rhs> for Complex<V>
900 where
901 Complex<V>: core::ops::$trait<Rhs, Output = Self>,
902 {
903 #[inline(always)]
904 fn [<$method _assign_c>](&mut self, mask: V::Mask, rhs: Rhs) {
905 *self = mask.select(self.$method(rhs), *self);
906 }
907 #[inline(always)]
908 fn [<$method _assign_m>](&mut self, src: Self, mask: V::Mask, rhs: Rhs) {
909 *self = mask.select(self.$method(rhs), src);
910 }
911 #[inline(always)]
912 fn [<$method _assign_z>](&mut self, mask: V::Mask, rhs: Rhs) {
913 *self = mask.select(self.$method(rhs), Self::EMPTY);
914 }
915 }
916 }};
917}
918
919impl_masked!(MUL_ADD: mul_add, mul_sub, nmul_add, nmul_sub, mul_adde, mul_sube, nmul_adde, nmul_sube);
920impl_masked!(Add::add);
921impl_masked!(Sub::sub);
922impl_masked!(Mul::mul);
923impl_masked!(Div::div);
924impl_masked!(Rem::rem);
925
926#[inline(always)]
937fn neg_even_complex<V: RealFloatVector>(x: Complex<V>) -> Complex<V> {
938 Complex::new(V::ZERO.addsub(x.re), V::ZERO.addsub(x.im))
940}
941
942impl<V: RealFloatVector> AddSubExt for Complex<V> {
943 type Output = Self;
944
945 #[inline(always)]
946 fn addsub(self, b: Self) -> Self {
947 self + neg_even_complex(b)
948 }
949 #[inline(always)]
950 fn fmaddsub(self, b: Self, c: Self) -> Self {
951 self.mul_adde(b, neg_even_complex(c))
952 }
953 #[inline(always)]
954 fn fmsubadd(self, b: Self, c: Self) -> Self {
955 self.mul_sube(b, neg_even_complex(c))
956 }
957}
958
959impl<V: RealFloatVector> AddSubExtMasked<V::Mask> for Complex<V> {
960 #[inline(always)]
961 fn addsub_c(self, mask: V::Mask, b: Self) -> Self {
962 mask.select(self.addsub(b), self)
963 }
964 #[inline(always)]
965 fn addsub_m(self, src: Self, mask: V::Mask, b: Self) -> Self {
966 mask.select(self.addsub(b), src)
967 }
968 #[inline(always)]
969 fn addsub_z(self, mask: V::Mask, b: Self) -> Self {
970 mask.select(self.addsub(b), Self::EMPTY)
971 }
972
973 #[inline(always)]
974 fn fmaddsub_c(self, mask: V::Mask, b: Self, c: Self) -> Self {
975 mask.select(self.fmaddsub(b, c), self)
976 }
977 #[inline(always)]
978 fn fmaddsub_m(self, src: Self, mask: V::Mask, b: Self, c: Self) -> Self {
979 mask.select(self.fmaddsub(b, c), src)
980 }
981 #[inline(always)]
982 fn fmaddsub_z(self, mask: V::Mask, b: Self, c: Self) -> Self {
983 mask.select(self.fmaddsub(b, c), Self::EMPTY)
984 }
985
986 #[inline(always)]
987 fn fmsubadd_c(self, mask: V::Mask, b: Self, c: Self) -> Self {
988 mask.select(self.fmsubadd(b, c), self)
989 }
990 #[inline(always)]
991 fn fmsubadd_m(self, src: Self, mask: V::Mask, b: Self, c: Self) -> Self {
992 mask.select(self.fmsubadd(b, c), src)
993 }
994 #[inline(always)]
995 fn fmsubadd_z(self, mask: V::Mask, b: Self, c: Self) -> Self {
996 mask.select(self.fmsubadd(b, c), Self::EMPTY)
997 }
998}
999
1000impl<V: RealFloatVector> SquareMasked<V::Mask> for Complex<V> {
1001 #[inline(always)]
1002 fn square_c(self, mask: V::Mask) -> Self::Output {
1003 mask.select(self.square(), self)
1004 }
1005
1006 #[inline(always)]
1007 fn square_m(self, src: Self, mask: V::Mask) -> Self::Output {
1008 mask.select(self.square(), src)
1009 }
1010
1011 #[inline(always)]
1012 fn square_z(self, mask: V::Mask) -> Self::Output {
1013 mask.select(self.square(), Self::ZERO)
1014 }
1015}
1016
1017macro_rules! complex_masked {
1020 (unary: $($m:ident),* $(,)?) => { paste::paste! {
1021 $(
1022 #[inline(always)] fn [<$m _c>](self, mask: Self::Mask) -> Self { mask.select(self.$m(), self) }
1023 #[inline(always)] fn [<$m _m>](self, src: Self, mask: Self::Mask) -> Self { mask.select(self.$m(), src) }
1024 #[inline(always)] fn [<$m _z>](self, mask: Self::Mask) -> Self { mask.select(self.$m(), Self::ZERO) }
1025 )*
1026 }};
1027 (binary: $($m:ident),* $(,)?) => { paste::paste! {
1028 $(
1029 #[inline(always)] fn [<$m _c>](self, mask: Self::Mask, rhs: Self) -> Self { mask.select(self.$m(rhs), self) }
1030 #[inline(always)] fn [<$m _m>](self, src: Self, mask: Self::Mask, rhs: Self) -> Self { mask.select(self.$m(rhs), src) }
1031 #[inline(always)] fn [<$m _z>](self, mask: Self::Mask, rhs: Self) -> Self { mask.select(self.$m(rhs), Self::ZERO) }
1032 )*
1033 }};
1034}
1035
1036#[rustfmt::skip]
1039impl<V: RealFloatVector> Bounded for Complex<V> {
1040 #[inline(always)] fn min_value() -> Self { Complex::new(V::MIN, V::MIN) }
1041 #[inline(always)] fn max_value() -> Self { Complex::new(V::MAX, V::MAX) }
1042}
1043
1044#[rustfmt::skip]
1045impl<V: RealFloatVector> thermite::sort::SortKey<Self> for Complex<V> {
1049 #[inline(always)]
1050 fn key_lt(a: Self, b: Self) -> V::Mask {
1051 a.cmp_lt(b)
1052 }
1053}
1054
1055#[inline(always)]
1059fn sort_lanes_scalar<V: NumericVector, O: thermite::sort::SortOrder>(v: V) -> V
1060where
1061 V::Element: PartialOrd,
1062{
1063 let mut out = v;
1064 let mut i = 1;
1065 while i < V::LANES {
1066 let key = out.extractv(i);
1067 let mut j = i;
1068 while j > 0 {
1069 let prev = out.extractv(j - 1);
1070 let misplaced = if O::IS_ASCENDING { prev > key } else { prev < key };
1071 if !misplaced {
1072 break;
1073 }
1074 out = out.insertv(j, prev);
1075 j -= 1;
1076 }
1077 out = out.insertv(j, key);
1078 i += 1;
1079 }
1080 out
1081}
1082
1083impl<V: RealFloatVector> NumericVector for Complex<V> {
1084 #[inline(always)]
1088 fn to_signed_integer(self) -> Self::Signed {
1089 self.re.to_signed_integer()
1090 }
1091
1092 #[inline(always)]
1093 fn from_signed_integer(v: Self::Signed) -> Self {
1094 Self::real(V::from_signed_integer(v))
1095 }
1096
1097 #[inline(always)]
1098 fn to_unsigned_integer(self) -> Self::Unsigned {
1099 self.re.to_unsigned_integer()
1100 }
1101
1102 #[inline(always)]
1103 fn from_unsigned_integer(v: Self::Unsigned) -> Self {
1104 Self::real(V::from_unsigned_integer(v))
1105 }
1106
1107 const ZERO: Self = Complex::new(V::ZERO, V::ZERO);
1108 const ONE: Self = Complex::new(V::ONE, V::ZERO);
1109 const TWO: Self = Self::real(V::TWO);
1110
1111 const MIN: Self = Complex::new(V::MIN, V::MIN);
1113 const MAX: Self = Complex::new(V::MAX, V::MAX);
1114
1115 #[inline(always)]
1116 fn is_zero(self) -> Self::Mask {
1117 self.re.is_zero() & self.im.is_zero()
1118 }
1119 #[inline(always)]
1120 fn is_all_zero(self) -> bool {
1121 self.re.is_all_zero() && self.im.is_all_zero()
1122 }
1123
1124 #[inline(always)]
1129 fn sort_by<O: thermite::sort::SortOrder>(self) -> Self {
1130 if const { Self::LANES <= 16 && Self::LANES.is_power_of_two() } {
1131 thermite::sort::sort_lanes_by_key::<Self, O, Self>(self)
1132 } else {
1133 sort_lanes_scalar::<Self, O>(self)
1134 }
1135 }
1136
1137 #[inline(always)]
1138 fn bitonic_clean_by<O: thermite::sort::SortOrder>(self) -> Self {
1139 if const { Self::LANES <= 16 && Self::LANES.is_power_of_two() } {
1140 thermite::sort::bitonic_clean_lanes_by_key::<Self, O, Self>(self)
1141 } else {
1142 sort_lanes_scalar::<Self, O>(self)
1144 }
1145 }
1146
1147 #[inline(always)]
1148 fn min(self, other: Self) -> Self {
1149 self.cmp_lt(other).select(self, other)
1150 }
1151 #[inline(always)]
1152 fn max(self, other: Self) -> Self {
1153 self.cmp_gt(other).select(self, other)
1154 }
1155
1156 #[inline(always)]
1158 fn clamp(self, min: Self, max: Self) -> Self {
1159 let is_lt = self.cmp_lt(min);
1160 let is_gt = self.cmp_gt(max);
1161
1162 Complex::new(
1163 is_lt.select(min.re, is_gt.select(max.re, self.re)),
1164 is_lt.select(min.im, is_gt.select(max.im, self.im)),
1165 )
1166 }
1167
1168 #[inline(always)]
1172 fn min_element(self) -> Self::Element {
1173 let mut arr = self.into_array();
1174 reduce_in_place(&mut arr, |a, b| if b < a { b } else { a });
1175 arr[0]
1176 }
1177
1178 #[inline(always)]
1179 fn max_element(self) -> Self::Element {
1180 let mut arr = self.into_array();
1181 reduce_in_place(&mut arr, |a, b| if b > a { b } else { a });
1182 arr[0]
1183 }
1184
1185 #[inline(always)]
1186 fn min_max_element(self) -> (Self::Element, Self::Element) {
1187 (self.min_element(), self.max_element())
1188 }
1189
1190 #[inline(always)]
1191 fn arg_minmax(self) -> (usize, usize) {
1192 let arr = self.into_array();
1193
1194 let (mut lo, mut hi) = (0, 0);
1195
1196 for i in 1..Self::LANES {
1197 if arr[i] < arr[lo] {
1198 lo = i;
1199 }
1200 if arr[i] > arr[hi] {
1201 hi = i;
1202 }
1203 }
1204
1205 (lo, hi)
1206 }
1207
1208 #[inline(always)]
1212 fn sum_elements(self) -> Self::Element {
1213 Complex::new(self.re.sum_elements(), self.im.sum_elements())
1214 }
1215
1216 #[inline(always)]
1219 fn prefix_sum(self) -> Self {
1220 Complex::new(self.re.prefix_sum(), self.im.prefix_sum())
1221 }
1222
1223 #[inline(always)]
1224 fn reverse_prefix_sum(self) -> Self {
1225 Complex::new(self.re.reverse_prefix_sum(), self.im.reverse_prefix_sum())
1226 }
1227
1228 #[inline(always)]
1233 fn prefix_min(self) -> Self {
1234 thermite::scan_ladder!(forward, self, self.broadcast::<0>(), Self::min)
1235 }
1236
1237 #[inline(always)]
1238 fn prefix_max(self) -> Self {
1239 thermite::scan_ladder!(forward, self, self.broadcast::<0>(), Self::max)
1240 }
1241
1242 #[inline(always)]
1243 fn reverse_prefix_min(self) -> Self {
1244 thermite::scan_ladder!(reverse, self, self.reverse().broadcast::<0>(), Self::min)
1245 }
1246
1247 #[inline(always)]
1248 fn reverse_prefix_max(self) -> Self {
1249 thermite::scan_ladder!(reverse, self, self.reverse().broadcast::<0>(), Self::max)
1250 }
1251
1252 #[inline(always)]
1256 fn prod_elements(self) -> Self::Element {
1257 let mut arr = self.into_array();
1258 reduce_in_place(&mut arr, |a, b| a * b);
1259 arr[0]
1260 }
1261
1262 #[inline(always)]
1263 fn offset() -> Self {
1264 Self::real(V::offset())
1265 }
1266 #[inline(always)]
1267 fn indexed() -> Self {
1268 Self::real(V::indexed())
1269 }
1270
1271 #[inline(always)]
1272 fn scale(self, factor: Self::Element) -> Self {
1273 self * Self::splat(factor)
1274 }
1275
1276 #[inline(always)]
1277 fn scale_c(self, mask: Self::Mask, factor: Self::Element) -> Self {
1278 mask.select(<Self as NumericVector>::scale(self, factor), self)
1279 }
1280 #[inline(always)]
1281 fn scale_m(self, src: Self, mask: Self::Mask, factor: Self::Element) -> Self {
1282 mask.select(<Self as NumericVector>::scale(self, factor), src)
1283 }
1284 #[inline(always)]
1285 fn scale_z(self, mask: Self::Mask, factor: Self::Element) -> Self {
1286 mask.select(<Self as NumericVector>::scale(self, factor), Self::ZERO)
1287 }
1288 complex_masked!(binary: min, max);
1289
1290 #[inline(always)]
1293 fn pairwise_sum(lo: Self, hi: Self) -> Self {
1294 Complex::new(V::pairwise_sum(lo.re, hi.re), V::pairwise_sum(lo.im, hi.im))
1295 }
1296
1297 #[inline(always)]
1298 fn relaxed_pairwise_sum(lo: Self, hi: Self) -> Self {
1299 Complex::new(
1300 V::relaxed_pairwise_sum(lo.re, hi.re),
1301 V::relaxed_pairwise_sum(lo.im, hi.im),
1302 )
1303 }
1304}
1305
1306impl<V: RealFloatVector> NegMasked<V::Mask> for Complex<V> {
1309 #[inline(always)]
1310 fn neg_c(self, mask: V::Mask) -> Self {
1311 Complex::new(self.re.neg_c(mask), self.im.neg_c(mask))
1312 }
1313
1314 #[inline(always)]
1315 fn neg_m(self, src: Self, mask: V::Mask) -> Self {
1316 Complex::new(self.re.neg_m(src.re, mask), self.im.neg_m(src.im, mask))
1317 }
1318
1319 #[inline(always)]
1320 fn neg_z(self, mask: V::Mask) -> Self {
1321 Complex::new(self.re.neg_z(mask), self.im.neg_z(mask))
1322 }
1323}
1324
1325impl<V: RealFloatVector> Complex<V> {
1326 #[inline(always)]
1330 pub(crate) fn modulus(self) -> V {
1331 self.re.hypot_p::<DefaultPolicy>(self.im)
1332 }
1333}
1334
1335#[rustfmt::skip]
1336impl<V: RealFloatVector> SignedVector for Complex<V> {
1337 const NEG_ONE: Self = Self::real(V::NEG_ONE);
1338 const MIN_POSITIVE: Self = Self::real(V::MIN_POSITIVE);
1339
1340 #[inline(always)]
1342 fn abs(self) -> Self {
1343 Self::real(self.modulus())
1344 }
1345
1346 #[inline(always)]
1350 fn signum(self) -> Self {
1351 let m = self.modulus();
1352 let is_zero = m.is_zero();
1353 let inv = m.reciprocal_p::<DefaultPolicy>();
1354
1355 Complex::new((self.re * inv).nz(is_zero), (self.im * inv).nz(is_zero))
1358 }
1359
1360 #[inline(always)] fn is_positive(self) -> Self::Mask { self.re.is_positive() }
1363 #[inline(always)] fn is_negative(self) -> Self::Mask { self.re.is_negative() }
1364 #[inline(always)] fn select_negative(self, if_neg: Self, if_pos: Self) -> Self { self.is_negative().select(if_neg, if_pos) }
1365
1366 #[inline(always)]
1367 fn copysign(self, sign: Self) -> Self {
1368 Complex::new(self.re.copysign(sign.re), self.im.copysign(sign.im))
1369 }
1370
1371 complex_masked!(unary: abs);
1372 complex_masked!(binary: copysign);
1373}
1374
1375#[inline(always)]
1383fn sqrt_kahan<V: RealFloatVector>(z: Complex<V>) -> (Complex<V>, V::Mask) {
1384 let half = <V as FloatVector>::HALF;
1385
1386 let m = z.modulus();
1387
1388 let t = z.re.abs().mul_adde(half, m * half).sqrt(); let half_im = z.im * half;
1395
1396 let q = half_im / t;
1398
1399 let re_pos = z.re.is_positive();
1401
1402 let degenerate = if const { features::PRESERVE_DENORMALS || features::IGNORE_DENORMALS } {
1415 t.is_zero()
1416 } else {
1417 m.is_zero()
1418 };
1419
1420 (
1421 Complex::new(re_pos.select(t, q.abs()), re_pos.select(q, t.mul_sign(z.im))),
1422 degenerate,
1423 )
1424}
1425
1426#[inline(always)]
1440fn sqrt_rescaled<V: RealFloatVector>(z: Complex<V>) -> Complex<V> {
1441 let up = V::ONE / <V as SignedVector>::MIN_POSITIVE;
1442 let down = <V as SignedVector>::MIN_POSITIVE.sqrt();
1443
1444 let (r, _) = sqrt_kahan(Complex::new(z.re * up, z.im * up));
1445
1446 let is_zero = z.is_zero();
1447
1448 Complex::new((r.re * down).nz(is_zero), (r.im * down).nz(is_zero))
1449}
1450
1451#[rustfmt::skip]
1452impl<V: RealFloatVector> FloatVector for Complex<V> {
1453 const HALF: Self = Self::real(<V as FloatVector>::HALF);
1454 const NEG_ZERO: Self = Self::real(<V as FloatVector>::NEG_ZERO);
1455 const EPSILON: Self = Self::real(<V as FloatVector>::EPSILON);
1456
1457 const INFINITY: Self = Self::real(<V as FloatVector>::INFINITY);
1460 const NEG_INFINITY: Self = Self::real(<V as FloatVector>::NEG_INFINITY);
1461 const NAN: Self = Complex::new(<V as FloatVector>::NAN, <V as FloatVector>::NAN);
1462
1463 type ExtendedPrecision = Self;
1464
1465 const HAS_APPROX_RCP: bool = V::HAS_APPROX_RCP;
1468 const HAS_APPROX_RSQRT: bool = V::HAS_APPROX_RCP;
1469
1470 #[inline(always)] fn is_nan(self) -> Self::Mask { self.re.is_nan() | self.im.is_nan() }
1471 #[inline(always)] fn is_infinite(self) -> Self::Mask { self.re.is_infinite() | self.im.is_infinite() }
1472 #[inline(always)] fn is_finite(self) -> Self::Mask { self.re.is_finite() & self.im.is_finite() }
1473
1474 #[inline(always)] fn is_zero_or_subnormal(self) -> Self::Mask { self.re.is_zero_or_subnormal() & self.im.is_zero_or_subnormal() }
1477 #[inline(always)] fn is_normal(self) -> Self::Mask { (self.re.is_normal() | self.im.is_normal()) & self.is_finite() }
1478 #[inline(always)] fn is_subnormal(self) -> Self::Mask { (self.re.is_subnormal() | self.im.is_subnormal()) & self.is_zero_or_subnormal() }
1479
1480 #[inline(always)]
1482 fn sqrt(self) -> Self {
1483 let (res, degenerate) = sqrt_kahan(self);
1494
1495 if thermite::unlikely(degenerate.any()) {
1499 return degenerate.select(sqrt_rescaled(self), res);
1500 }
1501
1502 res
1503 }
1504
1505 #[inline(always)]
1507 fn rcp(self) -> Self {
1508 let inv = self.norm_sqr().rcp();
1509
1510 Complex::new(self.re * inv, -(self.im * inv))
1511 }
1512
1513 #[inline(always)]
1515 fn rsqrt(self) -> Self {
1516 let s = self.sqrt();
1517 let inv = self.modulus().rcp();
1518
1519 Complex::new(s.re * inv, -(s.im * inv))
1520 }
1521
1522 #[inline(always)] fn floor(self) -> Self { Complex::new(self.re.floor(), self.im.floor()) }
1524 #[inline(always)] fn ceil(self) -> Self { Complex::new(self.re.ceil(), self.im.ceil()) }
1525 #[inline(always)] fn round(self) -> Self { Complex::new(self.re.round(), self.im.round()) }
1526 #[inline(always)] fn trunc(self) -> Self { Complex::new(self.re.trunc(), self.im.trunc()) }
1527 #[inline(always)] fn fract(self) -> Self { Complex::new(self.re.fract(), self.im.fract()) }
1528
1529 #[inline(always)] fn mul_sign(self, sign: Self) -> Self { Complex::new(self.re.mul_sign(sign.re), self.im.mul_sign(sign.im)) }
1530 #[inline(always)] fn signed_zero(self) -> Self { Complex::new(self.re.signed_zero(), self.im.signed_zero()) }
1531
1532 #[inline(always)] fn next_up(self) -> Self { Complex::new(self.re.next_up(), self.im.next_up()) }
1533 #[inline(always)] fn next_down(self) -> Self { Complex::new(self.re.next_down(), self.im.next_down()) }
1534
1535 #[inline(always)]
1536 unsafe fn block_autovectorization(&mut self) {
1537 unsafe {
1538 self.re.block_autovectorization();
1539 self.im.block_autovectorization();
1540 }
1541 }
1542
1543 #[inline(always)] fn mix(self, a: Self, b: Self) -> Self { (b - a).mul_adde(self, a) }
1546
1547 complex_masked!(unary: sqrt, rsqrt, rcp, floor, ceil, round, trunc, fract, signed_zero, next_up, next_down);
1548 complex_masked!(binary: mul_sign);
1549}