1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(non_camel_case_types)]
3use bytemuck::Pod;
4use core::fmt::Debug;
5use num_complex::Complex;
6use pulp::Simd;
7use qd::Quad;
8pub mod imply {
10 pub trait Imply<T: ?Sized>: sealed::ImplyInner<T, Is = T> {}
11 impl<T: ?Sized, U: ?Sized> Imply<T> for U {}
12 mod sealed {
13 pub trait ImplyInner<T: ?Sized> {
14 type Is: ?Sized;
15 }
16 impl<T: ?Sized, U: ?Sized> ImplyInner<T> for U {
17 type Is = T;
18 }
19 }
20}
21use core::ops::*;
22use imply::Imply;
23use math_utils::*;
24pub mod math_utils {
25 use crate::{ByRef, ComplexField, RealField, abs_impl};
26 #[inline(always)]
27 #[must_use]
28 pub fn eps<T: RealField>() -> T {
29 T::Real::epsilon_impl()
30 }
31 #[inline(always)]
32 #[must_use]
33 pub fn nbits<T: ComplexField>() -> usize {
34 T::Real::nbits_impl()
35 }
36 #[inline(always)]
37 #[must_use]
38 pub fn min_positive<T: RealField>() -> T {
39 T::min_positive_impl()
40 }
41 #[inline(always)]
42 #[must_use]
43 pub fn max_positive<T: RealField>() -> T {
44 T::max_positive_impl()
45 }
46 #[inline(always)]
47 #[must_use]
48 pub fn sqrt_min_positive<T: RealField>() -> T {
49 T::sqrt_min_positive_impl()
50 }
51 #[inline(always)]
52 #[must_use]
53 pub fn sqrt_max_positive<T: RealField>() -> T {
54 T::sqrt_max_positive_impl()
55 }
56 #[inline(always)]
57 #[must_use]
58 pub fn zero<T: ComplexField>() -> T {
59 T::zero_impl()
60 }
61 #[inline(always)]
62 #[must_use]
63 pub fn one<T: ComplexField>() -> T {
64 T::one_impl()
65 }
66 #[inline(always)]
67 #[must_use]
68 pub fn nan<T: ComplexField>() -> T {
69 T::nan_impl()
70 }
71 #[inline(always)]
72 #[must_use]
73 pub fn infinity<T: ComplexField>() -> T {
74 T::infinity_impl()
75 }
76 #[inline(always)]
77 #[must_use]
78 pub fn as_real<T: ComplexField>(value: &T) -> T {
79 T::from_real_impl(&T::real_part_impl((value).by_ref()))
80 }
81 #[inline(always)]
82 #[must_use]
83 pub fn real<T: ComplexField>(value: &T) -> T::Real {
84 T::real_part_impl((value).by_ref())
85 }
86 #[inline(always)]
87 #[must_use]
88 pub fn imag<T: ComplexField>(value: &T) -> T::Real {
89 T::imag_part_impl((value).by_ref())
90 }
91 #[inline(always)]
92 #[track_caller]
93 #[must_use]
94 pub fn neg<T: NegByRef>(value: &T) -> T::Output {
95 value.neg_by_ref()
96 }
97 #[inline(always)]
98 #[must_use]
99 pub fn copy<T: ComplexField>(value: &T) -> T {
100 T::copy_impl((value).by_ref())
101 }
102 #[inline(always)]
103 #[must_use]
104 pub fn conj<T: ComplexField>(value: &T) -> T {
105 T::conj_impl((value).by_ref())
106 }
107 #[inline(always)]
108 #[track_caller]
109 #[must_use]
110 pub fn add<T: AddByRef<U>, U>(lhs: &T, rhs: &U) -> T::Output {
111 lhs.add_by_ref(rhs)
112 }
113 #[inline(always)]
114 #[track_caller]
115 #[must_use]
116 pub fn sub<T: SubByRef<U>, U>(lhs: &T, rhs: &U) -> T::Output {
117 lhs.sub_by_ref(rhs)
118 }
119 #[inline(always)]
120 #[track_caller]
121 #[must_use]
122 pub fn mul<T: MulByRef<U>, U>(lhs: &T, rhs: &U) -> T::Output {
123 lhs.mul_by_ref(rhs)
124 }
125 #[inline(always)]
126 #[track_caller]
127 #[must_use]
128 pub fn div<T: DivByRef<U>, U>(lhs: &T, rhs: &U) -> T::Output {
129 lhs.div_by_ref(rhs)
130 }
131 #[inline(always)]
132 #[must_use]
133 pub fn mul_real<T: ComplexField>(lhs: &T, rhs: &T::Real) -> T {
134 T::mul_real_impl((lhs).by_ref(), (rhs).by_ref())
135 }
136 #[inline(always)]
137 #[must_use]
138 pub fn mul_pow2<T: ComplexField>(lhs: &T, rhs: &T::Real) -> T {
139 T::mul_real_impl((lhs).by_ref(), (rhs).by_ref())
140 }
141 #[inline(always)]
142 #[must_use]
143 pub fn abs1<T: ComplexField>(value: &T) -> T::Real {
144 T::abs1_impl((value).by_ref())
145 }
146 #[inline(always)]
147 #[must_use]
148 pub fn absmax<T: ComplexField>(value: &T) -> T::Real {
149 if const { T::IS_REAL } {
150 T::abs1_impl(value)
151 } else {
152 &T::Real::abs1_impl(&real(value))
153 + &T::Real::abs1_impl(&imag(value))
154 }
155 }
156 #[inline(always)]
157 #[must_use]
158 pub fn abs<T: ComplexField>(value: &T) -> T::Real {
159 T::abs_impl((value).by_ref())
160 }
161 #[inline(always)]
162 #[must_use]
163 pub fn hypot<T: RealField>(lhs: &T, rhs: &T) -> T {
164 abs_impl::<T::Real>(lhs.clone(), rhs.clone())
165 }
166 #[inline(always)]
167 #[must_use]
168 pub fn abs2<T: ComplexField>(value: &T) -> T::Real {
169 T::abs2_impl((value).by_ref())
170 }
171 #[inline(always)]
172 #[must_use]
173 pub fn max<T: RealField>(lhs: &T, rhs: &T) -> T {
174 if lhs > rhs { copy(lhs) } else { copy(rhs) }
175 }
176 #[inline(always)]
177 #[must_use]
178 pub fn min<T: RealField>(lhs: &T, rhs: &T) -> T {
179 if lhs < rhs { copy(lhs) } else { copy(rhs) }
180 }
181 #[inline(always)]
182 #[must_use]
183 pub fn is_nan<T: ComplexField>(value: &T) -> bool {
184 T::is_nan_impl((value).by_ref())
185 }
186 #[inline(always)]
187 #[must_use]
188 pub fn is_finite<T: ComplexField>(value: &T) -> bool {
189 T::is_finite_impl((value).by_ref())
190 }
191 #[inline(always)]
192 #[must_use]
193 pub fn sqrt<T: ComplexField>(value: &T) -> T {
194 T::sqrt_impl((value).by_ref())
195 }
196 #[inline(always)]
197 #[must_use]
198 pub fn recip<T: ComplexField>(value: &T) -> T {
199 T::recip_impl((value).by_ref())
200 }
201 #[inline(always)]
202 #[must_use]
203 pub fn from_real<T: ComplexField>(value: &T::Real) -> T {
204 T::from_real_impl((value).by_ref())
205 }
206 #[inline(always)]
207 #[must_use]
208 pub fn from_f64<T: ComplexField>(value: f64) -> T {
209 T::from_f64_impl(value)
210 }
211 pub use crate::{AddByRef, DivByRef, MulByRef, NegByRef, SubByRef};
212}
213macro_rules! impl_op {
214 ({$(
215 impl$(<$T:ident: $bound:ident>)? $op:ident for $ty:ty {
216 fn $op_fn:ident($self:ident, $rhs:ident: Self) -> Self::Output $body:block
217 }
218 )*}) => {$(
219 impl$(<$T: $bound>)? $op for $ty {
220 type Output = $ty;
221 #[inline(always)]
222 fn $op_fn($self, $rhs: $ty) -> Self::Output $body
223 }
224 impl$(<$T: $bound>)? $op<&$ty> for $ty {
225 type Output = $ty;
226 #[inline(always)]
227 fn $op_fn($self, $rhs: &$ty) -> Self::Output $body
228 }
229 impl$(<$T: $bound>)? $op<$ty> for &$ty {
230 type Output = $ty;
231 #[inline(always)]
232 fn $op_fn($self, $rhs: $ty) -> Self::Output $body
233 }
234 impl$(<$T: $bound>)? $op<&$ty> for &$ty {
235 type Output = $ty;
236 #[inline(always)]
237 fn $op_fn($self, $rhs: &$ty) -> Self::Output $body
238 }
239 )*};
240}
241macro_rules! impl_assign_op {
242 ({$(
243 impl$(<$T:ident: $bound:ident>)? $op:ident for $ty:ty {
244 fn $op_fn:ident(&mut $self:ident, $rhs:ident: Self) $body:block
245 }
246 )*}) => {$(
247 impl$(<$T: $bound>)? $op for $ty {
248 #[inline(always)]
249 fn $op_fn(&mut $self, $rhs: Self) $body
250 }
251 impl$(<$T: $bound>)? $op<&$ty> for $ty {
252 #[inline(always)]
253 fn $op_fn(&mut $self, $rhs: &$ty) $body
254 }
255 )*};
256}
257pub trait AddByRef<Rhs = Self> {
258 type Output;
259 fn add_by_ref(&self, rhs: &Rhs) -> Self::Output;
260}
261pub trait SubByRef<Rhs = Self> {
262 type Output;
263 fn sub_by_ref(&self, rhs: &Rhs) -> Self::Output;
264}
265pub trait NegByRef {
266 type Output;
267 fn neg_by_ref(&self) -> Self::Output;
268}
269pub trait MulByRef<Rhs = Self> {
270 type Output;
271 fn mul_by_ref(&self, rhs: &Rhs) -> Self::Output;
272}
273pub trait DivByRef<Rhs = Self> {
274 type Output;
275 fn div_by_ref(&self, rhs: &Rhs) -> Self::Output;
276}
277impl<Rhs, Lhs, Output> AddByRef<Rhs> for Lhs
278where
279 for<'a> &'a Lhs: core::ops::Add<&'a Rhs, Output = Output>,
280{
281 type Output = Output;
282
283 #[inline]
284 #[track_caller]
285 fn add_by_ref(&self, rhs: &Rhs) -> Self::Output {
286 self + rhs
287 }
288}
289impl<Rhs, Lhs, Output> SubByRef<Rhs> for Lhs
290where
291 for<'a> &'a Lhs: core::ops::Sub<&'a Rhs, Output = Output>,
292{
293 type Output = Output;
294
295 #[inline]
296 #[track_caller]
297 fn sub_by_ref(&self, rhs: &Rhs) -> Self::Output {
298 self - rhs
299 }
300}
301impl<Rhs, Lhs, Output> MulByRef<Rhs> for Lhs
302where
303 for<'a> &'a Lhs: core::ops::Mul<&'a Rhs, Output = Output>,
304{
305 type Output = Output;
306
307 #[inline]
308 #[track_caller]
309 fn mul_by_ref(&self, rhs: &Rhs) -> Self::Output {
310 self * rhs
311 }
312}
313impl<Rhs, Lhs, Output> DivByRef<Rhs> for Lhs
314where
315 for<'a> &'a Lhs: core::ops::Div<&'a Rhs, Output = Output>,
316{
317 type Output = Output;
318
319 #[inline]
320 #[track_caller]
321 fn div_by_ref(&self, rhs: &Rhs) -> Self::Output {
322 self / rhs
323 }
324}
325impl<T, Output> NegByRef for T
326where
327 for<'a> &'a T: core::ops::Neg<Output = Output>,
328{
329 type Output = Output;
330
331 #[inline]
332 #[track_caller]
333 fn neg_by_ref(&self) -> Self::Output {
334 -self
335 }
336}
337fn abs_impl<T: RealField>(re: T, im: T) -> T {
338 use ext::*;
339 let (re, im) = &(re, im);
340 let small = &sqrt_min_positive();
341 let big = &sqrt_max_positive();
342 let one = &one();
343 let re_abs = &re.abs();
344 let im_abs = &im.abs();
345 if re_abs > big || im_abs > big {
346 ((re * small).abs2() + (im * small).abs2()).sqrt() * big
347 } else if re_abs > one || im_abs > one {
348 (re.abs2() + im.abs2()).sqrt()
349 } else {
350 ((re * big).abs2() + (im * big).abs2()).sqrt() * small
351 }
352}
353fn recip_impl<T: RealField>(re: T, im: T) -> (T, T) {
354 use ext::*;
355 let (re, im) = &(re, im);
356 if is_nan(re) || is_nan(im) {
357 return (nan(), nan());
358 }
359 if *re == zero() && *im == zero() {
360 return (infinity(), infinity());
361 }
362 if !is_finite(re) || !is_finite(im) {
363 return (zero(), zero());
364 }
365 let small = &sqrt_min_positive();
366 let big = &sqrt_max_positive();
367 let one = &one();
368 let re_abs = &abs(re);
369 let im_abs = &abs(im);
370 if re_abs > big || im_abs > big {
371 let re = re * small;
372 let im = im * small;
373 let inv = &(re.abs2() + im.abs2()).recip();
374 (((re * inv) * small), ((-im * inv) * small))
375 } else if re_abs > one || im_abs > one {
376 let inv = &(re.abs2() + im.abs2()).recip();
377 ((re * inv), (-im * inv))
378 } else {
379 let re = re * big;
380 let im = im * big;
381 if &abs(&re) < small && &abs(&im) < small {
382 let re = re * big;
385 let im = im * big;
386 let inv = &(re.abs2() + im.abs2()).recip();
387 (((re * inv) * big) * big, ((-im * inv) * big) * big)
388 } else {
389 let inv = &(re.abs2() + im.abs2()).recip();
390 (((re * inv) * big), ((-im * inv) * big))
391 }
392 }
393}
394fn sqrt_impl<T: RealField>(re: T, im: T) -> (T, T) {
395 use ext::*;
396 let im_negative = im < zero();
397 let half = &from_f64(0.5);
398 let abs = &abs_impl(re.clone(), im);
399 let zero = &zero::<T>();
400 let re = &re;
401 let mut sum = re + abs;
402 if &sum < zero {
403 sum = zero.copy();
404 }
405 let out_re = sum.mul_pow2(half).sqrt();
406 let mut out_im = (abs - re).mul_pow2(half).fmax(zero).sqrt();
407 if im_negative {
408 out_im = -out_im;
409 }
410 (out_re, out_im)
411}
412pub trait ByRef<T> {
413 fn by_ref(&self) -> &T;
414}
415impl<T> ByRef<T> for T {
416 #[inline]
417 fn by_ref(&self) -> &T {
418 self
419 }
420}
421impl<T> ByRef<T> for &T {
422 #[inline]
423 fn by_ref(&self) -> &T {
424 *self
425 }
426}
427#[repr(transparent)]
428pub struct SimdCtx<T: ComplexField, S: Simd>(pub T::SimdCtx<S>);
429impl<T: ComplexField, S: Simd> Copy for SimdCtx<T, S> {}
430impl<T: ComplexField, S: Simd> Clone for SimdCtx<T, S> {
431 #[inline]
432 fn clone(&self) -> Self {
433 *self
434 }
435}
436#[derive(Copy, Clone, Debug)]
437#[repr(transparent)]
438pub struct RealReg<T>(pub T);
439impl<T: ComplexField, S: Simd> SimdCtx<T, S> {
440 #[inline(always)]
441 pub fn new(ctx: &T::SimdCtx<S>) -> &Self {
442 unsafe { &*(ctx as *const T::SimdCtx<S> as *const Self) }
443 }
444
445 #[inline(always)]
446 pub fn zero(&self) -> T::SimdVec<S> {
447 unsafe { core::mem::zeroed() }
448 }
449
450 #[inline(always)]
451 pub fn splat(&self, value: impl ByRef<T>) -> T::SimdVec<S> {
452 unsafe {
453 core::mem::transmute_copy(&T::simd_splat(&self.0, value.by_ref()))
454 }
455 }
456
457 #[inline(always)]
458 pub fn splat_real(
459 &self,
460 value: impl ByRef<T::Real>,
461 ) -> RealReg<T::SimdVec<S>> {
462 RealReg(unsafe {
463 core::mem::transmute_copy(&T::simd_splat_real(
464 &self.0,
465 value.by_ref(),
466 ))
467 })
468 }
469
470 #[inline(always)]
471 pub fn add(&self, lhs: T::SimdVec<S>, rhs: T::SimdVec<S>) -> T::SimdVec<S> {
472 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
473 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
474 unsafe { core::mem::transmute_copy(&T::simd_add(&self.0, lhs, rhs)) }
475 }
476
477 #[inline(always)]
478 pub fn sub(&self, lhs: T::SimdVec<S>, rhs: T::SimdVec<S>) -> T::SimdVec<S> {
479 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
480 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
481 unsafe { core::mem::transmute_copy(&T::simd_sub(&self.0, lhs, rhs)) }
482 }
483
484 #[inline(always)]
485 pub fn neg(&self, value: T::SimdVec<S>) -> T::SimdVec<S> {
486 let value = unsafe { core::mem::transmute_copy(&value) };
487 unsafe { core::mem::transmute_copy(&T::simd_neg(&self.0, value)) }
488 }
489
490 #[inline(always)]
491 pub fn conj(&self, value: T::SimdVec<S>) -> T::SimdVec<S> {
492 let value = unsafe { core::mem::transmute_copy(&value) };
493 unsafe { core::mem::transmute_copy(&T::simd_conj(&self.0, value)) }
494 }
495
496 #[inline(always)]
497 pub fn abs1(&self, value: T::SimdVec<S>) -> RealReg<T::SimdVec<S>> {
498 let value = unsafe { core::mem::transmute_copy(&value) };
499 RealReg(unsafe {
500 core::mem::transmute_copy(&T::simd_abs1(&self.0, value))
501 })
502 }
503
504 #[inline(always)]
505 pub fn abs_max(&self, value: T::SimdVec<S>) -> RealReg<T::SimdVec<S>> {
506 let value = unsafe { core::mem::transmute_copy(&value) };
507 RealReg(unsafe {
508 core::mem::transmute_copy(&T::simd_abs_max(&self.0, value))
509 })
510 }
511
512 #[inline(always)]
513 pub fn mul_real(
514 &self,
515 lhs: T::SimdVec<S>,
516 rhs: RealReg<T::SimdVec<S>>,
517 ) -> T::SimdVec<S> {
518 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
519 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
520 unsafe {
521 core::mem::transmute_copy(&T::simd_mul_real(&self.0, lhs, rhs))
522 }
523 }
524
525 #[inline(always)]
526 pub fn mul_pow2(
527 &self,
528 lhs: T::SimdVec<S>,
529 rhs: RealReg<T::SimdVec<S>>,
530 ) -> T::SimdVec<S> {
531 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
532 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
533 unsafe {
534 core::mem::transmute_copy(&T::simd_mul_pow2(&self.0, lhs, rhs))
535 }
536 }
537
538 #[inline(always)]
539 pub fn mul(&self, lhs: T::SimdVec<S>, rhs: T::SimdVec<S>) -> T::SimdVec<S> {
540 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
541 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
542 unsafe { core::mem::transmute_copy(&T::simd_mul(&self.0, lhs, rhs)) }
543 }
544
545 #[inline(always)]
546 pub fn conj_mul(
547 &self,
548 lhs: T::SimdVec<S>,
549 rhs: T::SimdVec<S>,
550 ) -> T::SimdVec<S> {
551 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
552 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
553 unsafe {
554 core::mem::transmute_copy(&T::simd_conj_mul(&self.0, lhs, rhs))
555 }
556 }
557
558 #[inline(always)]
559 pub fn mul_add(
560 &self,
561 lhs: T::SimdVec<S>,
562 rhs: T::SimdVec<S>,
563 acc: T::SimdVec<S>,
564 ) -> T::SimdVec<S> {
565 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
566 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
567 let acc = unsafe { core::mem::transmute_copy(&acc) };
568 unsafe {
569 core::mem::transmute_copy(&T::simd_mul_add(&self.0, lhs, rhs, acc))
570 }
571 }
572
573 #[inline(always)]
574 pub fn conj_mul_add(
575 &self,
576 lhs: T::SimdVec<S>,
577 rhs: T::SimdVec<S>,
578 acc: T::SimdVec<S>,
579 ) -> T::SimdVec<S> {
580 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
581 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
582 let acc = unsafe { core::mem::transmute_copy(&acc) };
583 unsafe {
584 core::mem::transmute_copy(&T::simd_conj_mul_add(
585 &self.0, lhs, rhs, acc,
586 ))
587 }
588 }
589
590 #[inline(always)]
591 pub fn maybe_conj_mul_add<const CONJ: bool>(
592 &self,
593 lhs: T::SimdVec<S>,
594 rhs: T::SimdVec<S>,
595 acc: T::SimdVec<S>,
596 ) -> T::SimdVec<S> {
597 if const { CONJ } {
598 self.conj_mul_add(lhs, rhs, acc)
599 } else {
600 self.mul_add(lhs, rhs, acc)
601 }
602 }
603
604 #[inline(always)]
605 pub fn abs2(&self, value: T::SimdVec<S>) -> RealReg<T::SimdVec<S>> {
606 let value = unsafe { core::mem::transmute_copy(&value) };
607 RealReg(unsafe {
608 core::mem::transmute_copy(&T::simd_abs2(&self.0, value))
609 })
610 }
611
612 #[inline(always)]
613 pub fn abs2_add(
614 &self,
615 value: T::SimdVec<S>,
616 acc: RealReg<T::SimdVec<S>>,
617 ) -> RealReg<T::SimdVec<S>> {
618 let value = unsafe { core::mem::transmute_copy(&value) };
619 let acc = unsafe { core::mem::transmute_copy(&acc) };
620 RealReg(unsafe {
621 core::mem::transmute_copy(&T::simd_abs2_add(&self.0, value, acc))
622 })
623 }
624
625 #[inline(always)]
626 pub fn reduce_sum(&self, value: T::SimdVec<S>) -> T {
627 let value = unsafe { core::mem::transmute_copy(&value) };
628 unsafe {
629 core::mem::transmute_copy(&T::simd_reduce_sum(&self.0, value))
630 }
631 }
632
633 #[inline(always)]
634 pub fn reduce_max(&self, value: RealReg<T::SimdVec<S>>) -> T {
635 let value = unsafe { core::mem::transmute_copy(&value) };
636 unsafe {
637 core::mem::transmute_copy(&T::simd_reduce_max(&self.0, value))
638 }
639 }
640
641 #[inline(always)]
642 pub fn reduce_sum_real(&self, value: RealReg<T::SimdVec<S>>) -> Real<T> {
643 let value = T::simd_reduce_sum(&self.0, value.0);
644 if const { T::SIMD_ABS_SPLIT_REAL_IMAG && !S::IS_SCALAR } {
645 let r = real(&value);
646 let i = imag(&value);
647 &r + &i
648 } else {
649 real(&value)
650 }
651 }
652
653 #[inline(always)]
654 pub fn reduce_max_real(&self, value: RealReg<T::SimdVec<S>>) -> Real<T> {
655 use crate::ext::*;
656 let value = T::simd_reduce_max(&self.0, value.0);
657 if const { T::SIMD_ABS_SPLIT_REAL_IMAG && !S::IS_SCALAR } {
658 value.real().fmax(value.imag())
659 } else {
660 value.real()
661 }
662 }
663
664 #[inline(always)]
665 pub fn max(
666 &self,
667 lhs: RealReg<T::SimdVec<S>>,
668 rhs: RealReg<T::SimdVec<S>>,
669 ) -> RealReg<T::SimdVec<S>> {
670 let cmp = self.gt(lhs, rhs);
671 RealReg(self.select(cmp, lhs.0, rhs.0))
672 }
673
674 #[inline(always)]
675 pub fn eq(&self, lhs: T::SimdVec<S>, rhs: T::SimdVec<S>) -> T::SimdMask<S> {
676 T::simd_equal(&self.0, lhs, rhs)
677 }
678
679 #[inline(always)]
680 pub fn lt(
681 &self,
682 lhs: RealReg<T::SimdVec<S>>,
683 rhs: RealReg<T::SimdVec<S>>,
684 ) -> T::SimdMask<S> {
685 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
686 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
687 unsafe {
688 core::mem::transmute_copy(&T::simd_less_than(&self.0, lhs, rhs))
689 }
690 }
691
692 #[inline(always)]
693 pub fn gt(
694 &self,
695 lhs: RealReg<T::SimdVec<S>>,
696 rhs: RealReg<T::SimdVec<S>>,
697 ) -> T::SimdMask<S> {
698 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
699 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
700 unsafe {
701 core::mem::transmute_copy(&T::simd_greater_than(&self.0, lhs, rhs))
702 }
703 }
704
705 #[inline(always)]
706 pub fn le(
707 &self,
708 lhs: RealReg<T::SimdVec<S>>,
709 rhs: RealReg<T::SimdVec<S>>,
710 ) -> T::SimdMask<S> {
711 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
712 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
713 unsafe {
714 core::mem::transmute_copy(&T::simd_less_than_or_equal(
715 &self.0, lhs, rhs,
716 ))
717 }
718 }
719
720 #[inline(always)]
721 pub fn ge(
722 &self,
723 lhs: RealReg<T::SimdVec<S>>,
724 rhs: RealReg<T::SimdVec<S>>,
725 ) -> T::SimdMask<S> {
726 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
727 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
728 unsafe {
729 core::mem::transmute_copy(&T::simd_greater_than_or_equal(
730 &self.0, lhs, rhs,
731 ))
732 }
733 }
734
735 #[inline(always)]
736 pub fn select(
737 &self,
738 mask: T::SimdMask<S>,
739 lhs: T::SimdVec<S>,
740 rhs: T::SimdVec<S>,
741 ) -> T::SimdVec<S> {
742 let lhs = unsafe { core::mem::transmute_copy(&lhs) };
743 let rhs = unsafe { core::mem::transmute_copy(&rhs) };
744 unsafe {
745 core::mem::transmute_copy(&T::simd_select(&self.0, mask, lhs, rhs))
746 }
747 }
748
749 #[inline(always)]
750 pub fn iselect(
751 &self,
752 mask: T::SimdMask<S>,
753 lhs: T::SimdIndex<S>,
754 rhs: T::SimdIndex<S>,
755 ) -> T::SimdIndex<S> {
756 unsafe {
757 core::mem::transmute_copy(&T::simd_index_select(
758 &self.0, mask, lhs, rhs,
759 ))
760 }
761 }
762
763 #[inline(always)]
764 pub fn isplat(&self, value: T::Index) -> T::SimdIndex<S> {
765 unsafe {
766 core::mem::transmute_copy(&T::simd_index_splat(&self.0, value))
767 }
768 }
769
770 #[inline(always)]
771 pub fn izero(&self) -> T::SimdIndex<S> {
772 unsafe { core::mem::zeroed() }
773 }
774
775 #[inline(always)]
776 pub fn iadd(
777 &self,
778 lhs: T::SimdIndex<S>,
779 rhs: T::SimdIndex<S>,
780 ) -> T::SimdIndex<S> {
781 unsafe {
782 core::mem::transmute_copy(&T::simd_index_add(&self.0, lhs, rhs))
783 }
784 }
785
786 #[inline(always)]
787 pub fn or_mask(
788 &self,
789 lhs: T::SimdMask<S>,
790 rhs: T::SimdMask<S>,
791 ) -> T::SimdMask<S> {
792 T::simd_or_mask(&self.0, lhs, rhs)
793 }
794
795 #[inline(always)]
796 pub fn and_mask(
797 &self,
798 lhs: T::SimdMask<S>,
799 rhs: T::SimdMask<S>,
800 ) -> T::SimdMask<S> {
801 T::simd_and_mask(&self.0, lhs, rhs)
802 }
803
804 #[inline(always)]
805 pub fn not_mask(&self, mask: T::SimdMask<S>) -> T::SimdMask<S> {
806 T::simd_not_mask(&self.0, mask)
807 }
808
809 #[inline(always)]
810 pub fn first_true_mask(&self, value: T::SimdMask<S>) -> usize {
811 T::simd_first_true_mask(&self.0, value)
812 }
813
814 #[inline(always)]
815 pub unsafe fn mask_load(
816 &self,
817 mask: T::SimdMemMask<S>,
818 ptr: *const T::SimdVec<S>,
819 ) -> T::SimdVec<S> {
820 unsafe { T::simd_mask_load(&self.0, mask, ptr) }
821 }
822
823 #[inline(always)]
824 pub unsafe fn mask_store(
825 &self,
826 mask: T::SimdMemMask<S>,
827 ptr: *mut T::SimdVec<S>,
828 value: T::SimdVec<S>,
829 ) {
830 let value = unsafe { core::mem::transmute_copy(&value) };
831 unsafe { T::simd_mask_store(&self.0, mask, ptr, value) }
832 }
833
834 #[inline(always)]
835 pub fn load(&self, ptr: &T::SimdVec<S>) -> T::SimdVec<S> {
836 unsafe { core::mem::transmute_copy(&T::simd_load(&self.0, ptr)) }
837 }
838
839 #[inline(always)]
840 pub fn store(&self, ptr: &mut T::SimdVec<S>, value: T::SimdVec<S>) {
841 let value = unsafe { core::mem::transmute_copy(&value) };
842 unsafe {
843 core::mem::transmute_copy(&T::simd_store(&self.0, ptr, value))
844 }
845 }
846}
847pub unsafe trait Conjugate:
848 Send + Sync + core::fmt::Debug + Imply<Self::Canonical, Is: RefOps>
849{
850 const IS_CANONICAL: bool;
851 type Conj: Conjugate<Conj = Self, Canonical = Self::Canonical>;
852 type Canonical: Conjugate<Canonical = Self::Canonical> + ComplexField;
853}
854pub type Real<T> = <<T as Conjugate>::Canonical as ComplexField>::Real;
855#[derive(Copy, Clone, Debug, PartialEq, Eq)]
856pub struct ComplexConj<T> {
857 pub re: T,
858 pub im_neg: T,
859}
860#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
861pub enum SimdCapabilities {
862 None,
863 Copy,
864 Simd,
865}
866impl SimdCapabilities {
867 #[inline]
868 pub const fn is_copy(self) -> bool {
869 matches!(self, Self::Copy | Self::Simd)
870 }
871
872 #[inline]
873 pub const fn is_simd(self) -> bool {
874 matches!(self, Self::Simd)
875 }
876}
877mod seal {
878 pub trait Seal {}
879 impl Seal for u8 {}
880 impl Seal for u16 {}
881 impl Seal for u32 {}
882 impl Seal for u64 {}
883 impl Seal for u128 {}
884 impl Seal for usize {}
885 impl Seal for i32 {}
886 impl Seal for i64 {}
887 impl Seal for isize {}
888}
889pub trait Seal: seal::Seal {}
890impl<T: seal::Seal> Seal for T {}
891pub trait SignedIndex:
895 Seal
896 + core::fmt::Debug
897 + core::ops::Neg<Output = Self>
898 + core::ops::Add<Output = Self>
899 + core::ops::Sub<Output = Self>
900 + core::ops::AddAssign
901 + core::ops::SubAssign
902 + bytemuck::Pod
903 + Eq
904 + Ord
905 + Send
906 + Sync
907{
908 const MAX: Self;
910 #[must_use]
912 fn truncate(value: usize) -> Self;
913 #[must_use]
915 fn zx(self) -> usize;
916 #[must_use]
918 fn sx(self) -> usize;
919 fn sum_nonnegative(slice: &[Self]) -> Option<Self> {
921 let mut acc = Self::zeroed();
922 for &i in slice {
923 if Self::MAX - i < acc {
924 return None;
925 }
926 acc += i;
927 }
928 Some(acc)
929 }
930}
931impl SignedIndex for i32 {
932 const MAX: Self = Self::MAX;
933
934 #[inline(always)]
935 fn truncate(value: usize) -> Self {
936 value as isize as Self
937 }
938
939 #[inline(always)]
940 fn zx(self) -> usize {
941 self as u32 as usize
942 }
943
944 #[inline(always)]
945 fn sx(self) -> usize {
946 self as isize as usize
947 }
948}
949impl SignedIndex for i64 {
950 const MAX: Self = Self::MAX;
951
952 #[inline(always)]
953 fn truncate(value: usize) -> Self {
954 value as isize as Self
955 }
956
957 #[inline(always)]
958 fn zx(self) -> usize {
959 self as u64 as usize
960 }
961
962 #[inline(always)]
963 fn sx(self) -> usize {
964 self as isize as usize
965 }
966}
967impl SignedIndex for isize {
968 const MAX: Self = Self::MAX;
969
970 #[inline(always)]
971 fn truncate(value: usize) -> Self {
972 value as isize
973 }
974
975 #[inline(always)]
976 fn zx(self) -> usize {
977 self as usize
978 }
979
980 #[inline(always)]
981 fn sx(self) -> usize {
982 self as usize
983 }
984}
985pub trait IndexCore:
986 Seal
987 + core::fmt::Debug
988 + core::ops::Not<Output = Self>
989 + core::ops::BitAnd<Output = Self>
990 + core::ops::BitOr<Output = Self>
991 + core::ops::BitXor<Output = Self>
992 + core::ops::Add<Output = Self>
993 + core::ops::Sub<Output = Self>
994 + core::ops::AddAssign
995 + core::ops::SubAssign
996 + bytemuck::Pod
997 + Eq
998 + Ord
999 + Send
1000 + Sync
1001 + Ord
1002{
1003 const MAX: Self;
1004 #[must_use]
1006 fn truncate(value: usize) -> Self;
1007 #[must_use]
1009 fn zx(self) -> usize;
1010}
1011pub trait Index: IndexCore {
1012 type FixedWidth: Index;
1014 type Signed: SignedIndex;
1016 const BITS: u32 = core::mem::size_of::<Self>() as u32 * 8;
1017 #[inline(always)]
1019 fn canonicalize(slice: &[Self]) -> &[Self::FixedWidth] {
1020 bytemuck::cast_slice(slice)
1021 }
1022 #[inline(always)]
1024 fn canonicalize_mut(slice: &mut [Self]) -> &mut [Self::FixedWidth] {
1025 bytemuck::cast_slice_mut(slice)
1026 }
1027 #[inline(always)]
1029 fn from_signed(value: Self::Signed) -> Self {
1030 bytemuck::cast(value)
1031 }
1032 #[inline(always)]
1034 fn to_signed(self) -> Self::Signed {
1035 bytemuck::cast(self)
1036 }
1037 #[inline]
1039 fn sum_nonnegative(slice: &[Self]) -> Option<Self> {
1040 Self::Signed::sum_nonnegative(bytemuck::cast_slice(slice))
1041 .map(Self::from_signed)
1042 }
1043}
1044impl IndexCore for u8 {
1045 const MAX: Self = Self::MAX;
1046
1047 #[inline(always)]
1048 fn truncate(value: usize) -> Self {
1049 value as _
1050 }
1051
1052 #[inline(always)]
1053 fn zx(self) -> usize {
1054 self as _
1055 }
1056}
1057impl IndexCore for u16 {
1058 const MAX: Self = Self::MAX;
1059
1060 #[inline(always)]
1061 fn truncate(value: usize) -> Self {
1062 value as _
1063 }
1064
1065 #[inline(always)]
1066 fn zx(self) -> usize {
1067 self as _
1068 }
1069}
1070impl IndexCore for u32 {
1071 const MAX: Self = Self::MAX;
1072
1073 #[inline(always)]
1074 fn truncate(value: usize) -> Self {
1075 value as _
1076 }
1077
1078 #[inline(always)]
1079 fn zx(self) -> usize {
1080 self as _
1081 }
1082}
1083impl IndexCore for u64 {
1084 const MAX: Self = Self::MAX;
1085
1086 #[inline(always)]
1087 fn truncate(value: usize) -> Self {
1088 value as _
1089 }
1090
1091 #[inline(always)]
1092 fn zx(self) -> usize {
1093 self as _
1094 }
1095}
1096impl IndexCore for u128 {
1097 const MAX: Self = Self::MAX;
1098
1099 #[inline(always)]
1100 fn truncate(value: usize) -> Self {
1101 value as _
1102 }
1103
1104 #[inline(always)]
1105 fn zx(self) -> usize {
1106 self as _
1107 }
1108}
1109impl IndexCore for usize {
1110 const MAX: Self = Self::MAX;
1111
1112 #[inline(always)]
1113 fn truncate(value: usize) -> Self {
1114 value
1115 }
1116
1117 #[inline(always)]
1118 fn zx(self) -> usize {
1119 self
1120 }
1121}
1122impl Index for u32 {
1123 type FixedWidth = u32;
1124 type Signed = i32;
1125}
1126impl Index for u64 {
1127 type FixedWidth = u64;
1128 type Signed = i64;
1129}
1130impl Index for usize {
1131 #[cfg(target_pointer_width = "32")]
1132 type FixedWidth = u32;
1133 #[cfg(target_pointer_width = "64")]
1134 type FixedWidth = u64;
1135 type Signed = isize;
1136}
1137unsafe impl<T: RealField> Conjugate for T {
1138 type Canonical = T;
1139 type Conj = T;
1140
1141 const IS_CANONICAL: bool = true;
1142}
1143unsafe impl<T: RealField> Conjugate for Complex<T> {
1144 type Canonical = Complex<T>;
1145 type Conj = ComplexConj<T>;
1146
1147 const IS_CANONICAL: bool = true;
1148}
1149unsafe impl<T: RealField> Conjugate for ComplexConj<T> {
1150 type Canonical = Complex<T>;
1151 type Conj = Complex<T>;
1152
1153 const IS_CANONICAL: bool = false;
1154}
1155pub trait SimdArch: Copy + Default + Send + Sync {
1156 fn dispatch<R>(self, f: impl pulp::WithSimd<Output = R>) -> R;
1157}
1158impl SimdArch for pulp::Arch {
1159 #[inline]
1160 fn dispatch<R>(self, f: impl pulp::WithSimd<Output = R>) -> R {
1161 self.dispatch(f)
1162 }
1163}
1164impl SimdArch for pulp::Scalar {
1165 #[inline]
1166 fn dispatch<R>(self, f: impl pulp::WithSimd<Output = R>) -> R {
1167 f.with_simd(self)
1168 }
1169}
1170pub trait RefOps:
1171 Sized
1172 + core::ops::Neg<Output = Self>
1173 + core::ops::Add<Output = Self>
1174 + core::ops::Sub<Output = Self>
1175 + core::ops::Mul<Output = Self>
1176 + core::ops::Div<Output = Self>
1177 + core::ops::AddAssign
1178 + core::ops::SubAssign
1179 + core::ops::MulAssign
1180 + core::ops::DivAssign
1181 + for<'a> core::ops::Add<&'a Self, Output = Self>
1182 + for<'a> core::ops::Sub<&'a Self, Output = Self>
1183 + for<'a> core::ops::Mul<&'a Self, Output = Self>
1184 + for<'a> core::ops::Div<&'a Self, Output = Self>
1185 + for<'a> core::ops::AddAssign<&'a Self>
1186 + for<'a> core::ops::SubAssign<&'a Self>
1187 + for<'a> core::ops::MulAssign<&'a Self>
1188 + for<'a> core::ops::DivAssign<&'a Self>
1189 + for<'a> Imply<
1190 &'a Self,
1191 Is: core::ops::Neg<Output = Self>
1192 + core::ops::Add<Output = Self>
1193 + core::ops::Sub<Output = Self>
1194 + core::ops::Mul<Output = Self>
1195 + core::ops::Div<Output = Self>
1196 + core::ops::Add<Self, Output = Self>
1197 + core::ops::Sub<Self, Output = Self>
1198 + core::ops::Mul<Self, Output = Self>
1199 + core::ops::Div<Self, Output = Self>,
1200 >
1201{
1202}
1203impl<T> RefOps for T
1204where
1205 T: core::ops::Neg<Output = Self>
1206 + core::ops::Add<Output = Self>
1207 + core::ops::Sub<Output = Self>
1208 + core::ops::Mul<Output = Self>
1209 + core::ops::Div<Output = Self>
1210 + core::ops::AddAssign
1211 + core::ops::SubAssign
1212 + core::ops::MulAssign
1213 + core::ops::DivAssign
1214 + for<'a> core::ops::Add<&'a T, Output = Self>
1215 + for<'a> core::ops::Sub<&'a T, Output = Self>
1216 + for<'a> core::ops::Mul<&'a T, Output = Self>
1217 + for<'a> core::ops::Div<&'a T, Output = Self>
1218 + for<'a> core::ops::AddAssign<&'a T>
1219 + for<'a> core::ops::SubAssign<&'a T>
1220 + for<'a> core::ops::MulAssign<&'a T>
1221 + for<'a> core::ops::DivAssign<&'a T>,
1222 for<'a> &'a T: core::ops::Neg<Output = T>
1223 + core::ops::Add<Output = T>
1224 + core::ops::Sub<Output = T>
1225 + core::ops::Mul<Output = T>
1226 + core::ops::Div<Output = T>
1227 + core::ops::Add<T, Output = T>
1228 + core::ops::Sub<T, Output = T>
1229 + core::ops::Mul<T, Output = T>
1230 + core::ops::Div<T, Output = T>,
1231{
1232}
1233pub trait ComplexField:
1234 Debug
1235 + Clone
1236 + Conjugate<Canonical = Self>
1237 + PartialEq
1238 + RefOps
1239 + Imply<Self::Real, Is: RefOps>
1240{
1241 const IS_REAL: bool;
1242 const SIMD_ABS_SPLIT_REAL_IMAG: bool = false;
1243 type Arch: SimdArch;
1244 type Unit: ComplexField;
1245 type SimdCtx<S: Simd>: Copy;
1246 type Index: IndexCore;
1247 type Real: RealField;
1248 #[doc(hidden)]
1249 const IS_NATIVE_F32: bool = false;
1250 #[doc(hidden)]
1251 const IS_NATIVE_C32: bool = false;
1252 #[doc(hidden)]
1253 const IS_NATIVE_F64: bool = false;
1254 #[doc(hidden)]
1255 const IS_NATIVE_C64: bool = false;
1256 const SIMD_CAPABILITIES: SimdCapabilities;
1257 type SimdMask<S: Simd>: Copy + Debug;
1258 type SimdMemMask<S: Simd>: Copy + Debug;
1259 type SimdVec<S: Simd>: Pod + Debug;
1260 type SimdIndex<S: Simd>: Pod + Debug;
1261 fn zero_impl() -> Self;
1262 fn one_impl() -> Self;
1263 fn nan_impl() -> Self;
1264 fn infinity_impl() -> Self;
1265 fn from_real_impl(real: &Self::Real) -> Self;
1266 fn from_f64_impl(real: f64) -> Self;
1267 fn real_part_impl(value: &Self) -> Self::Real;
1268 fn imag_part_impl(value: &Self) -> Self::Real;
1269 fn copy_impl(value: &Self) -> Self;
1270 fn conj_impl(value: &Self) -> Self;
1271 fn recip_impl(value: &Self) -> Self;
1272 fn sqrt_impl(value: &Self) -> Self;
1273 fn abs_impl(value: &Self) -> Self::Real;
1274 fn abs1_impl(value: &Self) -> Self::Real;
1275 fn abs2_impl(value: &Self) -> Self::Real;
1276 fn mul_real_impl(lhs: &Self, rhs: &Self::Real) -> Self;
1277 fn mul_pow2_impl(lhs: &Self, rhs: &Self::Real) -> Self;
1278 fn is_finite_impl(value: &Self) -> bool;
1279 fn is_nan_impl(value: &Self) -> bool {
1280 value != value
1281 }
1282 fn simd_ctx<S: Simd>(simd: S) -> Self::SimdCtx<S>;
1283 fn ctx_from_simd<S: Simd>(ctx: &Self::SimdCtx<S>) -> S;
1284 fn simd_mask_between<S: Simd>(
1285 ctx: &Self::SimdCtx<S>,
1286 start: Self::Index,
1287 end: Self::Index,
1288 ) -> Self::SimdMask<S>;
1289 fn simd_mem_mask_between<S: Simd>(
1290 ctx: &Self::SimdCtx<S>,
1291 start: Self::Index,
1292 end: Self::Index,
1293 ) -> Self::SimdMemMask<S>;
1294 unsafe fn simd_mask_load_raw<S: Simd>(
1295 ctx: &Self::SimdCtx<S>,
1296 mask: Self::SimdMemMask<S>,
1297 ptr: *const Self::SimdVec<S>,
1298 ) -> Self::SimdVec<S>;
1299 unsafe fn simd_mask_store_raw<S: Simd>(
1300 ctx: &Self::SimdCtx<S>,
1301 mask: Self::SimdMemMask<S>,
1302 ptr: *mut Self::SimdVec<S>,
1303 values: Self::SimdVec<S>,
1304 );
1305 fn simd_splat<S: Simd>(
1306 ctx: &Self::SimdCtx<S>,
1307 value: &Self,
1308 ) -> Self::SimdVec<S>;
1309 fn simd_splat_real<S: Simd>(
1310 ctx: &Self::SimdCtx<S>,
1311 value: &Self::Real,
1312 ) -> Self::SimdVec<S>;
1313 fn simd_add<S: Simd>(
1314 ctx: &Self::SimdCtx<S>,
1315 lhs: Self::SimdVec<S>,
1316 rhs: Self::SimdVec<S>,
1317 ) -> Self::SimdVec<S>;
1318 fn simd_sub<S: Simd>(
1319 ctx: &Self::SimdCtx<S>,
1320 lhs: Self::SimdVec<S>,
1321 rhs: Self::SimdVec<S>,
1322 ) -> Self::SimdVec<S>;
1323 fn simd_neg<S: Simd>(
1324 ctx: &Self::SimdCtx<S>,
1325 value: Self::SimdVec<S>,
1326 ) -> Self::SimdVec<S>;
1327 fn simd_conj<S: Simd>(
1328 ctx: &Self::SimdCtx<S>,
1329 value: Self::SimdVec<S>,
1330 ) -> Self::SimdVec<S>;
1331 fn simd_abs1<S: Simd>(
1332 ctx: &Self::SimdCtx<S>,
1333 value: Self::SimdVec<S>,
1334 ) -> Self::SimdVec<S>;
1335 fn simd_abs_max<S: Simd>(
1336 ctx: &Self::SimdCtx<S>,
1337 value: Self::SimdVec<S>,
1338 ) -> Self::SimdVec<S>;
1339 fn simd_mul_real<S: Simd>(
1340 ctx: &Self::SimdCtx<S>,
1341 lhs: Self::SimdVec<S>,
1342 real_rhs: Self::SimdVec<S>,
1343 ) -> Self::SimdVec<S>;
1344 fn simd_mul_pow2<S: Simd>(
1345 ctx: &Self::SimdCtx<S>,
1346 lhs: Self::SimdVec<S>,
1347 real_rhs: Self::SimdVec<S>,
1348 ) -> Self::SimdVec<S>;
1349 fn simd_mul<S: Simd>(
1350 ctx: &Self::SimdCtx<S>,
1351 lhs: Self::SimdVec<S>,
1352 rhs: Self::SimdVec<S>,
1353 ) -> Self::SimdVec<S>;
1354 fn simd_conj_mul<S: Simd>(
1355 ctx: &Self::SimdCtx<S>,
1356 lhs: Self::SimdVec<S>,
1357 rhs: Self::SimdVec<S>,
1358 ) -> Self::SimdVec<S>;
1359 fn simd_mul_add<S: Simd>(
1360 ctx: &Self::SimdCtx<S>,
1361 lhs: Self::SimdVec<S>,
1362 rhs: Self::SimdVec<S>,
1363 acc: Self::SimdVec<S>,
1364 ) -> Self::SimdVec<S>;
1365 fn simd_conj_mul_add<S: Simd>(
1366 ctx: &Self::SimdCtx<S>,
1367 lhs: Self::SimdVec<S>,
1368 rhs: Self::SimdVec<S>,
1369 acc: Self::SimdVec<S>,
1370 ) -> Self::SimdVec<S>;
1371 fn simd_abs2<S: Simd>(
1372 ctx: &Self::SimdCtx<S>,
1373 value: Self::SimdVec<S>,
1374 ) -> Self::SimdVec<S>;
1375 fn simd_abs2_add<S: Simd>(
1376 ctx: &Self::SimdCtx<S>,
1377 value: Self::SimdVec<S>,
1378 acc: Self::SimdVec<S>,
1379 ) -> Self::SimdVec<S>;
1380 fn simd_reduce_sum<S: Simd>(
1381 ctx: &Self::SimdCtx<S>,
1382 value: Self::SimdVec<S>,
1383 ) -> Self;
1384 fn simd_reduce_max<S: Simd>(
1385 ctx: &Self::SimdCtx<S>,
1386 value: Self::SimdVec<S>,
1387 ) -> Self;
1388 fn simd_equal<S: Simd>(
1389 ctx: &Self::SimdCtx<S>,
1390 real_lhs: Self::SimdVec<S>,
1391 real_rhs: Self::SimdVec<S>,
1392 ) -> Self::SimdMask<S>;
1393 fn simd_less_than<S: Simd>(
1394 ctx: &Self::SimdCtx<S>,
1395 real_lhs: Self::SimdVec<S>,
1396 real_rhs: Self::SimdVec<S>,
1397 ) -> Self::SimdMask<S>;
1398 fn simd_less_than_or_equal<S: Simd>(
1399 ctx: &Self::SimdCtx<S>,
1400 real_lhs: Self::SimdVec<S>,
1401 real_rhs: Self::SimdVec<S>,
1402 ) -> Self::SimdMask<S>;
1403 fn simd_greater_than<S: Simd>(
1404 ctx: &Self::SimdCtx<S>,
1405 real_lhs: Self::SimdVec<S>,
1406 real_rhs: Self::SimdVec<S>,
1407 ) -> Self::SimdMask<S>;
1408 fn simd_greater_than_or_equal<S: Simd>(
1409 ctx: &Self::SimdCtx<S>,
1410 real_lhs: Self::SimdVec<S>,
1411 real_rhs: Self::SimdVec<S>,
1412 ) -> Self::SimdMask<S>;
1413 fn simd_select<S: Simd>(
1414 ctx: &Self::SimdCtx<S>,
1415 mask: Self::SimdMask<S>,
1416 lhs: Self::SimdVec<S>,
1417 rhs: Self::SimdVec<S>,
1418 ) -> Self::SimdVec<S>;
1419 fn simd_index_select<S: Simd>(
1420 ctx: &Self::SimdCtx<S>,
1421 mask: Self::SimdMask<S>,
1422 lhs: Self::SimdIndex<S>,
1423 rhs: Self::SimdIndex<S>,
1424 ) -> Self::SimdIndex<S>;
1425 fn simd_index_splat<S: Simd>(
1426 ctx: &Self::SimdCtx<S>,
1427 value: Self::Index,
1428 ) -> Self::SimdIndex<S>;
1429 fn simd_index_add<S: Simd>(
1430 ctx: &Self::SimdCtx<S>,
1431 lhs: Self::SimdIndex<S>,
1432 rhs: Self::SimdIndex<S>,
1433 ) -> Self::SimdIndex<S>;
1434 fn simd_index_less_than<S: Simd>(
1435 ctx: &Self::SimdCtx<S>,
1436 lhs: Self::SimdIndex<S>,
1437 rhs: Self::SimdIndex<S>,
1438 ) -> Self::SimdMask<S>;
1439 #[inline(always)]
1440 fn simd_index_greater_than<S: Simd>(
1441 ctx: &Self::SimdCtx<S>,
1442 lhs: Self::SimdIndex<S>,
1443 rhs: Self::SimdIndex<S>,
1444 ) -> Self::SimdMask<S> {
1445 Self::simd_index_less_than(ctx, rhs, lhs)
1446 }
1447 #[inline(always)]
1448 fn simd_index_less_than_or_equal<S: Simd>(
1449 ctx: &Self::SimdCtx<S>,
1450 lhs: Self::SimdIndex<S>,
1451 rhs: Self::SimdIndex<S>,
1452 ) -> Self::SimdMask<S> {
1453 Self::simd_not_mask(ctx, Self::simd_index_less_than(ctx, rhs, lhs))
1454 }
1455 #[inline(always)]
1456 fn simd_index_greater_than_or_equal<S: Simd>(
1457 ctx: &Self::SimdCtx<S>,
1458 lhs: Self::SimdIndex<S>,
1459 rhs: Self::SimdIndex<S>,
1460 ) -> Self::SimdMask<S> {
1461 Self::simd_not_mask(ctx, Self::simd_index_greater_than(ctx, rhs, lhs))
1462 }
1463 fn simd_and_mask<S: Simd>(
1464 ctx: &Self::SimdCtx<S>,
1465 lhs: Self::SimdMask<S>,
1466 rhs: Self::SimdMask<S>,
1467 ) -> Self::SimdMask<S>;
1468 fn simd_or_mask<S: Simd>(
1469 ctx: &Self::SimdCtx<S>,
1470 lhs: Self::SimdMask<S>,
1471 rhs: Self::SimdMask<S>,
1472 ) -> Self::SimdMask<S>;
1473 fn simd_not_mask<S: Simd>(
1474 ctx: &Self::SimdCtx<S>,
1475 mask: Self::SimdMask<S>,
1476 ) -> Self::SimdMask<S>;
1477 fn simd_first_true_mask<S: Simd>(
1478 ctx: &Self::SimdCtx<S>,
1479 value: Self::SimdMask<S>,
1480 ) -> usize;
1481 #[inline(always)]
1482 fn simd_load<S: Simd>(
1483 ctx: &Self::SimdCtx<S>,
1484 ptr: &Self::SimdVec<S>,
1485 ) -> Self::SimdVec<S> {
1486 let simd = Self::ctx_from_simd(ctx);
1487 if const { Self::Unit::IS_NATIVE_F32 } {
1488 simd.deinterleave_shfl_f32s(*ptr)
1489 } else if const { Self::Unit::IS_NATIVE_F64 } {
1490 simd.deinterleave_shfl_f64s(*ptr)
1491 } else {
1492 panic!();
1493 }
1494 }
1495 #[inline(always)]
1496 fn simd_store<S: Simd>(
1497 ctx: &Self::SimdCtx<S>,
1498 ptr: &mut Self::SimdVec<S>,
1499 value: Self::SimdVec<S>,
1500 ) {
1501 let simd = Self::ctx_from_simd(ctx);
1502 if const { Self::Unit::IS_NATIVE_F32 } {
1503 *ptr = simd.interleave_shfl_f32s(value)
1504 } else if const { Self::Unit::IS_NATIVE_F64 } {
1505 *ptr = simd.interleave_shfl_f64s(value)
1506 } else {
1507 panic!();
1508 }
1509 }
1510 #[inline(always)]
1511 unsafe fn simd_mask_load<S: Simd>(
1512 ctx: &Self::SimdCtx<S>,
1513 mask: Self::SimdMemMask<S>,
1514 ptr: *const Self::SimdVec<S>,
1515 ) -> Self::SimdVec<S> {
1516 let simd = Self::ctx_from_simd(ctx);
1517 let value = Self::simd_mask_load_raw(ctx, mask, ptr);
1518 if const { Self::Unit::IS_NATIVE_F32 } {
1519 simd.deinterleave_shfl_f32s(value)
1520 } else if const { Self::Unit::IS_NATIVE_F64 } {
1521 simd.deinterleave_shfl_f64s(value)
1522 } else {
1523 panic!();
1524 }
1525 }
1526 #[inline(always)]
1527 unsafe fn simd_mask_store<S: Simd>(
1528 ctx: &Self::SimdCtx<S>,
1529 mask: Self::SimdMemMask<S>,
1530 ptr: *mut Self::SimdVec<S>,
1531 value: Self::SimdVec<S>,
1532 ) {
1533 let simd = Self::ctx_from_simd(ctx);
1534 if const { Self::Unit::IS_NATIVE_F32 } {
1535 Self::simd_mask_store_raw(
1536 ctx,
1537 mask,
1538 ptr,
1539 simd.interleave_shfl_f32s(value),
1540 )
1541 } else if const { Self::Unit::IS_NATIVE_F64 } {
1542 Self::simd_mask_store_raw(
1543 ctx,
1544 mask,
1545 ptr,
1546 simd.interleave_shfl_f64s(value),
1547 )
1548 } else {
1549 panic!();
1550 }
1551 }
1552 #[inline(always)]
1553 fn simd_iota<S: Simd>(ctx: &Self::SimdCtx<S>) -> Self::SimdIndex<S> {
1554 let simd = Self::ctx_from_simd(ctx);
1555 #[repr(transparent)]
1556 struct Interleave<T>(T);
1557 unsafe impl<T> pulp::Interleave for Interleave<T> {}
1558 unsafe {
1559 if const { Self::Unit::IS_NATIVE_F32 } {
1560 core::mem::transmute_copy::<_, Self::SimdIndex<S>>(
1561 &simd.deinterleave_shfl_f32s(Interleave(
1562 core::mem::transmute_copy::<_, Self::SimdVec<S>>(
1563 &pulp::iota_32::<Interleave<Self>, 64>(),
1564 ),
1565 )),
1566 )
1567 } else if const { Self::Unit::IS_NATIVE_F64 } {
1568 core::mem::transmute_copy::<_, Self::SimdIndex<S>>(
1569 &simd.deinterleave_shfl_f64s(core::mem::transmute_copy::<
1570 _,
1571 Self::SimdVec<S>,
1572 >(&pulp::iota_64::<
1573 Interleave<Self>,
1574 64,
1575 >())),
1576 )
1577 } else {
1578 panic!();
1579 }
1580 }
1581 }
1582}
1583pub trait RealField:
1584 ComplexField<Real = Self, Conj = Self>
1585 + PartialOrd
1586 + num_traits::NumAssign
1587 + num_traits::Num
1588 + RefOps
1589{
1590 fn epsilon_impl() -> Self;
1591 fn nbits_impl() -> usize;
1592 fn min_positive_impl() -> Self;
1593 fn max_positive_impl() -> Self;
1594 fn sqrt_min_positive_impl() -> Self;
1595 fn sqrt_max_positive_impl() -> Self;
1596}
1597impl ComplexField for f32 {
1598 type Arch = pulp::Arch;
1599 type Index = u32;
1600 type Real = Self;
1601 type SimdCtx<S: Simd> = S;
1602 type SimdIndex<S: Simd> = S::u32s;
1603 type SimdMask<S: Simd> = S::m32s;
1604 type SimdMemMask<S: Simd> = pulp::MemMask<S::m32s>;
1605 type SimdVec<S: Simd> = S::f32s;
1606 type Unit = Self;
1607
1608 const IS_NATIVE_F32: bool = true;
1609 const IS_REAL: bool = true;
1610 const SIMD_CAPABILITIES: SimdCapabilities = SimdCapabilities::Simd;
1611
1612 #[inline(always)]
1613 fn zero_impl() -> Self {
1614 0.0
1615 }
1616
1617 #[inline(always)]
1618 fn one_impl() -> Self {
1619 1.0
1620 }
1621
1622 #[inline(always)]
1623 fn nan_impl() -> Self {
1624 Self::NAN
1625 }
1626
1627 #[inline(always)]
1628 fn infinity_impl() -> Self {
1629 Self::INFINITY
1630 }
1631
1632 #[inline(always)]
1633 fn from_real_impl(value: &Self) -> Self {
1634 *value
1635 }
1636
1637 #[inline(always)]
1638 fn from_f64_impl(value: f64) -> Self {
1639 value as _
1640 }
1641
1642 #[inline(always)]
1643 fn real_part_impl(value: &Self) -> Self {
1644 *value
1645 }
1646
1647 #[inline(always)]
1648 fn imag_part_impl(_: &Self) -> Self {
1649 0.0
1650 }
1651
1652 #[inline(always)]
1653 fn copy_impl(value: &Self) -> Self {
1654 *value
1655 }
1656
1657 #[inline(always)]
1658 fn conj_impl(value: &Self) -> Self {
1659 *value
1660 }
1661
1662 #[inline(always)]
1663 fn recip_impl(value: &Self) -> Self {
1664 1.0 / *value
1665 }
1666
1667 #[inline(always)]
1668 fn sqrt_impl(value: &Self) -> Self {
1669 #[cfg(feature = "std")]
1670 {
1671 Self::sqrt(*value)
1672 }
1673 #[cfg(not(feature = "std"))]
1674 {
1675 libm::sqrtf(*value)
1676 }
1677 }
1678
1679 #[inline(always)]
1680 fn abs_impl(value: &Self) -> Self {
1681 (*value).abs()
1682 }
1683
1684 #[inline(always)]
1685 fn abs1_impl(value: &Self) -> Self {
1686 (*value).abs()
1687 }
1688
1689 #[inline(always)]
1690 fn abs2_impl(value: &Self) -> Self {
1691 (*value) * (*value)
1692 }
1693
1694 #[inline(always)]
1695 fn mul_real_impl(lhs: &Self, rhs: &Self) -> Self {
1696 (*lhs) * (*rhs)
1697 }
1698
1699 #[inline(always)]
1700 fn mul_pow2_impl(lhs: &Self, rhs: &Self) -> Self {
1701 (*lhs) * (*rhs)
1702 }
1703
1704 #[inline(always)]
1705 fn is_finite_impl(value: &Self) -> bool {
1706 (*value).is_finite()
1707 }
1708
1709 #[inline(always)]
1710 fn is_nan_impl(value: &Self) -> bool {
1711 (*value).is_nan()
1712 }
1713
1714 #[inline(always)]
1715 fn simd_ctx<S: Simd>(simd: S) -> Self::SimdCtx<S> {
1716 simd
1717 }
1718
1719 #[inline(always)]
1720 fn simd_splat<S: Simd>(
1721 ctx: &Self::SimdCtx<S>,
1722 value: &Self,
1723 ) -> Self::SimdVec<S> {
1724 ctx.splat_f32s(*value)
1725 }
1726
1727 #[inline(always)]
1728 fn simd_splat_real<S: Simd>(
1729 ctx: &Self::SimdCtx<S>,
1730 value: &Self::Real,
1731 ) -> Self::SimdVec<S> {
1732 ctx.splat_f32s(*value)
1733 }
1734
1735 #[inline(always)]
1736 fn simd_add<S: Simd>(
1737 ctx: &Self::SimdCtx<S>,
1738 lhs: Self::SimdVec<S>,
1739 rhs: Self::SimdVec<S>,
1740 ) -> Self::SimdVec<S> {
1741 ctx.add_f32s(lhs, rhs)
1742 }
1743
1744 #[inline(always)]
1745 fn simd_sub<S: Simd>(
1746 ctx: &Self::SimdCtx<S>,
1747 lhs: Self::SimdVec<S>,
1748 rhs: Self::SimdVec<S>,
1749 ) -> Self::SimdVec<S> {
1750 ctx.sub_f32s(lhs, rhs)
1751 }
1752
1753 #[inline(always)]
1754 fn simd_neg<S: Simd>(
1755 ctx: &Self::SimdCtx<S>,
1756 value: Self::SimdVec<S>,
1757 ) -> Self::SimdVec<S> {
1758 ctx.neg_f32s(value)
1759 }
1760
1761 #[inline(always)]
1762 fn simd_conj<S: Simd>(
1763 _: &Self::SimdCtx<S>,
1764 value: Self::SimdVec<S>,
1765 ) -> Self::SimdVec<S> {
1766 value
1767 }
1768
1769 #[inline(always)]
1770 fn simd_abs1<S: Simd>(
1771 ctx: &Self::SimdCtx<S>,
1772 value: Self::SimdVec<S>,
1773 ) -> Self::SimdVec<S> {
1774 ctx.abs_f32s(value)
1775 }
1776
1777 #[inline(always)]
1778 fn simd_mul<S: Simd>(
1779 ctx: &Self::SimdCtx<S>,
1780 lhs: Self::SimdVec<S>,
1781 rhs: Self::SimdVec<S>,
1782 ) -> Self::SimdVec<S> {
1783 ctx.mul_f32s(lhs, rhs)
1784 }
1785
1786 #[inline(always)]
1787 fn simd_mul_real<S: Simd>(
1788 ctx: &Self::SimdCtx<S>,
1789 lhs: Self::SimdVec<S>,
1790 real_rhs: Self::SimdVec<S>,
1791 ) -> Self::SimdVec<S> {
1792 ctx.mul_f32s(lhs, real_rhs)
1793 }
1794
1795 #[inline(always)]
1796 fn simd_mul_pow2<S: Simd>(
1797 ctx: &Self::SimdCtx<S>,
1798 lhs: Self::SimdVec<S>,
1799 real_rhs: Self::SimdVec<S>,
1800 ) -> Self::SimdVec<S> {
1801 ctx.mul_f32s(lhs, real_rhs)
1802 }
1803
1804 #[inline(always)]
1805 fn simd_conj_mul<S: Simd>(
1806 ctx: &Self::SimdCtx<S>,
1807 lhs: Self::SimdVec<S>,
1808 rhs: Self::SimdVec<S>,
1809 ) -> Self::SimdVec<S> {
1810 ctx.mul_f32s(lhs, rhs)
1811 }
1812
1813 #[inline(always)]
1814 fn simd_mul_add<S: Simd>(
1815 ctx: &Self::SimdCtx<S>,
1816 lhs: Self::SimdVec<S>,
1817 rhs: Self::SimdVec<S>,
1818 acc: Self::SimdVec<S>,
1819 ) -> Self::SimdVec<S> {
1820 ctx.mul_add_e_f32s(lhs, rhs, acc)
1821 }
1822
1823 #[inline(always)]
1824 fn simd_conj_mul_add<S: Simd>(
1825 ctx: &Self::SimdCtx<S>,
1826 lhs: Self::SimdVec<S>,
1827 rhs: Self::SimdVec<S>,
1828 acc: Self::SimdVec<S>,
1829 ) -> Self::SimdVec<S> {
1830 ctx.mul_add_e_f32s(lhs, rhs, acc)
1831 }
1832
1833 #[inline(always)]
1834 fn simd_abs2<S: Simd>(
1835 ctx: &Self::SimdCtx<S>,
1836 value: Self::SimdVec<S>,
1837 ) -> Self::SimdVec<S> {
1838 ctx.mul_f32s(value, value)
1839 }
1840
1841 #[inline(always)]
1842 fn simd_abs2_add<S: Simd>(
1843 ctx: &Self::SimdCtx<S>,
1844 value: Self::SimdVec<S>,
1845 acc: Self::SimdVec<S>,
1846 ) -> Self::SimdVec<S> {
1847 ctx.mul_add_e_f32s(value, value, acc)
1848 }
1849
1850 #[inline(always)]
1851 fn simd_reduce_sum<S: Simd>(
1852 ctx: &Self::SimdCtx<S>,
1853 value: Self::SimdVec<S>,
1854 ) -> Self {
1855 ctx.reduce_sum_f32s(value)
1856 }
1857
1858 #[inline(always)]
1859 fn simd_reduce_max<S: Simd>(
1860 ctx: &Self::SimdCtx<S>,
1861 value: Self::SimdVec<S>,
1862 ) -> Self {
1863 ctx.reduce_max_f32s(value)
1864 }
1865
1866 #[inline(always)]
1867 fn simd_equal<S: Simd>(
1868 ctx: &Self::SimdCtx<S>,
1869 real_lhs: Self::SimdVec<S>,
1870 real_rhs: Self::SimdVec<S>,
1871 ) -> Self::SimdMask<S> {
1872 ctx.equal_f32s(real_lhs, real_rhs)
1873 }
1874
1875 #[inline(always)]
1876 fn simd_less_than<S: Simd>(
1877 ctx: &Self::SimdCtx<S>,
1878 real_lhs: Self::SimdVec<S>,
1879 real_rhs: Self::SimdVec<S>,
1880 ) -> Self::SimdMask<S> {
1881 ctx.less_than_f32s(real_lhs, real_rhs)
1882 }
1883
1884 #[inline(always)]
1885 fn simd_greater_than<S: Simd>(
1886 ctx: &Self::SimdCtx<S>,
1887 real_lhs: Self::SimdVec<S>,
1888 real_rhs: Self::SimdVec<S>,
1889 ) -> Self::SimdMask<S> {
1890 ctx.greater_than_f32s(real_lhs, real_rhs)
1891 }
1892
1893 #[inline(always)]
1894 fn simd_less_than_or_equal<S: Simd>(
1895 ctx: &Self::SimdCtx<S>,
1896 real_lhs: Self::SimdVec<S>,
1897 real_rhs: Self::SimdVec<S>,
1898 ) -> Self::SimdMask<S> {
1899 ctx.less_than_or_equal_f32s(real_lhs, real_rhs)
1900 }
1901
1902 #[inline(always)]
1903 fn simd_greater_than_or_equal<S: Simd>(
1904 ctx: &Self::SimdCtx<S>,
1905 real_lhs: Self::SimdVec<S>,
1906 real_rhs: Self::SimdVec<S>,
1907 ) -> Self::SimdMask<S> {
1908 ctx.greater_than_or_equal_f32s(real_lhs, real_rhs)
1909 }
1910
1911 #[inline(always)]
1912 fn simd_select<S: Simd>(
1913 ctx: &Self::SimdCtx<S>,
1914 mask: Self::SimdMask<S>,
1915 lhs: Self::SimdVec<S>,
1916 rhs: Self::SimdVec<S>,
1917 ) -> Self::SimdVec<S> {
1918 ctx.select_f32s(mask, lhs, rhs)
1919 }
1920
1921 #[inline(always)]
1922 fn simd_index_select<S: Simd>(
1923 ctx: &Self::SimdCtx<S>,
1924 mask: Self::SimdMask<S>,
1925 lhs: Self::SimdIndex<S>,
1926 rhs: Self::SimdIndex<S>,
1927 ) -> Self::SimdIndex<S> {
1928 ctx.select_u32s(mask, lhs, rhs)
1929 }
1930
1931 #[inline(always)]
1932 fn simd_index_splat<S: Simd>(
1933 ctx: &Self::SimdCtx<S>,
1934 value: Self::Index,
1935 ) -> Self::SimdIndex<S> {
1936 ctx.splat_u32s(value as _)
1937 }
1938
1939 #[inline(always)]
1940 fn simd_index_add<S: Simd>(
1941 ctx: &Self::SimdCtx<S>,
1942 lhs: Self::SimdIndex<S>,
1943 rhs: Self::SimdIndex<S>,
1944 ) -> Self::SimdIndex<S> {
1945 ctx.add_u32s(lhs, rhs)
1946 }
1947
1948 #[inline(always)]
1949 fn simd_index_less_than<S: Simd>(
1950 ctx: &Self::SimdCtx<S>,
1951 lhs: Self::SimdIndex<S>,
1952 rhs: Self::SimdIndex<S>,
1953 ) -> Self::SimdMask<S> {
1954 ctx.less_than_u32s(lhs, rhs)
1955 }
1956
1957 #[inline(always)]
1958 fn simd_abs_max<S: Simd>(
1959 ctx: &Self::SimdCtx<S>,
1960 value: Self::SimdVec<S>,
1961 ) -> Self::SimdVec<S> {
1962 ctx.abs_f32s(value)
1963 }
1964
1965 #[inline(always)]
1966 fn ctx_from_simd<S: Simd>(ctx: &Self::SimdCtx<S>) -> S {
1967 *ctx
1968 }
1969
1970 #[inline(always)]
1971 fn simd_and_mask<S: Simd>(
1972 simd: &Self::SimdCtx<S>,
1973 lhs: Self::SimdMask<S>,
1974 rhs: Self::SimdMask<S>,
1975 ) -> Self::SimdMask<S> {
1976 simd.and_m32s(lhs, rhs)
1977 }
1978
1979 #[inline(always)]
1980 fn simd_or_mask<S: Simd>(
1981 simd: &Self::SimdCtx<S>,
1982 lhs: Self::SimdMask<S>,
1983 rhs: Self::SimdMask<S>,
1984 ) -> Self::SimdMask<S> {
1985 simd.or_m32s(lhs, rhs)
1986 }
1987
1988 #[inline(always)]
1989 fn simd_not_mask<S: Simd>(
1990 ctx: &Self::SimdCtx<S>,
1991 mask: Self::SimdMask<S>,
1992 ) -> Self::SimdMask<S> {
1993 ctx.not_m32s(mask)
1994 }
1995
1996 #[inline(always)]
1997 fn simd_first_true_mask<S: Simd>(
1998 ctx: &Self::SimdCtx<S>,
1999 value: Self::SimdMask<S>,
2000 ) -> usize {
2001 ctx.first_true_m32s(value)
2002 }
2003
2004 #[inline(always)]
2005 fn simd_mem_mask_between<S: Simd>(
2006 ctx: &Self::SimdCtx<S>,
2007 start: Self::Index,
2008 end: Self::Index,
2009 ) -> Self::SimdMemMask<S> {
2010 ctx.mask_between_m32s(start as _, end as _)
2011 }
2012
2013 #[inline(always)]
2014 fn simd_mask_between<S: Simd>(
2015 ctx: &Self::SimdCtx<S>,
2016 start: Self::Index,
2017 end: Self::Index,
2018 ) -> Self::SimdMask<S> {
2019 ctx.mask_between_m32s(start as _, end as _).mask()
2020 }
2021
2022 #[inline(always)]
2023 unsafe fn simd_mask_load_raw<S: Simd>(
2024 ctx: &Self::SimdCtx<S>,
2025 mask: Self::SimdMemMask<S>,
2026 ptr: *const Self::SimdVec<S>,
2027 ) -> Self::SimdVec<S> {
2028 ctx.mask_load_ptr_f32s(mask, ptr as _)
2029 }
2030
2031 #[inline(always)]
2032 unsafe fn simd_mask_store_raw<S: Simd>(
2033 ctx: &Self::SimdCtx<S>,
2034 mask: Self::SimdMemMask<S>,
2035 ptr: *mut Self::SimdVec<S>,
2036 values: Self::SimdVec<S>,
2037 ) {
2038 ctx.mask_store_ptr_f32s(mask, ptr as _, values);
2039 }
2040}
2041impl RealField for f32 {
2042 #[inline(always)]
2043 fn epsilon_impl() -> Self {
2044 Self::EPSILON
2045 }
2046
2047 #[inline(always)]
2048 fn min_positive_impl() -> Self {
2049 Self::MIN_POSITIVE
2050 }
2051
2052 #[inline(always)]
2053 fn max_positive_impl() -> Self {
2054 Self::MIN_POSITIVE.recip()
2055 }
2056
2057 #[inline(always)]
2058 fn sqrt_min_positive_impl() -> Self {
2059 Self::sqrt_impl(&Self::MIN_POSITIVE)
2060 }
2061
2062 #[inline(always)]
2063 fn sqrt_max_positive_impl() -> Self {
2064 Self::sqrt_impl(&Self::MIN_POSITIVE.recip())
2065 }
2066
2067 #[inline(always)]
2068 fn nbits_impl() -> usize {
2069 Self::MANTISSA_DIGITS as usize
2070 }
2071}
2072impl ComplexField for f64 {
2073 type Arch = pulp::Arch;
2074 type Index = u64;
2075 type Real = Self;
2076 type SimdCtx<S: Simd> = S;
2077 type SimdIndex<S: Simd> = S::u64s;
2078 type SimdMask<S: Simd> = S::m64s;
2079 type SimdMemMask<S: Simd> = pulp::MemMask<S::m64s>;
2080 type SimdVec<S: Simd> = S::f64s;
2081 type Unit = Self;
2082
2083 const IS_NATIVE_F64: bool = true;
2084 const IS_REAL: bool = true;
2085 const SIMD_CAPABILITIES: SimdCapabilities = SimdCapabilities::Simd;
2086
2087 #[inline(always)]
2088 fn zero_impl() -> Self {
2089 0.0
2090 }
2091
2092 #[inline(always)]
2093 fn one_impl() -> Self {
2094 1.0
2095 }
2096
2097 #[inline(always)]
2098 fn nan_impl() -> Self {
2099 Self::NAN
2100 }
2101
2102 #[inline(always)]
2103 fn infinity_impl() -> Self {
2104 Self::INFINITY
2105 }
2106
2107 #[inline(always)]
2108 fn from_real_impl(value: &Self) -> Self {
2109 *value
2110 }
2111
2112 #[inline(always)]
2113 fn from_f64_impl(value: f64) -> Self {
2114 value as _
2115 }
2116
2117 #[inline(always)]
2118 fn real_part_impl(value: &Self) -> Self {
2119 *value
2120 }
2121
2122 #[inline(always)]
2123 fn imag_part_impl(_: &Self) -> Self {
2124 0.0
2125 }
2126
2127 #[inline(always)]
2128 fn copy_impl(value: &Self) -> Self {
2129 *value
2130 }
2131
2132 #[inline(always)]
2133 fn conj_impl(value: &Self) -> Self {
2134 *value
2135 }
2136
2137 #[inline(always)]
2138 fn recip_impl(value: &Self) -> Self {
2139 1.0 / *value
2140 }
2141
2142 #[inline(always)]
2143 fn sqrt_impl(value: &Self) -> Self {
2144 #[cfg(feature = "std")]
2145 {
2146 Self::sqrt(*value)
2147 }
2148 #[cfg(not(feature = "std"))]
2149 {
2150 libm::sqrt(*value)
2151 }
2152 }
2153
2154 #[inline(always)]
2155 fn abs_impl(value: &Self) -> Self {
2156 (*value).abs()
2157 }
2158
2159 #[inline(always)]
2160 fn abs1_impl(value: &Self) -> Self {
2161 (*value).abs()
2162 }
2163
2164 #[inline(always)]
2165 fn abs2_impl(value: &Self) -> Self {
2166 (*value) * (*value)
2167 }
2168
2169 #[inline(always)]
2170 fn mul_real_impl(lhs: &Self, rhs: &Self) -> Self {
2171 (*lhs) * (*rhs)
2172 }
2173
2174 #[inline(always)]
2175 fn mul_pow2_impl(lhs: &Self, rhs: &Self) -> Self {
2176 (*lhs) * (*rhs)
2177 }
2178
2179 #[inline(always)]
2180 fn is_nan_impl(value: &Self) -> bool {
2181 (*value).is_nan()
2182 }
2183
2184 #[inline(always)]
2185 fn simd_ctx<S: Simd>(simd: S) -> Self::SimdCtx<S> {
2186 simd
2187 }
2188
2189 #[inline(always)]
2190 fn simd_splat<S: Simd>(
2191 ctx: &Self::SimdCtx<S>,
2192 value: &Self,
2193 ) -> Self::SimdVec<S> {
2194 ctx.splat_f64s(*value)
2195 }
2196
2197 #[inline(always)]
2198 fn simd_splat_real<S: Simd>(
2199 ctx: &Self::SimdCtx<S>,
2200 value: &Self::Real,
2201 ) -> Self::SimdVec<S> {
2202 ctx.splat_f64s(*value)
2203 }
2204
2205 #[inline(always)]
2206 fn simd_add<S: Simd>(
2207 ctx: &Self::SimdCtx<S>,
2208 lhs: Self::SimdVec<S>,
2209 rhs: Self::SimdVec<S>,
2210 ) -> Self::SimdVec<S> {
2211 ctx.add_f64s(lhs, rhs)
2212 }
2213
2214 #[inline(always)]
2215 fn simd_sub<S: Simd>(
2216 ctx: &Self::SimdCtx<S>,
2217 lhs: Self::SimdVec<S>,
2218 rhs: Self::SimdVec<S>,
2219 ) -> Self::SimdVec<S> {
2220 ctx.sub_f64s(lhs, rhs)
2221 }
2222
2223 #[inline(always)]
2224 fn simd_neg<S: Simd>(
2225 ctx: &Self::SimdCtx<S>,
2226 value: Self::SimdVec<S>,
2227 ) -> Self::SimdVec<S> {
2228 ctx.neg_f64s(value)
2229 }
2230
2231 #[inline(always)]
2232 fn simd_conj<S: Simd>(
2233 _: &Self::SimdCtx<S>,
2234 value: Self::SimdVec<S>,
2235 ) -> Self::SimdVec<S> {
2236 value
2237 }
2238
2239 #[inline(always)]
2240 fn simd_abs1<S: Simd>(
2241 ctx: &Self::SimdCtx<S>,
2242 value: Self::SimdVec<S>,
2243 ) -> Self::SimdVec<S> {
2244 ctx.abs_f64s(value)
2245 }
2246
2247 #[inline(always)]
2248 fn simd_mul<S: Simd>(
2249 ctx: &Self::SimdCtx<S>,
2250 lhs: Self::SimdVec<S>,
2251 rhs: Self::SimdVec<S>,
2252 ) -> Self::SimdVec<S> {
2253 ctx.mul_f64s(lhs, rhs)
2254 }
2255
2256 #[inline(always)]
2257 fn simd_mul_real<S: Simd>(
2258 ctx: &Self::SimdCtx<S>,
2259 lhs: Self::SimdVec<S>,
2260 real_rhs: Self::SimdVec<S>,
2261 ) -> Self::SimdVec<S> {
2262 ctx.mul_f64s(lhs, real_rhs)
2263 }
2264
2265 #[inline(always)]
2266 fn simd_mul_pow2<S: Simd>(
2267 ctx: &Self::SimdCtx<S>,
2268 lhs: Self::SimdVec<S>,
2269 real_rhs: Self::SimdVec<S>,
2270 ) -> Self::SimdVec<S> {
2271 ctx.mul_f64s(lhs, real_rhs)
2272 }
2273
2274 #[inline(always)]
2275 fn simd_conj_mul<S: Simd>(
2276 ctx: &Self::SimdCtx<S>,
2277 lhs: Self::SimdVec<S>,
2278 rhs: Self::SimdVec<S>,
2279 ) -> Self::SimdVec<S> {
2280 ctx.mul_f64s(lhs, rhs)
2281 }
2282
2283 #[inline(always)]
2284 fn simd_mul_add<S: Simd>(
2285 ctx: &Self::SimdCtx<S>,
2286 lhs: Self::SimdVec<S>,
2287 rhs: Self::SimdVec<S>,
2288 acc: Self::SimdVec<S>,
2289 ) -> Self::SimdVec<S> {
2290 ctx.mul_add_e_f64s(lhs, rhs, acc)
2291 }
2292
2293 #[inline(always)]
2294 fn simd_conj_mul_add<S: Simd>(
2295 ctx: &Self::SimdCtx<S>,
2296 lhs: Self::SimdVec<S>,
2297 rhs: Self::SimdVec<S>,
2298 acc: Self::SimdVec<S>,
2299 ) -> Self::SimdVec<S> {
2300 ctx.mul_add_e_f64s(lhs, rhs, acc)
2301 }
2302
2303 #[inline(always)]
2304 fn simd_abs2<S: Simd>(
2305 ctx: &Self::SimdCtx<S>,
2306 value: Self::SimdVec<S>,
2307 ) -> Self::SimdVec<S> {
2308 ctx.mul_f64s(value, value)
2309 }
2310
2311 #[inline(always)]
2312 fn simd_abs2_add<S: Simd>(
2313 ctx: &Self::SimdCtx<S>,
2314 value: Self::SimdVec<S>,
2315 acc: Self::SimdVec<S>,
2316 ) -> Self::SimdVec<S> {
2317 ctx.mul_add_e_f64s(value, value, acc)
2318 }
2319
2320 #[inline(always)]
2321 fn simd_reduce_sum<S: Simd>(
2322 ctx: &Self::SimdCtx<S>,
2323 value: Self::SimdVec<S>,
2324 ) -> Self {
2325 ctx.reduce_sum_f64s(value)
2326 }
2327
2328 #[inline(always)]
2329 fn simd_reduce_max<S: Simd>(
2330 ctx: &Self::SimdCtx<S>,
2331 value: Self::SimdVec<S>,
2332 ) -> Self {
2333 ctx.reduce_max_f64s(value)
2334 }
2335
2336 #[inline(always)]
2337 fn simd_equal<S: Simd>(
2338 ctx: &Self::SimdCtx<S>,
2339 real_lhs: Self::SimdVec<S>,
2340 real_rhs: Self::SimdVec<S>,
2341 ) -> Self::SimdMask<S> {
2342 ctx.equal_f64s(real_lhs, real_rhs)
2343 }
2344
2345 #[inline(always)]
2346 fn simd_less_than<S: Simd>(
2347 ctx: &Self::SimdCtx<S>,
2348 real_lhs: Self::SimdVec<S>,
2349 real_rhs: Self::SimdVec<S>,
2350 ) -> Self::SimdMask<S> {
2351 ctx.less_than_f64s(real_lhs, real_rhs)
2352 }
2353
2354 #[inline(always)]
2355 fn simd_greater_than<S: Simd>(
2356 ctx: &Self::SimdCtx<S>,
2357 real_lhs: Self::SimdVec<S>,
2358 real_rhs: Self::SimdVec<S>,
2359 ) -> Self::SimdMask<S> {
2360 ctx.greater_than_f64s(real_lhs, real_rhs)
2361 }
2362
2363 #[inline(always)]
2364 fn simd_less_than_or_equal<S: Simd>(
2365 ctx: &Self::SimdCtx<S>,
2366 real_lhs: Self::SimdVec<S>,
2367 real_rhs: Self::SimdVec<S>,
2368 ) -> Self::SimdMask<S> {
2369 ctx.less_than_or_equal_f64s(real_lhs, real_rhs)
2370 }
2371
2372 #[inline(always)]
2373 fn simd_greater_than_or_equal<S: Simd>(
2374 ctx: &Self::SimdCtx<S>,
2375 real_lhs: Self::SimdVec<S>,
2376 real_rhs: Self::SimdVec<S>,
2377 ) -> Self::SimdMask<S> {
2378 ctx.greater_than_or_equal_f64s(real_lhs, real_rhs)
2379 }
2380
2381 #[inline(always)]
2382 fn simd_select<S: Simd>(
2383 ctx: &Self::SimdCtx<S>,
2384 mask: Self::SimdMask<S>,
2385 lhs: Self::SimdVec<S>,
2386 rhs: Self::SimdVec<S>,
2387 ) -> Self::SimdVec<S> {
2388 ctx.select_f64s(mask, lhs, rhs)
2389 }
2390
2391 #[inline(always)]
2392 fn simd_index_select<S: Simd>(
2393 ctx: &Self::SimdCtx<S>,
2394 mask: Self::SimdMask<S>,
2395 lhs: Self::SimdIndex<S>,
2396 rhs: Self::SimdIndex<S>,
2397 ) -> Self::SimdIndex<S> {
2398 ctx.select_u64s(mask, lhs, rhs)
2399 }
2400
2401 #[inline(always)]
2402 fn simd_index_splat<S: Simd>(
2403 ctx: &Self::SimdCtx<S>,
2404 value: Self::Index,
2405 ) -> Self::SimdIndex<S> {
2406 ctx.splat_u64s(value as _)
2407 }
2408
2409 #[inline(always)]
2410 fn simd_index_add<S: Simd>(
2411 ctx: &Self::SimdCtx<S>,
2412 lhs: Self::SimdIndex<S>,
2413 rhs: Self::SimdIndex<S>,
2414 ) -> Self::SimdIndex<S> {
2415 ctx.add_u64s(lhs, rhs)
2416 }
2417
2418 #[inline(always)]
2419 fn simd_index_less_than<S: Simd>(
2420 ctx: &Self::SimdCtx<S>,
2421 lhs: Self::SimdIndex<S>,
2422 rhs: Self::SimdIndex<S>,
2423 ) -> Self::SimdMask<S> {
2424 ctx.less_than_u64s(lhs, rhs)
2425 }
2426
2427 #[inline(always)]
2428 fn simd_abs_max<S: Simd>(
2429 ctx: &Self::SimdCtx<S>,
2430 value: Self::SimdVec<S>,
2431 ) -> Self::SimdVec<S> {
2432 ctx.abs_f64s(value)
2433 }
2434
2435 #[inline(always)]
2436 fn ctx_from_simd<S: Simd>(ctx: &Self::SimdCtx<S>) -> S {
2437 *ctx
2438 }
2439
2440 #[inline(always)]
2441 fn simd_and_mask<S: Simd>(
2442 simd: &Self::SimdCtx<S>,
2443 lhs: Self::SimdMask<S>,
2444 rhs: Self::SimdMask<S>,
2445 ) -> Self::SimdMask<S> {
2446 simd.and_m64s(lhs, rhs)
2447 }
2448
2449 #[inline(always)]
2450 fn simd_or_mask<S: Simd>(
2451 simd: &Self::SimdCtx<S>,
2452 lhs: Self::SimdMask<S>,
2453 rhs: Self::SimdMask<S>,
2454 ) -> Self::SimdMask<S> {
2455 simd.or_m64s(lhs, rhs)
2456 }
2457
2458 #[inline(always)]
2459 fn simd_not_mask<S: Simd>(
2460 ctx: &Self::SimdCtx<S>,
2461 mask: Self::SimdMask<S>,
2462 ) -> Self::SimdMask<S> {
2463 ctx.not_m64s(mask)
2464 }
2465
2466 #[inline(always)]
2467 fn simd_first_true_mask<S: Simd>(
2468 ctx: &Self::SimdCtx<S>,
2469 value: Self::SimdMask<S>,
2470 ) -> usize {
2471 ctx.first_true_m64s(value)
2472 }
2473
2474 #[inline(always)]
2475 fn is_finite_impl(value: &Self) -> bool {
2476 (*value).is_finite()
2477 }
2478
2479 #[inline(always)]
2480 fn simd_mem_mask_between<S: Simd>(
2481 ctx: &Self::SimdCtx<S>,
2482 start: Self::Index,
2483 end: Self::Index,
2484 ) -> Self::SimdMemMask<S> {
2485 ctx.mask_between_m64s(start as _, end as _)
2486 }
2487
2488 #[inline(always)]
2489 fn simd_mask_between<S: Simd>(
2490 ctx: &Self::SimdCtx<S>,
2491 start: Self::Index,
2492 end: Self::Index,
2493 ) -> Self::SimdMask<S> {
2494 ctx.mask_between_m64s(start as _, end as _).mask()
2495 }
2496
2497 #[inline(always)]
2498 unsafe fn simd_mask_load_raw<S: Simd>(
2499 ctx: &Self::SimdCtx<S>,
2500 mask: Self::SimdMemMask<S>,
2501 ptr: *const Self::SimdVec<S>,
2502 ) -> Self::SimdVec<S> {
2503 ctx.mask_load_ptr_f64s(mask, ptr as _)
2504 }
2505
2506 #[inline(always)]
2507 unsafe fn simd_mask_store_raw<S: Simd>(
2508 ctx: &Self::SimdCtx<S>,
2509 mask: Self::SimdMemMask<S>,
2510 ptr: *mut Self::SimdVec<S>,
2511 values: Self::SimdVec<S>,
2512 ) {
2513 ctx.mask_store_ptr_f64s(mask, ptr as _, values);
2514 }
2515}
2516impl RealField for f64 {
2517 #[inline(always)]
2518 fn epsilon_impl() -> Self {
2519 Self::EPSILON
2520 }
2521
2522 #[inline(always)]
2523 fn min_positive_impl() -> Self {
2524 Self::MIN_POSITIVE
2525 }
2526
2527 #[inline(always)]
2528 fn max_positive_impl() -> Self {
2529 Self::MIN_POSITIVE.recip()
2530 }
2531
2532 #[inline(always)]
2533 fn sqrt_min_positive_impl() -> Self {
2534 Self::sqrt_impl(&Self::MIN_POSITIVE)
2535 }
2536
2537 #[inline(always)]
2538 fn sqrt_max_positive_impl() -> Self {
2539 Self::sqrt_impl(&Self::MIN_POSITIVE.recip())
2540 }
2541
2542 #[inline(always)]
2543 fn nbits_impl() -> usize {
2544 Self::MANTISSA_DIGITS as usize
2545 }
2546}
2547impl<T: RealField<Unit: ComplexField>> ComplexField for Complex<T> {
2548 type Arch = T::Arch;
2549 type Index = T::Index;
2550 type Real = T;
2551 type SimdCtx<S: Simd> = T::SimdCtx<S>;
2552 type SimdIndex<S: Simd> = T::SimdIndex<S>;
2553 type SimdMask<S: Simd> = T::SimdMask<S>;
2554 type SimdMemMask<S: Simd> = Complex<T::SimdMemMask<S>>;
2555 type SimdVec<S: Simd> = Complex<T::SimdVec<S>>;
2556 type Unit = T::Unit;
2557
2558 const IS_NATIVE_C32: bool = T::IS_NATIVE_F32;
2559 const IS_NATIVE_C64: bool = T::IS_NATIVE_F64;
2560 const IS_REAL: bool = false;
2561 const SIMD_CAPABILITIES: SimdCapabilities = T::SIMD_CAPABILITIES;
2562
2563 #[inline]
2564 fn zero_impl() -> Self {
2565 Complex {
2566 re: T::zero_impl(),
2567 im: T::zero_impl(),
2568 }
2569 }
2570
2571 #[inline]
2572 fn one_impl() -> Self {
2573 Complex {
2574 re: T::one_impl(),
2575 im: T::zero_impl(),
2576 }
2577 }
2578
2579 #[inline]
2580 fn nan_impl() -> Self {
2581 Complex {
2582 re: T::nan_impl(),
2583 im: T::nan_impl(),
2584 }
2585 }
2586
2587 #[inline]
2588 fn infinity_impl() -> Self {
2589 Complex {
2590 re: T::infinity_impl(),
2591 im: T::infinity_impl(),
2592 }
2593 }
2594
2595 #[inline]
2596 fn from_real_impl(real: &Self::Real) -> Self {
2597 Complex {
2598 re: real.clone(),
2599 im: T::zero_impl(),
2600 }
2601 }
2602
2603 #[inline]
2604 fn from_f64_impl(real: f64) -> Self {
2605 Complex {
2606 re: T::from_f64_impl(real),
2607 im: T::zero_impl(),
2608 }
2609 }
2610
2611 #[inline]
2612 fn real_part_impl(value: &Self) -> Self::Real {
2613 value.re.clone()
2614 }
2615
2616 #[inline]
2617 fn imag_part_impl(value: &Self) -> Self::Real {
2618 value.im.clone()
2619 }
2620
2621 #[inline]
2622 fn copy_impl(value: &Self) -> Self {
2623 value.clone()
2624 }
2625
2626 #[inline]
2627 fn conj_impl(value: &Self) -> Self {
2628 Self {
2629 re: value.re.clone(),
2630 im: value.im.neg_by_ref(),
2631 }
2632 }
2633
2634 #[inline]
2635 fn recip_impl(value: &Self) -> Self {
2636 let (re, im) = recip_impl(value.re.clone(), value.im.clone());
2637 Complex { re, im }
2638 }
2639
2640 #[inline]
2641 fn sqrt_impl(value: &Self) -> Self {
2642 let (re, im) = sqrt_impl(value.re.clone(), value.im.clone());
2643 Complex { re, im }
2644 }
2645
2646 #[inline]
2647 fn abs_impl(value: &Self) -> Self::Real {
2648 abs_impl(value.re.clone(), value.im.clone())
2649 }
2650
2651 #[inline]
2652 fn abs1_impl(value: &Self) -> Self::Real {
2653 use crate::ext::*;
2654 value.re.abs1() + value.im.abs1()
2655 }
2656
2657 #[inline]
2658 fn abs2_impl(value: &Self) -> Self::Real {
2659 use crate::ext::*;
2660 value.re.abs2() + value.im.abs2()
2661 }
2662
2663 #[inline]
2664 fn mul_real_impl(lhs: &Self, rhs: &Self::Real) -> Self {
2665 Complex {
2666 re: &lhs.re * rhs,
2667 im: &lhs.im * rhs,
2668 }
2669 }
2670
2671 #[inline]
2672 fn mul_pow2_impl(lhs: &Self, rhs: &Self::Real) -> Self {
2673 use crate::ext::*;
2674 Complex {
2675 re: lhs.re.mul_pow2(rhs),
2676 im: lhs.im.mul_pow2(rhs),
2677 }
2678 }
2679
2680 #[inline]
2681 fn is_finite_impl(value: &Self) -> bool {
2682 use crate::ext::*;
2683 value.re.is_finite() && value.im.is_finite()
2684 }
2685
2686 #[inline(always)]
2687 fn simd_ctx<S: Simd>(simd: S) -> Self::SimdCtx<S> {
2688 T::simd_ctx(simd)
2689 }
2690
2691 #[inline(always)]
2692 fn ctx_from_simd<S: Simd>(ctx: &Self::SimdCtx<S>) -> S {
2693 T::ctx_from_simd(ctx)
2694 }
2695
2696 #[inline(always)]
2697 fn simd_splat<S: Simd>(
2698 ctx: &Self::SimdCtx<S>,
2699 value: &Self,
2700 ) -> Self::SimdVec<S> {
2701 Complex {
2702 re: T::simd_splat(ctx, &value.re),
2703 im: T::simd_splat(ctx, &value.im),
2704 }
2705 }
2706
2707 #[inline(always)]
2708 fn simd_splat_real<S: Simd>(
2709 ctx: &Self::SimdCtx<S>,
2710 value: &Self::Real,
2711 ) -> Self::SimdVec<S> {
2712 Complex {
2713 re: T::simd_splat_real(ctx, value),
2714 im: T::simd_splat_real(ctx, value),
2715 }
2716 }
2717
2718 #[inline(always)]
2719 fn simd_add<S: Simd>(
2720 ctx: &Self::SimdCtx<S>,
2721 lhs: Self::SimdVec<S>,
2722 rhs: Self::SimdVec<S>,
2723 ) -> Self::SimdVec<S> {
2724 Complex {
2725 re: T::simd_add(ctx, lhs.re, rhs.re),
2726 im: T::simd_add(ctx, lhs.im, rhs.im),
2727 }
2728 }
2729
2730 #[inline(always)]
2731 fn simd_sub<S: Simd>(
2732 ctx: &Self::SimdCtx<S>,
2733 lhs: Self::SimdVec<S>,
2734 rhs: Self::SimdVec<S>,
2735 ) -> Self::SimdVec<S> {
2736 Complex {
2737 re: T::simd_sub(ctx, lhs.re, rhs.re),
2738 im: T::simd_sub(ctx, lhs.im, rhs.im),
2739 }
2740 }
2741
2742 #[inline(always)]
2743 fn simd_neg<S: Simd>(
2744 ctx: &Self::SimdCtx<S>,
2745 value: Self::SimdVec<S>,
2746 ) -> Self::SimdVec<S> {
2747 Complex {
2748 re: T::simd_neg(ctx, value.re),
2749 im: T::simd_neg(ctx, value.im),
2750 }
2751 }
2752
2753 #[inline(always)]
2754 fn simd_conj<S: Simd>(
2755 ctx: &Self::SimdCtx<S>,
2756 value: Self::SimdVec<S>,
2757 ) -> Self::SimdVec<S> {
2758 Complex {
2759 re: value.re,
2760 im: T::simd_neg(ctx, value.im),
2761 }
2762 }
2763
2764 #[inline(always)]
2765 fn simd_abs1<S: Simd>(
2766 ctx: &Self::SimdCtx<S>,
2767 value: Self::SimdVec<S>,
2768 ) -> Self::SimdVec<S> {
2769 let v = T::simd_add(
2770 ctx,
2771 T::simd_abs1(ctx, value.re),
2772 T::simd_abs1(ctx, value.im),
2773 );
2774 Complex { re: v, im: v }
2775 }
2776
2777 #[inline(always)]
2778 fn simd_abs_max<S: Simd>(
2779 ctx: &Self::SimdCtx<S>,
2780 value: Self::SimdVec<S>,
2781 ) -> Self::SimdVec<S> {
2782 let re = T::simd_abs_max(ctx, value.re);
2783 let im = T::simd_abs_max(ctx, value.im);
2784 let v = T::simd_select(ctx, T::simd_greater_than(ctx, re, im), re, im);
2785 Complex { re: v, im: v }
2786 }
2787
2788 #[inline(always)]
2789 fn simd_mul_real<S: Simd>(
2790 ctx: &Self::SimdCtx<S>,
2791 lhs: Self::SimdVec<S>,
2792 real_rhs: Self::SimdVec<S>,
2793 ) -> Self::SimdVec<S> {
2794 Complex {
2795 re: T::simd_mul_real(ctx, lhs.re, real_rhs.re),
2796 im: T::simd_mul_real(ctx, lhs.im, real_rhs.re),
2797 }
2798 }
2799
2800 #[inline(always)]
2801 fn simd_mul_pow2<S: Simd>(
2802 ctx: &Self::SimdCtx<S>,
2803 lhs: Self::SimdVec<S>,
2804 real_rhs: Self::SimdVec<S>,
2805 ) -> Self::SimdVec<S> {
2806 Complex {
2807 re: T::simd_mul_pow2(ctx, lhs.re, real_rhs.re),
2808 im: T::simd_mul_pow2(ctx, lhs.im, real_rhs.re),
2809 }
2810 }
2811
2812 #[inline(always)]
2813 fn simd_mul<S: Simd>(
2814 ctx: &Self::SimdCtx<S>,
2815 lhs: Self::SimdVec<S>,
2816 rhs: Self::SimdVec<S>,
2817 ) -> Self::SimdVec<S> {
2818 Complex {
2819 re: T::simd_mul_add(
2820 ctx,
2821 lhs.re,
2822 rhs.re,
2823 T::simd_neg(ctx, T::simd_mul(ctx, lhs.im, rhs.im)),
2824 ),
2825 im: T::simd_mul_add(
2826 ctx,
2827 lhs.re,
2828 rhs.im,
2829 T::simd_mul(ctx, lhs.im, rhs.re),
2830 ),
2831 }
2832 }
2833
2834 #[inline(always)]
2835 fn simd_conj_mul<S: Simd>(
2836 ctx: &Self::SimdCtx<S>,
2837 lhs: Self::SimdVec<S>,
2838 rhs: Self::SimdVec<S>,
2839 ) -> Self::SimdVec<S> {
2840 Complex {
2841 re: T::simd_mul_add(
2842 ctx,
2843 lhs.re,
2844 rhs.re,
2845 T::simd_mul(ctx, lhs.im, rhs.im),
2846 ),
2847 im: T::simd_mul_add(
2848 ctx,
2849 lhs.re,
2850 rhs.im,
2851 T::simd_neg(ctx, T::simd_mul(ctx, lhs.im, rhs.re)),
2852 ),
2853 }
2854 }
2855
2856 #[inline(always)]
2857 fn simd_mul_add<S: Simd>(
2858 ctx: &Self::SimdCtx<S>,
2859 lhs: Self::SimdVec<S>,
2860 rhs: Self::SimdVec<S>,
2861 acc: Self::SimdVec<S>,
2862 ) -> Self::SimdVec<S> {
2863 Complex {
2864 re: T::simd_mul_add(
2865 ctx,
2866 T::simd_neg(ctx, lhs.im),
2867 rhs.im,
2868 T::simd_mul_add(ctx, lhs.re, rhs.re, acc.re),
2869 ),
2870 im: T::simd_mul_add(
2871 ctx,
2872 lhs.re,
2873 rhs.im,
2874 T::simd_mul_add(ctx, lhs.im, rhs.re, acc.im),
2875 ),
2876 }
2877 }
2878
2879 #[inline(always)]
2880 fn simd_conj_mul_add<S: Simd>(
2881 ctx: &Self::SimdCtx<S>,
2882 lhs: Self::SimdVec<S>,
2883 rhs: Self::SimdVec<S>,
2884 acc: Self::SimdVec<S>,
2885 ) -> Self::SimdVec<S> {
2886 Complex {
2887 re: T::simd_mul_add(
2888 ctx,
2889 lhs.im,
2890 rhs.im,
2891 T::simd_mul_add(ctx, lhs.re, rhs.re, acc.re),
2892 ),
2893 im: T::simd_mul_add(
2894 ctx,
2895 lhs.re,
2896 rhs.im,
2897 T::simd_mul_add(ctx, T::simd_neg(ctx, lhs.im), rhs.re, acc.im),
2898 ),
2899 }
2900 }
2901
2902 #[inline(always)]
2903 fn simd_abs2<S: Simd>(
2904 ctx: &Self::SimdCtx<S>,
2905 value: Self::SimdVec<S>,
2906 ) -> Self::SimdVec<S> {
2907 let v = T::simd_abs2_add(ctx, value.re, T::simd_abs2(ctx, value.im));
2908 Complex { re: v, im: v }
2909 }
2910
2911 #[inline(always)]
2912 fn simd_abs2_add<S: Simd>(
2913 ctx: &Self::SimdCtx<S>,
2914 value: Self::SimdVec<S>,
2915 acc: Self::SimdVec<S>,
2916 ) -> Self::SimdVec<S> {
2917 let v = T::simd_abs2_add(
2918 ctx,
2919 value.re,
2920 T::simd_abs2_add(ctx, value.im, acc.re),
2921 );
2922 Complex { re: v, im: v }
2923 }
2924
2925 #[inline(always)]
2926 fn simd_reduce_sum<S: Simd>(
2927 ctx: &Self::SimdCtx<S>,
2928 value: Self::SimdVec<S>,
2929 ) -> Self {
2930 Complex {
2931 re: T::simd_reduce_sum(ctx, value.re),
2932 im: T::simd_reduce_sum(ctx, value.im),
2933 }
2934 }
2935
2936 #[inline(always)]
2937 fn simd_reduce_max<S: Simd>(
2938 ctx: &Self::SimdCtx<S>,
2939 value: Self::SimdVec<S>,
2940 ) -> Self {
2941 Complex {
2942 re: T::simd_reduce_max(ctx, value.re),
2943 im: T::simd_reduce_max(ctx, value.im),
2944 }
2945 }
2946
2947 #[inline(always)]
2948 fn simd_equal<S: Simd>(
2949 ctx: &Self::SimdCtx<S>,
2950 real_lhs: Self::SimdVec<S>,
2951 real_rhs: Self::SimdVec<S>,
2952 ) -> Self::SimdMask<S> {
2953 T::simd_and_mask(
2954 ctx,
2955 T::simd_equal(ctx, real_lhs.re, real_rhs.re),
2956 T::simd_equal(ctx, real_lhs.im, real_rhs.im),
2957 )
2958 }
2959
2960 #[inline(always)]
2961 fn simd_less_than<S: Simd>(
2962 ctx: &Self::SimdCtx<S>,
2963 real_lhs: Self::SimdVec<S>,
2964 real_rhs: Self::SimdVec<S>,
2965 ) -> Self::SimdMask<S> {
2966 T::simd_less_than(ctx, real_lhs.re, real_rhs.re)
2967 }
2968
2969 #[inline(always)]
2970 fn simd_less_than_or_equal<S: Simd>(
2971 ctx: &Self::SimdCtx<S>,
2972 real_lhs: Self::SimdVec<S>,
2973 real_rhs: Self::SimdVec<S>,
2974 ) -> Self::SimdMask<S> {
2975 T::simd_less_than_or_equal(ctx, real_lhs.re, real_rhs.re)
2976 }
2977
2978 #[inline(always)]
2979 fn simd_greater_than<S: Simd>(
2980 ctx: &Self::SimdCtx<S>,
2981 real_lhs: Self::SimdVec<S>,
2982 real_rhs: Self::SimdVec<S>,
2983 ) -> Self::SimdMask<S> {
2984 T::simd_greater_than(ctx, real_lhs.re, real_rhs.re)
2985 }
2986
2987 #[inline(always)]
2988 fn simd_greater_than_or_equal<S: Simd>(
2989 ctx: &Self::SimdCtx<S>,
2990 real_lhs: Self::SimdVec<S>,
2991 real_rhs: Self::SimdVec<S>,
2992 ) -> Self::SimdMask<S> {
2993 T::simd_greater_than_or_equal(ctx, real_lhs.re, real_rhs.re)
2994 }
2995
2996 #[inline(always)]
2997 fn simd_select<S: Simd>(
2998 ctx: &Self::SimdCtx<S>,
2999 mask: Self::SimdMask<S>,
3000 lhs: Self::SimdVec<S>,
3001 rhs: Self::SimdVec<S>,
3002 ) -> Self::SimdVec<S> {
3003 Complex {
3004 re: T::simd_select(ctx, mask, lhs.re, rhs.re),
3005 im: T::simd_select(ctx, mask, lhs.im, rhs.im),
3006 }
3007 }
3008
3009 #[inline(always)]
3010 fn simd_index_select<S: Simd>(
3011 ctx: &Self::SimdCtx<S>,
3012 mask: Self::SimdMask<S>,
3013 lhs: Self::SimdIndex<S>,
3014 rhs: Self::SimdIndex<S>,
3015 ) -> Self::SimdIndex<S> {
3016 T::simd_index_select(ctx, mask, lhs, rhs)
3017 }
3018
3019 #[inline(always)]
3020 fn simd_index_splat<S: Simd>(
3021 ctx: &Self::SimdCtx<S>,
3022 value: Self::Index,
3023 ) -> Self::SimdIndex<S> {
3024 T::simd_index_splat(ctx, value)
3025 }
3026
3027 #[inline(always)]
3028 fn simd_index_add<S: Simd>(
3029 ctx: &Self::SimdCtx<S>,
3030 lhs: Self::SimdIndex<S>,
3031 rhs: Self::SimdIndex<S>,
3032 ) -> Self::SimdIndex<S> {
3033 T::simd_index_add(ctx, lhs, rhs)
3034 }
3035
3036 #[inline(always)]
3037 fn simd_index_less_than<S: Simd>(
3038 ctx: &Self::SimdCtx<S>,
3039 lhs: Self::SimdIndex<S>,
3040 rhs: Self::SimdIndex<S>,
3041 ) -> Self::SimdMask<S> {
3042 T::simd_index_less_than(ctx, lhs, rhs)
3043 }
3044
3045 #[inline(always)]
3046 fn simd_and_mask<S: Simd>(
3047 ctx: &Self::SimdCtx<S>,
3048 lhs: Self::SimdMask<S>,
3049 rhs: Self::SimdMask<S>,
3050 ) -> Self::SimdMask<S> {
3051 T::simd_and_mask(ctx, lhs, rhs)
3052 }
3053
3054 #[inline(always)]
3055 fn simd_or_mask<S: Simd>(
3056 ctx: &Self::SimdCtx<S>,
3057 lhs: Self::SimdMask<S>,
3058 rhs: Self::SimdMask<S>,
3059 ) -> Self::SimdMask<S> {
3060 T::simd_or_mask(ctx, lhs, rhs)
3061 }
3062
3063 #[inline(always)]
3064 fn simd_not_mask<S: Simd>(
3065 ctx: &Self::SimdCtx<S>,
3066 mask: Self::SimdMask<S>,
3067 ) -> Self::SimdMask<S> {
3068 T::simd_not_mask(ctx, mask)
3069 }
3070
3071 #[inline(always)]
3072 fn simd_first_true_mask<S: Simd>(
3073 ctx: &Self::SimdCtx<S>,
3074 value: Self::SimdMask<S>,
3075 ) -> usize {
3076 T::simd_first_true_mask(ctx, value)
3077 }
3078
3079 #[inline(always)]
3080 fn simd_mem_mask_between<S: Simd>(
3081 ctx: &Self::SimdCtx<S>,
3082 start: Self::Index,
3083 end: Self::Index,
3084 ) -> Self::SimdMemMask<S> {
3085 let n = core::mem::size_of::<Self::SimdVec<S>>()
3086 / core::mem::size_of::<Self>();
3087 let start = start.zx() * 2;
3088 let end = end.zx() * 2;
3089 let mut sa = start.min(n);
3090 let mut ea = end.min(n);
3091 let mut sb = start.max(n) - n;
3092 let mut eb = end.max(n) - n;
3093 if sa == ea {
3094 sa = 0;
3095 ea = 0;
3096 }
3097 if sb == eb {
3098 sb = 0;
3099 eb = 0;
3100 }
3101 let re = T::simd_mem_mask_between(
3102 ctx,
3103 T::Index::truncate(sa),
3104 T::Index::truncate(ea),
3105 );
3106 let im = T::simd_mem_mask_between(
3107 ctx,
3108 T::Index::truncate(sb),
3109 T::Index::truncate(eb),
3110 );
3111 Complex { re, im }
3112 }
3113
3114 #[inline(always)]
3115 fn simd_mask_between<S: Simd>(
3116 ctx: &Self::SimdCtx<S>,
3117 start: Self::Index,
3118 end: Self::Index,
3119 ) -> Self::SimdMask<S> {
3120 T::simd_mask_between(ctx, start, end)
3121 }
3122
3123 #[inline(always)]
3124 unsafe fn simd_mask_load_raw<S: Simd>(
3125 ctx: &Self::SimdCtx<S>,
3126 mask: Self::SimdMemMask<S>,
3127 ptr: *const Self::SimdVec<S>,
3128 ) -> Self::SimdVec<S> {
3129 Complex {
3130 re: T::simd_mask_load_raw(
3131 ctx,
3132 mask.re,
3133 core::ptr::addr_of!((*ptr).re),
3134 ),
3135 im: T::simd_mask_load_raw(
3136 ctx,
3137 mask.im,
3138 core::ptr::addr_of!((*ptr).im),
3139 ),
3140 }
3141 }
3142
3143 #[inline(always)]
3144 unsafe fn simd_mask_store_raw<S: Simd>(
3145 ctx: &Self::SimdCtx<S>,
3146 mask: Self::SimdMemMask<S>,
3147 ptr: *mut Self::SimdVec<S>,
3148 values: Self::SimdVec<S>,
3149 ) {
3150 T::simd_mask_store_raw(
3151 ctx,
3152 mask.re,
3153 core::ptr::addr_of_mut!((*ptr).re),
3154 values.re,
3155 );
3156 T::simd_mask_store_raw(
3157 ctx,
3158 mask.im,
3159 core::ptr::addr_of_mut!((*ptr).im),
3160 values.im,
3161 );
3162 }
3163}
3164#[repr(transparent)]
3165#[doc(hidden)]
3166#[derive(Copy, Clone, Debug, PartialEq)]
3167pub struct ComplexImpl<T>(Complex<T>);
3168#[repr(transparent)]
3169#[doc(hidden)]
3170#[derive(Copy, Clone, Debug, PartialEq)]
3171pub struct ComplexImplConj<T>(Complex<T>);
3172unsafe impl Conjugate for ComplexImpl<f32> {
3173 type Canonical = ComplexImpl<f32>;
3174 type Conj = ComplexImplConj<f32>;
3175
3176 const IS_CANONICAL: bool = true;
3177}
3178unsafe impl Conjugate for ComplexImplConj<f32> {
3179 type Canonical = ComplexImpl<f32>;
3180 type Conj = ComplexImpl<f32>;
3181
3182 const IS_CANONICAL: bool = false;
3183}
3184unsafe impl Conjugate for ComplexImpl<f64> {
3185 type Canonical = ComplexImpl<f64>;
3186 type Conj = ComplexImplConj<f64>;
3187
3188 const IS_CANONICAL: bool = true;
3189}
3190unsafe impl Conjugate for ComplexImplConj<f64> {
3191 type Canonical = ComplexImpl<f64>;
3192 type Conj = ComplexImpl<f64>;
3193
3194 const IS_CANONICAL: bool = false;
3195}
3196impl<T: RealField> core::ops::Neg for ComplexImpl<T> {
3197 type Output = ComplexImpl<T>;
3198
3199 #[inline]
3200 fn neg(self) -> Self::Output {
3201 use math_utils::*;
3202 ComplexImpl(neg(&self.0))
3203 }
3204}
3205impl<T: RealField> core::ops::Neg for &ComplexImpl<T> {
3206 type Output = ComplexImpl<T>;
3207
3208 #[inline]
3209 fn neg(self) -> Self::Output {
3210 use math_utils::*;
3211 ComplexImpl(neg(&self.0))
3212 }
3213}
3214impl_op!({
3215 impl<T: RealField> Add for ComplexImpl<T> {
3216 fn add(self, rhs: Self) -> Self::Output {
3217 use math_utils::*;
3218 ComplexImpl(add(&self.0, &rhs.0))
3219 }
3220 }
3221 impl<T: RealField> Sub for ComplexImpl<T> {
3222 fn sub(self, rhs: Self) -> Self::Output {
3223 use math_utils::*;
3224 ComplexImpl(sub(&self.0, &rhs.0))
3225 }
3226 }
3227 impl<T: RealField> Mul for ComplexImpl<T> {
3228 fn mul(self, rhs: Self) -> Self::Output {
3229 use math_utils::*;
3230 ComplexImpl(mul(&self.0, &rhs.0))
3231 }
3232 }
3233 impl<T: RealField> Div for ComplexImpl<T> {
3234 fn div(self, rhs: Self) -> Self::Output {
3235 use math_utils::*;
3236 ComplexImpl(div(&self.0, &rhs.0))
3237 }
3238 }
3239});
3240impl_assign_op!({
3241 impl<T: RealField> AddAssign for ComplexImpl<T> {
3242 fn add_assign(&mut self, rhs: Self) {
3243 use math_utils::*;
3244 *self = ComplexImpl(add(&self.0, &rhs.0));
3245 }
3246 }
3247 impl<T: RealField> SubAssign for ComplexImpl<T> {
3248 fn sub_assign(&mut self, rhs: Self) {
3249 use math_utils::*;
3250 *self = ComplexImpl(sub(&self.0, &rhs.0));
3251 }
3252 }
3253 impl<T: RealField> MulAssign for ComplexImpl<T> {
3254 fn mul_assign(&mut self, rhs: Self) {
3255 use math_utils::*;
3256 *self = ComplexImpl(mul(&self.0, &rhs.0));
3257 }
3258 }
3259 impl<T: RealField> DivAssign for ComplexImpl<T> {
3260 fn div_assign(&mut self, rhs: Self) {
3261 use math_utils::*;
3262 *self = ComplexImpl(div(&self.0, &rhs.0));
3263 }
3264 }
3265});
3266impl<T> From<Complex<T>> for ComplexImpl<T> {
3267 #[inline]
3268 fn from(value: Complex<T>) -> Self {
3269 Self(value)
3270 }
3271}
3272impl ComplexField for ComplexImpl<f32> {
3273 type Arch = pulp::Arch;
3274 type Index = u32;
3275 type Real = f32;
3276 type SimdCtx<S: Simd> = S;
3277 type SimdIndex<S: Simd> = S::u32s;
3278 type SimdMask<S: Simd> = S::m32s;
3279 type SimdMemMask<S: Simd> = pulp::MemMask<S::m32s>;
3280 type SimdVec<S: Simd> = S::c32s;
3281 type Unit = f32;
3282
3283 const IS_NATIVE_C32: bool = true;
3284 const IS_REAL: bool = false;
3285 const SIMD_ABS_SPLIT_REAL_IMAG: bool = true;
3286 const SIMD_CAPABILITIES: SimdCapabilities = SimdCapabilities::Simd;
3287
3288 #[inline]
3289 fn zero_impl() -> Self {
3290 Complex {
3291 re: f32::zero_impl(),
3292 im: f32::zero_impl(),
3293 }
3294 .into()
3295 }
3296
3297 #[inline]
3298 fn one_impl() -> Self {
3299 Complex {
3300 re: f32::one_impl(),
3301 im: f32::zero_impl(),
3302 }
3303 .into()
3304 }
3305
3306 #[inline]
3307 fn nan_impl() -> Self {
3308 Complex {
3309 re: f32::nan_impl(),
3310 im: f32::nan_impl(),
3311 }
3312 .into()
3313 }
3314
3315 #[inline]
3316 fn infinity_impl() -> Self {
3317 Complex {
3318 re: f32::infinity_impl(),
3319 im: f32::infinity_impl(),
3320 }
3321 .into()
3322 }
3323
3324 #[inline]
3325 fn from_real_impl(real: &Self::Real) -> Self {
3326 Complex {
3327 re: real.clone(),
3328 im: f32::zero_impl(),
3329 }
3330 .into()
3331 }
3332
3333 #[inline]
3334 fn from_f64_impl(real: f64) -> Self {
3335 Complex {
3336 re: f32::from_f64_impl(real),
3337 im: f32::zero_impl(),
3338 }
3339 .into()
3340 }
3341
3342 #[inline]
3343 fn real_part_impl(value: &Self) -> Self::Real {
3344 value.0.re.clone()
3345 }
3346
3347 #[inline]
3348 fn imag_part_impl(value: &Self) -> Self::Real {
3349 value.0.im.clone()
3350 }
3351
3352 #[inline]
3353 fn copy_impl(value: &Self) -> Self {
3354 value.clone()
3355 }
3356
3357 #[inline]
3358 fn conj_impl(value: &Self) -> Self {
3359 Complex {
3360 re: value.0.re.clone(),
3361 im: value.0.im.neg_by_ref(),
3362 }
3363 .into()
3364 }
3365
3366 #[inline]
3367 fn recip_impl(value: &Self) -> Self {
3368 let (re, im) = recip_impl(value.0.re.clone(), value.0.im.clone());
3369 Complex { re, im }.into()
3370 }
3371
3372 #[inline]
3373 fn sqrt_impl(value: &Self) -> Self {
3374 let (re, im) = sqrt_impl(value.0.re.clone(), value.0.im.clone());
3375 Complex { re, im }.into()
3376 }
3377
3378 #[inline]
3379 fn abs_impl(value: &Self) -> Self::Real {
3380 abs_impl(value.0.re.clone(), value.0.im.clone())
3381 }
3382
3383 #[inline]
3384 fn abs1_impl(value: &Self) -> Self::Real {
3385 use crate::ext::*;
3386 value.0.re.abs1() + value.0.im.abs1()
3387 }
3388
3389 #[inline]
3390 fn abs2_impl(value: &Self) -> Self::Real {
3391 use crate::ext::*;
3392 value.0.re.abs2() + value.0.im.abs2()
3393 }
3394
3395 #[inline]
3396 fn mul_real_impl(lhs: &Self, rhs: &Self::Real) -> Self {
3397 Complex {
3398 re: lhs.0.re * rhs,
3399 im: lhs.0.im * rhs,
3400 }
3401 .into()
3402 }
3403
3404 #[inline]
3405 fn mul_pow2_impl(lhs: &Self, rhs: &Self::Real) -> Self {
3406 use crate::ext::*;
3407 Complex {
3408 re: lhs.0.re.mul_pow2(rhs),
3409 im: lhs.0.im.mul_pow2(rhs),
3410 }
3411 .into()
3412 }
3413
3414 #[inline]
3415 fn is_finite_impl(value: &Self) -> bool {
3416 value.0.re.is_finite() && value.0.im.is_finite()
3417 }
3418
3419 #[inline(always)]
3420 fn simd_ctx<S: Simd>(simd: S) -> Self::SimdCtx<S> {
3421 f32::simd_ctx(simd)
3422 }
3423
3424 #[inline(always)]
3425 fn ctx_from_simd<S: Simd>(ctx: &Self::SimdCtx<S>) -> S {
3426 f32::ctx_from_simd(ctx)
3427 }
3428
3429 #[inline(always)]
3430 fn simd_splat<S: Simd>(
3431 ctx: &Self::SimdCtx<S>,
3432 value: &Self,
3433 ) -> Self::SimdVec<S> {
3434 ctx.splat_c32s(value.0)
3435 }
3436
3437 #[inline(always)]
3438 fn simd_splat_real<S: Simd>(
3439 ctx: &Self::SimdCtx<S>,
3440 value: &Self::Real,
3441 ) -> Self::SimdVec<S> {
3442 ctx.splat_c32s(Complex {
3443 re: *value,
3444 im: *value,
3445 })
3446 }
3447
3448 #[inline(always)]
3449 fn simd_add<S: Simd>(
3450 ctx: &Self::SimdCtx<S>,
3451 lhs: Self::SimdVec<S>,
3452 rhs: Self::SimdVec<S>,
3453 ) -> Self::SimdVec<S> {
3454 ctx.add_c32s(lhs, rhs)
3455 }
3456
3457 #[inline(always)]
3458 fn simd_sub<S: Simd>(
3459 ctx: &Self::SimdCtx<S>,
3460 lhs: Self::SimdVec<S>,
3461 rhs: Self::SimdVec<S>,
3462 ) -> Self::SimdVec<S> {
3463 ctx.sub_c32s(lhs, rhs)
3464 }
3465
3466 #[inline(always)]
3467 fn simd_neg<S: Simd>(
3468 ctx: &Self::SimdCtx<S>,
3469 value: Self::SimdVec<S>,
3470 ) -> Self::SimdVec<S> {
3471 ctx.neg_c32s(value)
3472 }
3473
3474 #[inline(always)]
3475 fn simd_conj<S: Simd>(
3476 ctx: &Self::SimdCtx<S>,
3477 value: Self::SimdVec<S>,
3478 ) -> Self::SimdVec<S> {
3479 ctx.conj_c32s(value)
3480 }
3481
3482 #[inline(always)]
3483 fn simd_abs1<S: Simd>(
3484 ctx: &Self::SimdCtx<S>,
3485 value: Self::SimdVec<S>,
3486 ) -> Self::SimdVec<S> {
3487 if const {
3488 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3489 } {
3490 bytemuck::cast(ctx.abs_f32s(bytemuck::cast(value)))
3491 } else if const {
3492 core::mem::size_of::<S::c32s>()
3493 == core::mem::size_of::<Complex<f32>>()
3494 } {
3495 let value: Complex<f32> = bytemuck::cast(value);
3496 let v = value.re.abs() + value.im.abs();
3497 bytemuck::cast(Complex { re: v, im: v })
3498 } else {
3499 panic!();
3500 }
3501 }
3502
3503 #[inline(always)]
3504 fn simd_abs_max<S: Simd>(
3505 ctx: &Self::SimdCtx<S>,
3506 value: Self::SimdVec<S>,
3507 ) -> Self::SimdVec<S> {
3508 if const {
3509 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3510 } {
3511 bytemuck::cast(ctx.abs_f32s(bytemuck::cast(value)))
3512 } else if const {
3513 core::mem::size_of::<S::c32s>()
3514 == core::mem::size_of::<Complex<f32>>()
3515 } {
3516 let value: Complex<f32> = bytemuck::cast(value);
3517 let re = value.re.abs();
3518 let im = value.im.abs();
3519 let v = if re > im { re } else { im };
3520 bytemuck::cast(Complex { re: v, im: v })
3521 } else {
3522 panic!();
3523 }
3524 }
3525
3526 #[inline(always)]
3527 fn simd_mul_real<S: Simd>(
3528 ctx: &Self::SimdCtx<S>,
3529 lhs: Self::SimdVec<S>,
3530 real_rhs: Self::SimdVec<S>,
3531 ) -> Self::SimdVec<S> {
3532 if const {
3533 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3534 } {
3535 bytemuck::cast(
3536 ctx.mul_f32s(bytemuck::cast(lhs), bytemuck::cast(real_rhs)),
3537 )
3538 } else if const {
3539 core::mem::size_of::<S::c32s>()
3540 == core::mem::size_of::<Complex<f32>>()
3541 } {
3542 let mut lhs: Complex<f32> = bytemuck::cast(lhs);
3543 let rhs: Complex<f32> = bytemuck::cast(real_rhs);
3544 lhs *= rhs.re;
3545 bytemuck::cast(lhs)
3546 } else {
3547 panic!();
3548 }
3549 }
3550
3551 #[inline(always)]
3552 fn simd_mul_pow2<S: Simd>(
3553 ctx: &Self::SimdCtx<S>,
3554 lhs: Self::SimdVec<S>,
3555 real_rhs: Self::SimdVec<S>,
3556 ) -> Self::SimdVec<S> {
3557 Self::simd_mul_real(ctx, lhs, real_rhs)
3558 }
3559
3560 #[inline(always)]
3561 fn simd_mul<S: Simd>(
3562 ctx: &Self::SimdCtx<S>,
3563 lhs: Self::SimdVec<S>,
3564 rhs: Self::SimdVec<S>,
3565 ) -> Self::SimdVec<S> {
3566 ctx.mul_e_c32s(lhs, rhs)
3567 }
3568
3569 #[inline(always)]
3570 fn simd_conj_mul<S: Simd>(
3571 ctx: &Self::SimdCtx<S>,
3572 lhs: Self::SimdVec<S>,
3573 rhs: Self::SimdVec<S>,
3574 ) -> Self::SimdVec<S> {
3575 ctx.conj_mul_e_c32s(lhs, rhs)
3576 }
3577
3578 #[inline(always)]
3579 fn simd_mul_add<S: Simd>(
3580 ctx: &Self::SimdCtx<S>,
3581 lhs: Self::SimdVec<S>,
3582 rhs: Self::SimdVec<S>,
3583 acc: Self::SimdVec<S>,
3584 ) -> Self::SimdVec<S> {
3585 ctx.mul_add_e_c32s(lhs, rhs, acc)
3586 }
3587
3588 #[inline(always)]
3589 fn simd_conj_mul_add<S: Simd>(
3590 ctx: &Self::SimdCtx<S>,
3591 lhs: Self::SimdVec<S>,
3592 rhs: Self::SimdVec<S>,
3593 acc: Self::SimdVec<S>,
3594 ) -> Self::SimdVec<S> {
3595 ctx.conj_mul_add_e_c32s(lhs, rhs, acc)
3596 }
3597
3598 #[inline(always)]
3599 fn simd_abs2<S: Simd>(
3600 ctx: &Self::SimdCtx<S>,
3601 value: Self::SimdVec<S>,
3602 ) -> Self::SimdVec<S> {
3603 if const {
3604 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3605 } {
3606 bytemuck::cast(
3607 ctx.mul_f32s(bytemuck::cast(value), bytemuck::cast(value)),
3608 )
3609 } else if const {
3610 core::mem::size_of::<S::c32s>()
3611 == core::mem::size_of::<Complex<f32>>()
3612 } {
3613 let value: Complex<f32> = bytemuck::cast(value);
3614 let v = value.re * value.re + value.im * value.im;
3615 bytemuck::cast(Complex { re: v, im: v })
3616 } else {
3617 panic!();
3618 }
3619 }
3620
3621 #[inline(always)]
3622 fn simd_abs2_add<S: Simd>(
3623 ctx: &Self::SimdCtx<S>,
3624 value: Self::SimdVec<S>,
3625 acc: Self::SimdVec<S>,
3626 ) -> Self::SimdVec<S> {
3627 if const {
3628 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3629 } {
3630 bytemuck::cast(ctx.mul_add_f32s(
3631 bytemuck::cast(value),
3632 bytemuck::cast(value),
3633 bytemuck::cast(acc),
3634 ))
3635 } else if const {
3636 core::mem::size_of::<S::c32s>()
3637 == core::mem::size_of::<Complex<f32>>()
3638 } {
3639 let value: Complex<f32> = bytemuck::cast(value);
3640 let acc: Complex<f32> = bytemuck::cast(acc);
3641 let v = value.re * value.re + value.im * value.im + acc.re;
3642 bytemuck::cast(Complex { re: v, im: v })
3643 } else {
3644 panic!();
3645 }
3646 }
3647
3648 #[inline(always)]
3649 fn simd_reduce_sum<S: Simd>(
3650 ctx: &Self::SimdCtx<S>,
3651 value: Self::SimdVec<S>,
3652 ) -> Self {
3653 ctx.reduce_sum_c32s(value).into()
3654 }
3655
3656 #[inline(always)]
3657 fn simd_reduce_max<S: Simd>(
3658 ctx: &Self::SimdCtx<S>,
3659 value: Self::SimdVec<S>,
3660 ) -> Self {
3661 ctx.reduce_max_c32s(value).into()
3662 }
3663
3664 #[inline(always)]
3665 fn simd_equal<S: Simd>(
3666 _: &Self::SimdCtx<S>,
3667 _: Self::SimdVec<S>,
3668 _: Self::SimdVec<S>,
3669 ) -> Self::SimdMask<S> {
3670 panic!()
3671 }
3672
3673 #[inline(always)]
3674 fn simd_less_than<S: Simd>(
3675 ctx: &Self::SimdCtx<S>,
3676 real_lhs: Self::SimdVec<S>,
3677 real_rhs: Self::SimdVec<S>,
3678 ) -> Self::SimdMask<S> {
3679 if const {
3680 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3681 } {
3682 ctx.less_than_f32s(
3683 bytemuck::cast(real_lhs),
3684 bytemuck::cast(real_rhs),
3685 )
3686 } else if const {
3687 core::mem::size_of::<S::c32s>()
3688 == core::mem::size_of::<Complex<f32>>()
3689 } {
3690 assert!(
3691 const {
3692 core::mem::size_of::<S::m32s>()
3693 == core::mem::size_of::<bool>()
3694 }
3695 );
3696 let lhs: Complex<f32> = bytemuck::cast(real_lhs);
3697 let rhs: Complex<f32> = bytemuck::cast(real_rhs);
3698 unsafe { core::mem::transmute_copy(&(lhs.re < rhs.re)) }
3699 } else {
3700 panic!();
3701 }
3702 }
3703
3704 #[inline(always)]
3705 fn simd_less_than_or_equal<S: Simd>(
3706 ctx: &Self::SimdCtx<S>,
3707 real_lhs: Self::SimdVec<S>,
3708 real_rhs: Self::SimdVec<S>,
3709 ) -> Self::SimdMask<S> {
3710 if const {
3711 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3712 } {
3713 ctx.less_than_or_equal_f32s(
3714 bytemuck::cast(real_lhs),
3715 bytemuck::cast(real_rhs),
3716 )
3717 } else if const {
3718 core::mem::size_of::<S::c32s>()
3719 == core::mem::size_of::<Complex<f32>>()
3720 } {
3721 assert!(
3722 const {
3723 core::mem::size_of::<S::m32s>()
3724 == core::mem::size_of::<bool>()
3725 }
3726 );
3727 let lhs: Complex<f32> = bytemuck::cast(real_lhs);
3728 let rhs: Complex<f32> = bytemuck::cast(real_rhs);
3729 unsafe { core::mem::transmute_copy(&(lhs.re <= rhs.re)) }
3730 } else {
3731 panic!();
3732 }
3733 }
3734
3735 #[inline(always)]
3736 fn simd_greater_than<S: Simd>(
3737 ctx: &Self::SimdCtx<S>,
3738 real_lhs: Self::SimdVec<S>,
3739 real_rhs: Self::SimdVec<S>,
3740 ) -> Self::SimdMask<S> {
3741 if const {
3742 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3743 } {
3744 ctx.greater_than_f32s(
3745 bytemuck::cast(real_lhs),
3746 bytemuck::cast(real_rhs),
3747 )
3748 } else if const {
3749 core::mem::size_of::<S::c32s>()
3750 == core::mem::size_of::<Complex<f32>>()
3751 } {
3752 assert!(
3753 const {
3754 core::mem::size_of::<S::m32s>()
3755 == core::mem::size_of::<bool>()
3756 }
3757 );
3758 let lhs: Complex<f32> = bytemuck::cast(real_lhs);
3759 let rhs: Complex<f32> = bytemuck::cast(real_rhs);
3760 unsafe { core::mem::transmute_copy(&(lhs.re > rhs.re)) }
3761 } else {
3762 panic!();
3763 }
3764 }
3765
3766 #[inline(always)]
3767 fn simd_greater_than_or_equal<S: Simd>(
3768 ctx: &Self::SimdCtx<S>,
3769 real_lhs: Self::SimdVec<S>,
3770 real_rhs: Self::SimdVec<S>,
3771 ) -> Self::SimdMask<S> {
3772 if const {
3773 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3774 } {
3775 ctx.greater_than_or_equal_f32s(
3776 bytemuck::cast(real_lhs),
3777 bytemuck::cast(real_rhs),
3778 )
3779 } else if const {
3780 core::mem::size_of::<S::c32s>()
3781 == core::mem::size_of::<Complex<f32>>()
3782 } {
3783 assert!(
3784 const {
3785 core::mem::size_of::<S::m32s>()
3786 == core::mem::size_of::<bool>()
3787 }
3788 );
3789 let lhs: Complex<f32> = bytemuck::cast(real_lhs);
3790 let rhs: Complex<f32> = bytemuck::cast(real_rhs);
3791 unsafe { core::mem::transmute_copy(&(lhs.re >= rhs.re)) }
3792 } else {
3793 panic!();
3794 }
3795 }
3796
3797 #[inline(always)]
3798 fn simd_select<S: Simd>(
3799 ctx: &Self::SimdCtx<S>,
3800 mask: Self::SimdMask<S>,
3801 lhs: Self::SimdVec<S>,
3802 rhs: Self::SimdVec<S>,
3803 ) -> Self::SimdVec<S> {
3804 if const {
3805 core::mem::size_of::<S::c32s>() == core::mem::size_of::<S::f32s>()
3806 } {
3807 bytemuck::cast(ctx.select_f32s(
3808 mask,
3809 bytemuck::cast(lhs),
3810 bytemuck::cast(rhs),
3811 ))
3812 } else if const {
3813 core::mem::size_of::<S::c32s>()
3814 == core::mem::size_of::<Complex<f32>>()
3815 } {
3816 assert!(
3817 const {
3818 core::mem::size_of::<S::m32s>()
3819 == core::mem::size_of::<bool>()
3820 }
3821 );
3822 let mask: bool = unsafe { core::mem::transmute_copy(&mask) };
3823 let lhs: Complex<f32> = bytemuck::cast(lhs);
3824 let rhs: Complex<f32> = bytemuck::cast(rhs);
3825 bytemuck::cast(if mask { lhs } else { rhs })
3826 } else {
3827 panic!();
3828 }
3829 }
3830
3831 #[inline(always)]
3832 fn simd_index_select<S: Simd>(
3833 ctx: &Self::SimdCtx<S>,
3834 mask: Self::SimdMask<S>,
3835 lhs: Self::SimdIndex<S>,
3836 rhs: Self::SimdIndex<S>,
3837 ) -> Self::SimdIndex<S> {
3838 f32::simd_index_select(ctx, mask, lhs, rhs)
3839 }
3840
3841 #[inline(always)]
3842 fn simd_index_splat<S: Simd>(
3843 ctx: &Self::SimdCtx<S>,
3844 value: Self::Index,
3845 ) -> Self::SimdIndex<S> {
3846 f32::simd_index_splat(ctx, value)
3847 }
3848
3849 #[inline(always)]
3850 fn simd_index_add<S: Simd>(
3851 ctx: &Self::SimdCtx<S>,
3852 lhs: Self::SimdIndex<S>,
3853 rhs: Self::SimdIndex<S>,
3854 ) -> Self::SimdIndex<S> {
3855 f32::simd_index_add(ctx, lhs, rhs)
3856 }
3857
3858 #[inline(always)]
3859 fn simd_index_less_than<S: Simd>(
3860 ctx: &Self::SimdCtx<S>,
3861 lhs: Self::SimdIndex<S>,
3862 rhs: Self::SimdIndex<S>,
3863 ) -> Self::SimdMask<S> {
3864 f32::simd_index_less_than(ctx, lhs, rhs)
3865 }
3866
3867 #[inline(always)]
3868 fn simd_and_mask<S: Simd>(
3869 ctx: &Self::SimdCtx<S>,
3870 lhs: Self::SimdMask<S>,
3871 rhs: Self::SimdMask<S>,
3872 ) -> Self::SimdMask<S> {
3873 f32::simd_and_mask(ctx, lhs, rhs)
3874 }
3875
3876 #[inline(always)]
3877 fn simd_or_mask<S: Simd>(
3878 ctx: &Self::SimdCtx<S>,
3879 lhs: Self::SimdMask<S>,
3880 rhs: Self::SimdMask<S>,
3881 ) -> Self::SimdMask<S> {
3882 f32::simd_or_mask(ctx, lhs, rhs)
3883 }
3884
3885 #[inline(always)]
3886 fn simd_not_mask<S: Simd>(
3887 ctx: &Self::SimdCtx<S>,
3888 mask: Self::SimdMask<S>,
3889 ) -> Self::SimdMask<S> {
3890 f32::simd_not_mask(ctx, mask)
3891 }
3892
3893 #[inline(always)]
3894 fn simd_first_true_mask<S: Simd>(
3895 ctx: &Self::SimdCtx<S>,
3896 value: Self::SimdMask<S>,
3897 ) -> usize {
3898 f32::simd_first_true_mask(ctx, value)
3899 }
3900
3901 #[inline(always)]
3902 fn simd_mem_mask_between<S: Simd>(
3903 ctx: &Self::SimdCtx<S>,
3904 start: Self::Index,
3905 end: Self::Index,
3906 ) -> Self::SimdMemMask<S> {
3907 ctx.mask_between_m32s((2 * start) as _, (2 * end) as _)
3908 }
3909
3910 #[inline(always)]
3911 fn simd_mask_between<S: Simd>(
3912 ctx: &Self::SimdCtx<S>,
3913 start: Self::Index,
3914 end: Self::Index,
3915 ) -> Self::SimdMask<S> {
3916 ctx.mask_between_m32s((2 * start) as _, (2 * end) as _)
3917 .mask()
3918 }
3919
3920 #[inline(always)]
3921 unsafe fn simd_mask_load_raw<S: Simd>(
3922 ctx: &Self::SimdCtx<S>,
3923 mask: Self::SimdMemMask<S>,
3924 ptr: *const Self::SimdVec<S>,
3925 ) -> Self::SimdVec<S> {
3926 ctx.mask_load_ptr_c32s(mask, ptr as _)
3927 }
3928
3929 #[inline(always)]
3930 unsafe fn simd_mask_store_raw<S: Simd>(
3931 ctx: &Self::SimdCtx<S>,
3932 mask: Self::SimdMemMask<S>,
3933 ptr: *mut Self::SimdVec<S>,
3934 values: Self::SimdVec<S>,
3935 ) {
3936 ctx.mask_store_ptr_c32s(mask, ptr as _, values);
3937 }
3938}
3939impl ComplexField for ComplexImpl<f64> {
3940 type Arch = pulp::Arch;
3941 type Index = u64;
3942 type Real = f64;
3943 type SimdCtx<S: Simd> = S;
3944 type SimdIndex<S: Simd> = S::u64s;
3945 type SimdMask<S: Simd> = S::m64s;
3946 type SimdMemMask<S: Simd> = pulp::MemMask<S::m64s>;
3947 type SimdVec<S: Simd> = S::c64s;
3948 type Unit = f64;
3949
3950 const IS_NATIVE_C64: bool = true;
3951 const IS_REAL: bool = false;
3952 const SIMD_ABS_SPLIT_REAL_IMAG: bool = true;
3953 const SIMD_CAPABILITIES: SimdCapabilities = SimdCapabilities::Simd;
3954
3955 #[inline]
3956 fn zero_impl() -> Self {
3957 Complex {
3958 re: f64::zero_impl(),
3959 im: f64::zero_impl(),
3960 }
3961 .into()
3962 }
3963
3964 #[inline]
3965 fn one_impl() -> Self {
3966 Complex {
3967 re: f64::one_impl(),
3968 im: f64::zero_impl(),
3969 }
3970 .into()
3971 }
3972
3973 #[inline]
3974 fn nan_impl() -> Self {
3975 Complex {
3976 re: f64::nan_impl(),
3977 im: f64::nan_impl(),
3978 }
3979 .into()
3980 }
3981
3982 #[inline]
3983 fn infinity_impl() -> Self {
3984 Complex {
3985 re: f64::infinity_impl(),
3986 im: f64::infinity_impl(),
3987 }
3988 .into()
3989 }
3990
3991 #[inline]
3992 fn from_real_impl(real: &Self::Real) -> Self {
3993 Complex {
3994 re: real.clone(),
3995 im: f64::zero_impl(),
3996 }
3997 .into()
3998 }
3999
4000 #[inline]
4001 fn from_f64_impl(real: f64) -> Self {
4002 Complex {
4003 re: f64::from_f64_impl(real),
4004 im: f64::zero_impl(),
4005 }
4006 .into()
4007 }
4008
4009 #[inline]
4010 fn real_part_impl(value: &Self) -> Self::Real {
4011 value.0.re.clone()
4012 }
4013
4014 #[inline]
4015 fn imag_part_impl(value: &Self) -> Self::Real {
4016 value.0.im.clone()
4017 }
4018
4019 #[inline]
4020 fn copy_impl(value: &Self) -> Self {
4021 value.clone()
4022 }
4023
4024 #[inline]
4025 fn conj_impl(value: &Self) -> Self {
4026 Complex {
4027 re: value.0.re.clone(),
4028 im: value.0.im.neg_by_ref(),
4029 }
4030 .into()
4031 }
4032
4033 #[inline]
4034 fn recip_impl(value: &Self) -> Self {
4035 let (re, im) = recip_impl(value.0.re.clone(), value.0.im.clone());
4036 Complex { re, im }.into()
4037 }
4038
4039 #[inline]
4040 fn sqrt_impl(value: &Self) -> Self {
4041 let (re, im) = sqrt_impl(value.0.re.clone(), value.0.im.clone());
4042 Complex { re, im }.into()
4043 }
4044
4045 #[inline]
4046 fn abs_impl(value: &Self) -> Self::Real {
4047 abs_impl(value.0.re.clone(), value.0.im.clone())
4048 }
4049
4050 #[inline]
4051 fn abs1_impl(value: &Self) -> Self::Real {
4052 use crate::ext::*;
4053 value.0.re.abs1() + value.0.im.abs1()
4054 }
4055
4056 #[inline]
4057 fn abs2_impl(value: &Self) -> Self::Real {
4058 use crate::ext::*;
4059 value.0.re.abs2() + value.0.im.abs2()
4060 }
4061
4062 #[inline]
4063 fn mul_real_impl(lhs: &Self, rhs: &Self::Real) -> Self {
4064 Complex {
4065 re: lhs.0.re * rhs,
4066 im: lhs.0.im * rhs,
4067 }
4068 .into()
4069 }
4070
4071 #[inline]
4072 fn mul_pow2_impl(lhs: &Self, rhs: &Self::Real) -> Self {
4073 use crate::ext::*;
4074 Complex {
4075 re: lhs.0.re.mul_pow2(rhs),
4076 im: lhs.0.im.mul_pow2(rhs),
4077 }
4078 .into()
4079 }
4080
4081 #[inline]
4082 fn is_finite_impl(value: &Self) -> bool {
4083 value.0.re.is_finite() && value.0.im.is_finite()
4084 }
4085
4086 #[inline(always)]
4087 fn simd_ctx<S: Simd>(simd: S) -> Self::SimdCtx<S> {
4088 f64::simd_ctx(simd)
4089 }
4090
4091 #[inline(always)]
4092 fn ctx_from_simd<S: Simd>(ctx: &Self::SimdCtx<S>) -> S {
4093 f64::ctx_from_simd(ctx)
4094 }
4095
4096 #[inline(always)]
4097 fn simd_splat<S: Simd>(
4098 ctx: &Self::SimdCtx<S>,
4099 value: &Self,
4100 ) -> Self::SimdVec<S> {
4101 ctx.splat_c64s(value.0)
4102 }
4103
4104 #[inline(always)]
4105 fn simd_splat_real<S: Simd>(
4106 ctx: &Self::SimdCtx<S>,
4107 value: &Self::Real,
4108 ) -> Self::SimdVec<S> {
4109 ctx.splat_c64s(Complex {
4110 re: *value,
4111 im: *value,
4112 })
4113 }
4114
4115 #[inline(always)]
4116 fn simd_add<S: Simd>(
4117 ctx: &Self::SimdCtx<S>,
4118 lhs: Self::SimdVec<S>,
4119 rhs: Self::SimdVec<S>,
4120 ) -> Self::SimdVec<S> {
4121 ctx.add_c64s(lhs, rhs)
4122 }
4123
4124 #[inline(always)]
4125 fn simd_sub<S: Simd>(
4126 ctx: &Self::SimdCtx<S>,
4127 lhs: Self::SimdVec<S>,
4128 rhs: Self::SimdVec<S>,
4129 ) -> Self::SimdVec<S> {
4130 ctx.sub_c64s(lhs, rhs)
4131 }
4132
4133 #[inline(always)]
4134 fn simd_neg<S: Simd>(
4135 ctx: &Self::SimdCtx<S>,
4136 value: Self::SimdVec<S>,
4137 ) -> Self::SimdVec<S> {
4138 ctx.neg_c64s(value)
4139 }
4140
4141 #[inline(always)]
4142 fn simd_conj<S: Simd>(
4143 ctx: &Self::SimdCtx<S>,
4144 value: Self::SimdVec<S>,
4145 ) -> Self::SimdVec<S> {
4146 ctx.conj_c64s(value)
4147 }
4148
4149 #[inline(always)]
4150 fn simd_abs1<S: Simd>(
4151 ctx: &Self::SimdCtx<S>,
4152 value: Self::SimdVec<S>,
4153 ) -> Self::SimdVec<S> {
4154 if const {
4155 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4156 } {
4157 bytemuck::cast(ctx.abs_f64s(bytemuck::cast(value)))
4158 } else if const {
4159 core::mem::size_of::<S::c64s>()
4160 == core::mem::size_of::<Complex<f64>>()
4161 } {
4162 let value: Complex<f64> = bytemuck::cast(value);
4163 let v = value.re.abs() + value.im.abs();
4164 bytemuck::cast(Complex { re: v, im: v })
4165 } else {
4166 panic!();
4167 }
4168 }
4169
4170 #[inline(always)]
4171 fn simd_abs_max<S: Simd>(
4172 ctx: &Self::SimdCtx<S>,
4173 value: Self::SimdVec<S>,
4174 ) -> Self::SimdVec<S> {
4175 if const {
4176 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4177 } {
4178 bytemuck::cast(ctx.abs_f64s(bytemuck::cast(value)))
4179 } else if const {
4180 core::mem::size_of::<S::c64s>()
4181 == core::mem::size_of::<Complex<f64>>()
4182 } {
4183 let value: Complex<f64> = bytemuck::cast(value);
4184 let re = value.re.abs();
4185 let im = value.im.abs();
4186 let v = if re > im { re } else { im };
4187 bytemuck::cast(Complex { re: v, im: v })
4188 } else {
4189 panic!();
4190 }
4191 }
4192
4193 #[inline(always)]
4194 fn simd_mul_real<S: Simd>(
4195 ctx: &Self::SimdCtx<S>,
4196 lhs: Self::SimdVec<S>,
4197 real_rhs: Self::SimdVec<S>,
4198 ) -> Self::SimdVec<S> {
4199 if const {
4200 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4201 } {
4202 bytemuck::cast(
4203 ctx.mul_f64s(bytemuck::cast(lhs), bytemuck::cast(real_rhs)),
4204 )
4205 } else if const {
4206 core::mem::size_of::<S::c64s>()
4207 == core::mem::size_of::<Complex<f64>>()
4208 } {
4209 let mut lhs: Complex<f64> = bytemuck::cast(lhs);
4210 let rhs: Complex<f64> = bytemuck::cast(real_rhs);
4211 lhs *= rhs.re;
4212 bytemuck::cast(lhs)
4213 } else {
4214 panic!();
4215 }
4216 }
4217
4218 #[inline(always)]
4219 fn simd_mul_pow2<S: Simd>(
4220 ctx: &Self::SimdCtx<S>,
4221 lhs: Self::SimdVec<S>,
4222 real_rhs: Self::SimdVec<S>,
4223 ) -> Self::SimdVec<S> {
4224 Self::simd_mul_real(ctx, lhs, real_rhs)
4225 }
4226
4227 #[inline(always)]
4228 fn simd_mul<S: Simd>(
4229 ctx: &Self::SimdCtx<S>,
4230 lhs: Self::SimdVec<S>,
4231 rhs: Self::SimdVec<S>,
4232 ) -> Self::SimdVec<S> {
4233 ctx.mul_e_c64s(lhs, rhs)
4234 }
4235
4236 #[inline(always)]
4237 fn simd_conj_mul<S: Simd>(
4238 ctx: &Self::SimdCtx<S>,
4239 lhs: Self::SimdVec<S>,
4240 rhs: Self::SimdVec<S>,
4241 ) -> Self::SimdVec<S> {
4242 ctx.conj_mul_e_c64s(lhs, rhs)
4243 }
4244
4245 #[inline(always)]
4246 fn simd_mul_add<S: Simd>(
4247 ctx: &Self::SimdCtx<S>,
4248 lhs: Self::SimdVec<S>,
4249 rhs: Self::SimdVec<S>,
4250 acc: Self::SimdVec<S>,
4251 ) -> Self::SimdVec<S> {
4252 ctx.mul_add_e_c64s(lhs, rhs, acc)
4253 }
4254
4255 #[inline(always)]
4256 fn simd_conj_mul_add<S: Simd>(
4257 ctx: &Self::SimdCtx<S>,
4258 lhs: Self::SimdVec<S>,
4259 rhs: Self::SimdVec<S>,
4260 acc: Self::SimdVec<S>,
4261 ) -> Self::SimdVec<S> {
4262 ctx.conj_mul_add_e_c64s(lhs, rhs, acc)
4263 }
4264
4265 #[inline(always)]
4266 fn simd_abs2<S: Simd>(
4267 ctx: &Self::SimdCtx<S>,
4268 value: Self::SimdVec<S>,
4269 ) -> Self::SimdVec<S> {
4270 if const {
4271 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4272 } {
4273 bytemuck::cast(
4274 ctx.mul_f64s(bytemuck::cast(value), bytemuck::cast(value)),
4275 )
4276 } else if const {
4277 core::mem::size_of::<S::c64s>()
4278 == core::mem::size_of::<Complex<f64>>()
4279 } {
4280 let value: Complex<f64> = bytemuck::cast(value);
4281 let v = value.re * value.re + value.im * value.im;
4282 bytemuck::cast(Complex { re: v, im: v })
4283 } else {
4284 panic!();
4285 }
4286 }
4287
4288 #[inline(always)]
4289 fn simd_abs2_add<S: Simd>(
4290 ctx: &Self::SimdCtx<S>,
4291 value: Self::SimdVec<S>,
4292 acc: Self::SimdVec<S>,
4293 ) -> Self::SimdVec<S> {
4294 if const {
4295 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4296 } {
4297 bytemuck::cast(ctx.mul_add_f64s(
4298 bytemuck::cast(value),
4299 bytemuck::cast(value),
4300 bytemuck::cast(acc),
4301 ))
4302 } else if const {
4303 core::mem::size_of::<S::c64s>()
4304 == core::mem::size_of::<Complex<f64>>()
4305 } {
4306 let value: Complex<f64> = bytemuck::cast(value);
4307 let acc: Complex<f64> = bytemuck::cast(acc);
4308 let v = value.re * value.re + value.im * value.im + acc.re;
4309 bytemuck::cast(Complex { re: v, im: v })
4310 } else {
4311 panic!();
4312 }
4313 }
4314
4315 #[inline(always)]
4316 fn simd_reduce_sum<S: Simd>(
4317 ctx: &Self::SimdCtx<S>,
4318 value: Self::SimdVec<S>,
4319 ) -> Self {
4320 ctx.reduce_sum_c64s(value).into()
4321 }
4322
4323 #[inline(always)]
4324 fn simd_reduce_max<S: Simd>(
4325 ctx: &Self::SimdCtx<S>,
4326 value: Self::SimdVec<S>,
4327 ) -> Self {
4328 ctx.reduce_max_c64s(value).into()
4329 }
4330
4331 #[inline(always)]
4332 fn simd_equal<S: Simd>(
4333 _: &Self::SimdCtx<S>,
4334 _: Self::SimdVec<S>,
4335 _: Self::SimdVec<S>,
4336 ) -> Self::SimdMask<S> {
4337 panic!()
4338 }
4339
4340 #[inline(always)]
4341 fn simd_less_than<S: Simd>(
4342 ctx: &Self::SimdCtx<S>,
4343 real_lhs: Self::SimdVec<S>,
4344 real_rhs: Self::SimdVec<S>,
4345 ) -> Self::SimdMask<S> {
4346 if const {
4347 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4348 } {
4349 ctx.less_than_f64s(
4350 bytemuck::cast(real_lhs),
4351 bytemuck::cast(real_rhs),
4352 )
4353 } else if const {
4354 core::mem::size_of::<S::c64s>()
4355 == core::mem::size_of::<Complex<f64>>()
4356 } {
4357 assert!(
4358 const {
4359 core::mem::size_of::<S::m64s>()
4360 == core::mem::size_of::<bool>()
4361 }
4362 );
4363 let lhs: Complex<f64> = bytemuck::cast(real_lhs);
4364 let rhs: Complex<f64> = bytemuck::cast(real_rhs);
4365 unsafe { core::mem::transmute_copy(&(lhs.re < rhs.re)) }
4366 } else {
4367 panic!();
4368 }
4369 }
4370
4371 #[inline(always)]
4372 fn simd_less_than_or_equal<S: Simd>(
4373 ctx: &Self::SimdCtx<S>,
4374 real_lhs: Self::SimdVec<S>,
4375 real_rhs: Self::SimdVec<S>,
4376 ) -> Self::SimdMask<S> {
4377 if const {
4378 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4379 } {
4380 ctx.less_than_or_equal_f64s(
4381 bytemuck::cast(real_lhs),
4382 bytemuck::cast(real_rhs),
4383 )
4384 } else if const {
4385 core::mem::size_of::<S::c64s>()
4386 == core::mem::size_of::<Complex<f64>>()
4387 } {
4388 assert!(
4389 const {
4390 core::mem::size_of::<S::m64s>()
4391 == core::mem::size_of::<bool>()
4392 }
4393 );
4394 let lhs: Complex<f64> = bytemuck::cast(real_lhs);
4395 let rhs: Complex<f64> = bytemuck::cast(real_rhs);
4396 unsafe { core::mem::transmute_copy(&(lhs.re <= rhs.re)) }
4397 } else {
4398 panic!();
4399 }
4400 }
4401
4402 #[inline(always)]
4403 fn simd_greater_than<S: Simd>(
4404 ctx: &Self::SimdCtx<S>,
4405 real_lhs: Self::SimdVec<S>,
4406 real_rhs: Self::SimdVec<S>,
4407 ) -> Self::SimdMask<S> {
4408 if const {
4409 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4410 } {
4411 ctx.greater_than_f64s(
4412 bytemuck::cast(real_lhs),
4413 bytemuck::cast(real_rhs),
4414 )
4415 } else if const {
4416 core::mem::size_of::<S::c64s>()
4417 == core::mem::size_of::<Complex<f64>>()
4418 } {
4419 assert!(
4420 const {
4421 core::mem::size_of::<S::m64s>()
4422 == core::mem::size_of::<bool>()
4423 }
4424 );
4425 let lhs: Complex<f64> = bytemuck::cast(real_lhs);
4426 let rhs: Complex<f64> = bytemuck::cast(real_rhs);
4427 unsafe { core::mem::transmute_copy(&(lhs.re > rhs.re)) }
4428 } else {
4429 panic!();
4430 }
4431 }
4432
4433 #[inline(always)]
4434 fn simd_greater_than_or_equal<S: Simd>(
4435 ctx: &Self::SimdCtx<S>,
4436 real_lhs: Self::SimdVec<S>,
4437 real_rhs: Self::SimdVec<S>,
4438 ) -> Self::SimdMask<S> {
4439 if const {
4440 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4441 } {
4442 ctx.greater_than_or_equal_f64s(
4443 bytemuck::cast(real_lhs),
4444 bytemuck::cast(real_rhs),
4445 )
4446 } else if const {
4447 core::mem::size_of::<S::c64s>()
4448 == core::mem::size_of::<Complex<f64>>()
4449 } {
4450 assert!(
4451 const {
4452 core::mem::size_of::<S::m64s>()
4453 == core::mem::size_of::<bool>()
4454 }
4455 );
4456 let lhs: Complex<f64> = bytemuck::cast(real_lhs);
4457 let rhs: Complex<f64> = bytemuck::cast(real_rhs);
4458 unsafe { core::mem::transmute_copy(&(lhs.re >= rhs.re)) }
4459 } else {
4460 panic!();
4461 }
4462 }
4463
4464 #[inline(always)]
4465 fn simd_select<S: Simd>(
4466 ctx: &Self::SimdCtx<S>,
4467 mask: Self::SimdMask<S>,
4468 lhs: Self::SimdVec<S>,
4469 rhs: Self::SimdVec<S>,
4470 ) -> Self::SimdVec<S> {
4471 if const {
4472 core::mem::size_of::<S::c64s>() == core::mem::size_of::<S::f64s>()
4473 } {
4474 bytemuck::cast(ctx.select_f64s(
4475 mask,
4476 bytemuck::cast(lhs),
4477 bytemuck::cast(rhs),
4478 ))
4479 } else if const {
4480 core::mem::size_of::<S::c64s>()
4481 == core::mem::size_of::<Complex<f64>>()
4482 } {
4483 assert!(
4484 const {
4485 core::mem::size_of::<S::m64s>()
4486 == core::mem::size_of::<bool>()
4487 }
4488 );
4489 let mask: bool = unsafe { core::mem::transmute_copy(&mask) };
4490 let lhs: Complex<f64> = bytemuck::cast(lhs);
4491 let rhs: Complex<f64> = bytemuck::cast(rhs);
4492 bytemuck::cast(if mask { lhs } else { rhs })
4493 } else {
4494 panic!();
4495 }
4496 }
4497
4498 #[inline(always)]
4499 fn simd_index_select<S: Simd>(
4500 ctx: &Self::SimdCtx<S>,
4501 mask: Self::SimdMask<S>,
4502 lhs: Self::SimdIndex<S>,
4503 rhs: Self::SimdIndex<S>,
4504 ) -> Self::SimdIndex<S> {
4505 f64::simd_index_select(ctx, mask, lhs, rhs)
4506 }
4507
4508 #[inline(always)]
4509 fn simd_index_splat<S: Simd>(
4510 ctx: &Self::SimdCtx<S>,
4511 value: Self::Index,
4512 ) -> Self::SimdIndex<S> {
4513 f64::simd_index_splat(ctx, value)
4514 }
4515
4516 #[inline(always)]
4517 fn simd_index_add<S: Simd>(
4518 ctx: &Self::SimdCtx<S>,
4519 lhs: Self::SimdIndex<S>,
4520 rhs: Self::SimdIndex<S>,
4521 ) -> Self::SimdIndex<S> {
4522 f64::simd_index_add(ctx, lhs, rhs)
4523 }
4524
4525 #[inline(always)]
4526 fn simd_index_less_than<S: Simd>(
4527 ctx: &Self::SimdCtx<S>,
4528 lhs: Self::SimdIndex<S>,
4529 rhs: Self::SimdIndex<S>,
4530 ) -> Self::SimdMask<S> {
4531 f64::simd_index_less_than(ctx, lhs, rhs)
4532 }
4533
4534 #[inline(always)]
4535 fn simd_and_mask<S: Simd>(
4536 ctx: &Self::SimdCtx<S>,
4537 lhs: Self::SimdMask<S>,
4538 rhs: Self::SimdMask<S>,
4539 ) -> Self::SimdMask<S> {
4540 f64::simd_and_mask(ctx, lhs, rhs)
4541 }
4542
4543 #[inline(always)]
4544 fn simd_or_mask<S: Simd>(
4545 ctx: &Self::SimdCtx<S>,
4546 lhs: Self::SimdMask<S>,
4547 rhs: Self::SimdMask<S>,
4548 ) -> Self::SimdMask<S> {
4549 f64::simd_or_mask(ctx, lhs, rhs)
4550 }
4551
4552 #[inline(always)]
4553 fn simd_not_mask<S: Simd>(
4554 ctx: &Self::SimdCtx<S>,
4555 mask: Self::SimdMask<S>,
4556 ) -> Self::SimdMask<S> {
4557 f64::simd_not_mask(ctx, mask)
4558 }
4559
4560 #[inline(always)]
4561 fn simd_first_true_mask<S: Simd>(
4562 ctx: &Self::SimdCtx<S>,
4563 value: Self::SimdMask<S>,
4564 ) -> usize {
4565 f64::simd_first_true_mask(ctx, value)
4566 }
4567
4568 #[inline(always)]
4569 fn simd_mem_mask_between<S: Simd>(
4570 ctx: &Self::SimdCtx<S>,
4571 start: Self::Index,
4572 end: Self::Index,
4573 ) -> Self::SimdMemMask<S> {
4574 ctx.mask_between_m64s((2 * start) as _, (2 * end) as _)
4575 }
4576
4577 #[inline(always)]
4578 fn simd_mask_between<S: Simd>(
4579 ctx: &Self::SimdCtx<S>,
4580 start: Self::Index,
4581 end: Self::Index,
4582 ) -> Self::SimdMask<S> {
4583 ctx.mask_between_m64s((2 * start) as _, (2 * end) as _)
4584 .mask()
4585 }
4586
4587 #[inline(always)]
4588 unsafe fn simd_mask_load_raw<S: Simd>(
4589 ctx: &Self::SimdCtx<S>,
4590 mask: Self::SimdMemMask<S>,
4591 ptr: *const Self::SimdVec<S>,
4592 ) -> Self::SimdVec<S> {
4593 ctx.mask_load_ptr_c64s(mask, ptr as _)
4594 }
4595
4596 #[inline(always)]
4597 unsafe fn simd_mask_store_raw<S: Simd>(
4598 ctx: &Self::SimdCtx<S>,
4599 mask: Self::SimdMemMask<S>,
4600 ptr: *mut Self::SimdVec<S>,
4601 values: Self::SimdVec<S>,
4602 ) {
4603 ctx.mask_store_ptr_c64s(mask, ptr as _, values);
4604 }
4605}
4606#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
4607pub struct Symbolic;
4608impl_op!({
4609 impl Add for Symbolic {
4610 fn add(self, rhs: Self) -> Self::Output {
4611 _ = rhs;
4612 Symbolic
4613 }
4614 }
4615 impl Sub for Symbolic {
4616 fn sub(self, rhs: Self) -> Self::Output {
4617 _ = rhs;
4618 Symbolic
4619 }
4620 }
4621 impl Mul for Symbolic {
4622 fn mul(self, rhs: Self) -> Self::Output {
4623 _ = rhs;
4624 Symbolic
4625 }
4626 }
4627 impl Div for Symbolic {
4628 fn div(self, rhs: Self) -> Self::Output {
4629 _ = rhs;
4630 Symbolic
4631 }
4632 }
4633 impl Rem for Symbolic {
4634 fn rem(self, rhs: Self) -> Self::Output {
4635 _ = rhs;
4636 Symbolic
4637 }
4638 }
4639});
4640impl_assign_op!({
4641 impl AddAssign for Symbolic {
4642 fn add_assign(&mut self, rhs: Self) {
4643 _ = rhs;
4644 }
4645 }
4646 impl SubAssign for Symbolic {
4647 fn sub_assign(&mut self, rhs: Self) {
4648 _ = rhs;
4649 }
4650 }
4651 impl MulAssign for Symbolic {
4652 fn mul_assign(&mut self, rhs: Self) {
4653 _ = rhs;
4654 }
4655 }
4656 impl DivAssign for Symbolic {
4657 fn div_assign(&mut self, rhs: Self) {
4658 _ = rhs;
4659 }
4660 }
4661 impl RemAssign for Symbolic {
4662 fn rem_assign(&mut self, rhs: Self) {
4663 _ = rhs;
4664 }
4665 }
4666});
4667impl core::ops::Neg for Symbolic {
4668 type Output = Self;
4669
4670 fn neg(self) -> Self {
4671 Self
4672 }
4673}
4674impl core::ops::Neg for &Symbolic {
4675 type Output = Symbolic;
4676
4677 fn neg(self) -> Symbolic {
4678 Symbolic
4679 }
4680}
4681impl num_traits::Zero for Symbolic {
4682 fn zero() -> Self {
4683 Self
4684 }
4685
4686 fn is_zero(&self) -> bool {
4687 true
4688 }
4689}
4690impl num_traits::One for Symbolic {
4691 fn one() -> Self {
4692 Self
4693 }
4694
4695 fn is_one(&self) -> bool {
4696 true
4697 }
4698}
4699impl num_traits::Num for Symbolic {
4700 type FromStrRadixErr = core::convert::Infallible;
4701
4702 fn from_str_radix(_: &str, _: u32) -> Result<Self, Self::FromStrRadixErr> {
4703 Ok(Self)
4704 }
4705}
4706impl Symbolic {
4707 #[inline]
4708 pub fn materialize(len: usize) -> &'static mut [Self] {
4709 unsafe {
4710 core::slice::from_raw_parts_mut(
4711 core::ptr::NonNull::dangling().as_ptr(),
4712 len,
4713 )
4714 }
4715 }
4716}
4717impl RealField for Symbolic {
4718 fn epsilon_impl() -> Self {
4719 Self
4720 }
4721
4722 fn nbits_impl() -> usize {
4723 0
4724 }
4725
4726 fn min_positive_impl() -> Self {
4727 Self
4728 }
4729
4730 fn max_positive_impl() -> Self {
4731 Self
4732 }
4733
4734 fn sqrt_min_positive_impl() -> Self {
4735 Self
4736 }
4737
4738 fn sqrt_max_positive_impl() -> Self {
4739 Self
4740 }
4741}
4742impl ComplexField for Symbolic {
4743 type Arch = pulp::Scalar;
4744 type Index = usize;
4745 type Real = Self;
4746 type SimdCtx<S: pulp::Simd> = S;
4747 type SimdIndex<S: pulp::Simd> = ();
4748 type SimdMask<S: pulp::Simd> = ();
4749 type SimdMemMask<S: pulp::Simd> = ();
4750 type SimdVec<S: pulp::Simd> = ();
4751 type Unit = Self;
4752
4753 const IS_REAL: bool = true;
4754 const SIMD_CAPABILITIES: SimdCapabilities = SimdCapabilities::Copy;
4755
4756 fn zero_impl() -> Self {
4757 Self
4758 }
4759
4760 fn one_impl() -> Self {
4761 Self
4762 }
4763
4764 fn nan_impl() -> Self {
4765 Self
4766 }
4767
4768 fn infinity_impl() -> Self {
4769 Self
4770 }
4771
4772 fn from_real_impl(_: &Self::Real) -> Self {
4773 Self
4774 }
4775
4776 fn from_f64_impl(_: f64) -> Self {
4777 Self
4778 }
4779
4780 fn real_part_impl(_: &Self) -> Self::Real {
4781 Self
4782 }
4783
4784 fn imag_part_impl(_: &Self) -> Self::Real {
4785 Self
4786 }
4787
4788 fn copy_impl(_: &Self) -> Self {
4789 Self
4790 }
4791
4792 fn conj_impl(_: &Self) -> Self {
4793 Self
4794 }
4795
4796 fn recip_impl(_: &Self) -> Self {
4797 Self
4798 }
4799
4800 fn sqrt_impl(_: &Self) -> Self {
4801 Self
4802 }
4803
4804 fn abs_impl(_: &Self) -> Self::Real {
4805 Self
4806 }
4807
4808 fn abs1_impl(_: &Self) -> Self::Real {
4809 Self
4810 }
4811
4812 fn abs2_impl(_: &Self) -> Self::Real {
4813 Self
4814 }
4815
4816 fn mul_real_impl(_: &Self, _: &Self::Real) -> Self {
4817 Self
4818 }
4819
4820 fn mul_pow2_impl(_: &Self, _: &Self::Real) -> Self {
4821 Self
4822 }
4823
4824 fn is_finite_impl(_: &Self) -> bool {
4825 true
4826 }
4827
4828 fn simd_ctx<S: pulp::Simd>(simd: S) -> Self::SimdCtx<S> {
4829 simd
4830 }
4831
4832 fn ctx_from_simd<S: pulp::Simd>(simd: &Self::SimdCtx<S>) -> S {
4833 *simd
4834 }
4835
4836 fn simd_mem_mask_between<S: pulp::Simd>(
4837 _: &Self::SimdCtx<S>,
4838 _: Self::Index,
4839 _: Self::Index,
4840 ) -> Self::SimdMemMask<S> {
4841 ()
4842 }
4843
4844 unsafe fn simd_mask_load_raw<S: pulp::Simd>(
4845 _: &Self::SimdCtx<S>,
4846 _: Self::SimdMemMask<S>,
4847 _: *const Self::SimdVec<S>,
4848 ) -> Self::SimdVec<S> {
4849 ()
4850 }
4851
4852 unsafe fn simd_mask_store_raw<S: pulp::Simd>(
4853 _: &Self::SimdCtx<S>,
4854 _: Self::SimdMemMask<S>,
4855 _: *mut Self::SimdVec<S>,
4856 _: Self::SimdVec<S>,
4857 ) {
4858 ()
4859 }
4860
4861 fn simd_splat<S: pulp::Simd>(
4862 _: &Self::SimdCtx<S>,
4863 _: &Self,
4864 ) -> Self::SimdVec<S> {
4865 ()
4866 }
4867
4868 fn simd_splat_real<S: pulp::Simd>(
4869 _: &Self::SimdCtx<S>,
4870 _: &Self::Real,
4871 ) -> Self::SimdVec<S> {
4872 ()
4873 }
4874
4875 fn simd_add<S: pulp::Simd>(
4876 _: &Self::SimdCtx<S>,
4877 _: Self::SimdVec<S>,
4878 _: Self::SimdVec<S>,
4879 ) -> Self::SimdVec<S> {
4880 ()
4881 }
4882
4883 fn simd_sub<S: pulp::Simd>(
4884 _: &Self::SimdCtx<S>,
4885 _: Self::SimdVec<S>,
4886 _: Self::SimdVec<S>,
4887 ) -> Self::SimdVec<S> {
4888 ()
4889 }
4890
4891 fn simd_neg<S: pulp::Simd>(
4892 _: &Self::SimdCtx<S>,
4893 _: Self::SimdVec<S>,
4894 ) -> Self::SimdVec<S> {
4895 ()
4896 }
4897
4898 fn simd_conj<S: pulp::Simd>(
4899 _: &Self::SimdCtx<S>,
4900 _: Self::SimdVec<S>,
4901 ) -> Self::SimdVec<S> {
4902 ()
4903 }
4904
4905 fn simd_abs1<S: pulp::Simd>(
4906 _: &Self::SimdCtx<S>,
4907 _: Self::SimdVec<S>,
4908 ) -> Self::SimdVec<S> {
4909 ()
4910 }
4911
4912 fn simd_abs_max<S: pulp::Simd>(
4913 _: &Self::SimdCtx<S>,
4914 _: Self::SimdVec<S>,
4915 ) -> Self::SimdVec<S> {
4916 ()
4917 }
4918
4919 fn simd_mul_real<S: pulp::Simd>(
4920 _: &Self::SimdCtx<S>,
4921 _: Self::SimdVec<S>,
4922 _: Self::SimdVec<S>,
4923 ) -> Self::SimdVec<S> {
4924 ()
4925 }
4926
4927 fn simd_mul_pow2<S: pulp::Simd>(
4928 _: &Self::SimdCtx<S>,
4929 _: Self::SimdVec<S>,
4930 _: Self::SimdVec<S>,
4931 ) -> Self::SimdVec<S> {
4932 ()
4933 }
4934
4935 fn simd_mul<S: pulp::Simd>(
4936 _: &Self::SimdCtx<S>,
4937 _: Self::SimdVec<S>,
4938 _: Self::SimdVec<S>,
4939 ) -> Self::SimdVec<S> {
4940 ()
4941 }
4942
4943 fn simd_conj_mul<S: pulp::Simd>(
4944 _: &Self::SimdCtx<S>,
4945 _: Self::SimdVec<S>,
4946 _: Self::SimdVec<S>,
4947 ) -> Self::SimdVec<S> {
4948 ()
4949 }
4950
4951 fn simd_mul_add<S: pulp::Simd>(
4952 _: &Self::SimdCtx<S>,
4953 _: Self::SimdVec<S>,
4954 _: Self::SimdVec<S>,
4955 _: Self::SimdVec<S>,
4956 ) -> Self::SimdVec<S> {
4957 ()
4958 }
4959
4960 fn simd_conj_mul_add<S: pulp::Simd>(
4961 _: &Self::SimdCtx<S>,
4962 _: Self::SimdVec<S>,
4963 _: Self::SimdVec<S>,
4964 _: Self::SimdVec<S>,
4965 ) -> Self::SimdVec<S> {
4966 ()
4967 }
4968
4969 fn simd_abs2<S: pulp::Simd>(
4970 _: &Self::SimdCtx<S>,
4971 _: Self::SimdVec<S>,
4972 ) -> Self::SimdVec<S> {
4973 ()
4974 }
4975
4976 fn simd_abs2_add<S: pulp::Simd>(
4977 _: &Self::SimdCtx<S>,
4978 _: Self::SimdVec<S>,
4979 _: Self::SimdVec<S>,
4980 ) -> Self::SimdVec<S> {
4981 ()
4982 }
4983
4984 fn simd_reduce_sum<S: pulp::Simd>(
4985 _: &Self::SimdCtx<S>,
4986 _: Self::SimdVec<S>,
4987 ) -> Self {
4988 Self
4989 }
4990
4991 fn simd_reduce_max<S: pulp::Simd>(
4992 _: &Self::SimdCtx<S>,
4993 _: Self::SimdVec<S>,
4994 ) -> Self {
4995 Self
4996 }
4997
4998 fn simd_equal<S: pulp::Simd>(
4999 _: &Self::SimdCtx<S>,
5000 _: Self::SimdVec<S>,
5001 _: Self::SimdVec<S>,
5002 ) -> Self::SimdMask<S> {
5003 ()
5004 }
5005
5006 fn simd_less_than<S: pulp::Simd>(
5007 _: &Self::SimdCtx<S>,
5008 _: Self::SimdVec<S>,
5009 _: Self::SimdVec<S>,
5010 ) -> Self::SimdMask<S> {
5011 ()
5012 }
5013
5014 fn simd_less_than_or_equal<S: pulp::Simd>(
5015 _: &Self::SimdCtx<S>,
5016 _: Self::SimdVec<S>,
5017 _: Self::SimdVec<S>,
5018 ) -> Self::SimdMask<S> {
5019 ()
5020 }
5021
5022 fn simd_greater_than<S: pulp::Simd>(
5023 _: &Self::SimdCtx<S>,
5024 _: Self::SimdVec<S>,
5025 _: Self::SimdVec<S>,
5026 ) -> Self::SimdMask<S> {
5027 ()
5028 }
5029
5030 fn simd_greater_than_or_equal<S: pulp::Simd>(
5031 _: &Self::SimdCtx<S>,
5032 _: Self::SimdVec<S>,
5033 _: Self::SimdVec<S>,
5034 ) -> Self::SimdMask<S> {
5035 ()
5036 }
5037
5038 fn simd_select<S: pulp::Simd>(
5039 _: &Self::SimdCtx<S>,
5040 _: Self::SimdMask<S>,
5041 _: Self::SimdVec<S>,
5042 _: Self::SimdVec<S>,
5043 ) -> Self::SimdVec<S> {
5044 ()
5045 }
5046
5047 fn simd_index_select<S: pulp::Simd>(
5048 _: &Self::SimdCtx<S>,
5049 _: Self::SimdMask<S>,
5050 _: Self::SimdIndex<S>,
5051 _: Self::SimdIndex<S>,
5052 ) -> Self::SimdIndex<S> {
5053 ()
5054 }
5055
5056 fn simd_index_splat<S: pulp::Simd>(
5057 _: &Self::SimdCtx<S>,
5058 _: Self::Index,
5059 ) -> Self::SimdIndex<S> {
5060 ()
5061 }
5062
5063 fn simd_index_add<S: pulp::Simd>(
5064 _: &Self::SimdCtx<S>,
5065 _: Self::SimdIndex<S>,
5066 _: Self::SimdIndex<S>,
5067 ) -> Self::SimdIndex<S> {
5068 ()
5069 }
5070
5071 fn simd_and_mask<S: pulp::Simd>(
5072 _: &Self::SimdCtx<S>,
5073 _: Self::SimdMask<S>,
5074 _: Self::SimdMask<S>,
5075 ) -> Self::SimdMask<S> {
5076 ()
5077 }
5078
5079 fn simd_or_mask<S: pulp::Simd>(
5080 _: &Self::SimdCtx<S>,
5081 _: Self::SimdMask<S>,
5082 _: Self::SimdMask<S>,
5083 ) -> Self::SimdMask<S> {
5084 ()
5085 }
5086
5087 fn simd_not_mask<S: Simd>(
5088 _: &Self::SimdCtx<S>,
5089 _: Self::SimdMask<S>,
5090 ) -> Self::SimdMask<S> {
5091 ()
5092 }
5093
5094 fn simd_first_true_mask<S: pulp::Simd>(
5095 _: &Self::SimdCtx<S>,
5096 _: Self::SimdMask<S>,
5097 ) -> usize {
5098 0
5099 }
5100
5101 fn simd_mask_between<S: Simd>(
5102 _: &Self::SimdCtx<S>,
5103 _: Self::Index,
5104 _: Self::Index,
5105 ) -> Self::SimdMask<S> {
5106 ()
5107 }
5108
5109 fn simd_index_less_than<S: Simd>(
5110 _: &Self::SimdCtx<S>,
5111 _: Self::SimdIndex<S>,
5112 _: Self::SimdIndex<S>,
5113 ) -> Self::SimdMask<S> {
5114 ()
5115 }
5116}
5117pub type c64 = Complex<f64>;
5118pub type c32 = Complex<f32>;
5119pub type fx128 = qd::Quad;
5120pub type cx128 = Complex<fx128>;
5121pub extern crate num_traits;
5122pub extern crate pulp;
5123impl ComplexField for fx128 {
5124 type Arch = pulp::Arch;
5125 type Index = u64;
5126 type Real = Self;
5127 type SimdCtx<S: Simd> = S;
5128 type SimdIndex<S: Simd> = S::u64s;
5129 type SimdMask<S: Simd> = S::m64s;
5130 type SimdMemMask<S: Simd> = Quad<pulp::MemMask<S::m64s>>;
5131 type SimdVec<S: Simd> = Quad<S::f64s>;
5132 type Unit = f64;
5133
5134 const IS_REAL: bool = true;
5135 const SIMD_CAPABILITIES: SimdCapabilities = SimdCapabilities::Simd;
5136
5137 #[inline(always)]
5138 fn zero_impl() -> Self {
5139 Self::ZERO
5140 }
5141
5142 #[inline(always)]
5143 fn one_impl() -> Self {
5144 Quad(1.0, 0.0)
5145 }
5146
5147 #[inline(always)]
5148 fn nan_impl() -> Self {
5149 Self::NAN
5150 }
5151
5152 #[inline(always)]
5153 fn infinity_impl() -> Self {
5154 Self::INFINITY
5155 }
5156
5157 #[inline(always)]
5158 fn from_real_impl(real: &Self::Real) -> Self {
5159 *real
5160 }
5161
5162 #[inline(always)]
5163 fn from_f64_impl(real: f64) -> Self {
5164 real.into()
5165 }
5166
5167 #[inline(always)]
5168 fn real_part_impl(value: &Self) -> Self::Real {
5169 *value
5170 }
5171
5172 #[inline(always)]
5173 fn imag_part_impl(_: &Self) -> Self::Real {
5174 Self::ZERO
5175 }
5176
5177 #[inline(always)]
5178 fn copy_impl(value: &Self) -> Self {
5179 *value
5180 }
5181
5182 #[inline(always)]
5183 fn conj_impl(value: &Self) -> Self {
5184 *value
5185 }
5186
5187 #[inline(always)]
5188 fn recip_impl(value: &Self) -> Self {
5189 if value.0.abs() == f64::INFINITY {
5190 Quad::ZERO
5191 } else {
5192 Quad::from(1.0) / *value
5193 }
5194 }
5195
5196 #[inline(always)]
5197 fn sqrt_impl(value: &Self) -> Self {
5198 value.sqrt()
5199 }
5200
5201 #[inline(always)]
5202 fn abs_impl(value: &Self) -> Self::Real {
5203 value.abs()
5204 }
5205
5206 #[inline(always)]
5207 fn abs1_impl(value: &Self) -> Self::Real {
5208 value.abs()
5209 }
5210
5211 #[inline(always)]
5212 fn abs2_impl(value: &Self) -> Self::Real {
5213 value * value
5214 }
5215
5216 #[inline(always)]
5217 fn mul_real_impl(lhs: &Self, rhs: &Self::Real) -> Self {
5218 lhs * rhs
5219 }
5220
5221 #[inline(always)]
5222 fn mul_pow2_impl(lhs: &Self, rhs: &Self::Real) -> Self {
5223 lhs * rhs
5224 }
5225
5226 #[inline(always)]
5227 fn is_finite_impl(value: &Self) -> bool {
5228 value.0.is_finite() && value.1.is_finite()
5229 }
5230
5231 #[inline(always)]
5232 fn simd_ctx<S: Simd>(simd: S) -> Self::SimdCtx<S> {
5233 simd
5234 }
5235
5236 #[inline(always)]
5237 fn ctx_from_simd<S: Simd>(ctx: &Self::SimdCtx<S>) -> S {
5238 *ctx
5239 }
5240
5241 #[inline(always)]
5242 fn simd_mask_between<S: Simd>(
5243 ctx: &Self::SimdCtx<S>,
5244 start: Self::Index,
5245 end: Self::Index,
5246 ) -> Self::SimdMask<S> {
5247 ctx.mask_between_m64s(start as _, end as _).mask()
5248 }
5249
5250 #[inline(always)]
5251 fn simd_mem_mask_between<S: Simd>(
5252 ctx: &Self::SimdCtx<S>,
5253 start: Self::Index,
5254 end: Self::Index,
5255 ) -> Self::SimdMemMask<S> {
5256 let n = (core::mem::size_of::<Self::SimdVec<S>>()
5257 / core::mem::size_of::<Self>()) as u64;
5258 let start = start * 2;
5259 let end = end * 2;
5260 let mut sa = start.min(n);
5261 let mut ea = end.min(n);
5262 let mut sb = start.max(n) - n;
5263 let mut eb = end.max(n) - n;
5264 if sa == ea {
5265 sa = 0;
5266 ea = 0;
5267 }
5268 if sb == eb {
5269 sb = 0;
5270 eb = 0;
5271 }
5272 let a = f64::simd_mem_mask_between(ctx, sa, ea);
5273 let b = f64::simd_mem_mask_between(ctx, sb, eb);
5274 Quad(a, b)
5275 }
5276
5277 #[inline(always)]
5278 unsafe fn simd_mask_load_raw<S: Simd>(
5279 ctx: &Self::SimdCtx<S>,
5280 mask: Self::SimdMemMask<S>,
5281 ptr: *const Self::SimdVec<S>,
5282 ) -> Self::SimdVec<S> {
5283 unsafe {
5284 Quad(
5285 f64::simd_mask_load_raw(ctx, mask.0, &raw const (*ptr).0),
5286 f64::simd_mask_load_raw(ctx, mask.1, &raw const (*ptr).1),
5287 )
5288 }
5289 }
5290
5291 #[inline(always)]
5292 unsafe fn simd_mask_store_raw<S: Simd>(
5293 ctx: &Self::SimdCtx<S>,
5294 mask: Self::SimdMemMask<S>,
5295 ptr: *mut Self::SimdVec<S>,
5296 values: Self::SimdVec<S>,
5297 ) {
5298 unsafe {
5299 Quad(
5300 f64::simd_mask_store_raw(
5301 ctx,
5302 mask.0,
5303 &raw mut (*ptr).0,
5304 values.0,
5305 ),
5306 f64::simd_mask_store_raw(
5307 ctx,
5308 mask.1,
5309 &raw mut (*ptr).1,
5310 values.1,
5311 ),
5312 );
5313 }
5314 }
5315
5316 #[inline(always)]
5317 fn simd_splat<S: Simd>(
5318 ctx: &Self::SimdCtx<S>,
5319 value: &Self,
5320 ) -> Self::SimdVec<S> {
5321 Quad(ctx.splat_f64s(value.0), ctx.splat_f64s(value.1))
5322 }
5323
5324 #[inline(always)]
5325 fn simd_splat_real<S: Simd>(
5326 ctx: &Self::SimdCtx<S>,
5327 value: &Self::Real,
5328 ) -> Self::SimdVec<S> {
5329 Quad(ctx.splat_f64s(value.0), ctx.splat_f64s(value.1))
5330 }
5331
5332 #[inline(always)]
5333 fn simd_add<S: Simd>(
5334 ctx: &Self::SimdCtx<S>,
5335 lhs: Self::SimdVec<S>,
5336 rhs: Self::SimdVec<S>,
5337 ) -> Self::SimdVec<S> {
5338 qd::simd::add_estimate(*ctx, lhs, rhs)
5339 }
5340
5341 #[inline(always)]
5342 fn simd_sub<S: Simd>(
5343 ctx: &Self::SimdCtx<S>,
5344 lhs: Self::SimdVec<S>,
5345 rhs: Self::SimdVec<S>,
5346 ) -> Self::SimdVec<S> {
5347 qd::simd::sub_estimate(*ctx, lhs, rhs)
5348 }
5349
5350 #[inline(always)]
5351 fn simd_neg<S: Simd>(
5352 ctx: &Self::SimdCtx<S>,
5353 value: Self::SimdVec<S>,
5354 ) -> Self::SimdVec<S> {
5355 qd::simd::neg(*ctx, value)
5356 }
5357
5358 #[inline(always)]
5359 fn simd_conj<S: Simd>(
5360 _: &Self::SimdCtx<S>,
5361 value: Self::SimdVec<S>,
5362 ) -> Self::SimdVec<S> {
5363 value
5364 }
5365
5366 #[inline(always)]
5367 fn simd_abs1<S: Simd>(
5368 ctx: &Self::SimdCtx<S>,
5369 value: Self::SimdVec<S>,
5370 ) -> Self::SimdVec<S> {
5371 qd::simd::abs(*ctx, value)
5372 }
5373
5374 #[inline(always)]
5375 fn simd_abs_max<S: Simd>(
5376 ctx: &Self::SimdCtx<S>,
5377 value: Self::SimdVec<S>,
5378 ) -> Self::SimdVec<S> {
5379 qd::simd::abs(*ctx, value)
5380 }
5381
5382 #[inline(always)]
5383 fn simd_mul_real<S: Simd>(
5384 ctx: &Self::SimdCtx<S>,
5385 lhs: Self::SimdVec<S>,
5386 real_rhs: Self::SimdVec<S>,
5387 ) -> Self::SimdVec<S> {
5388 qd::simd::mul(*ctx, lhs, real_rhs)
5389 }
5390
5391 #[inline(always)]
5392 fn simd_mul_pow2<S: Simd>(
5393 ctx: &Self::SimdCtx<S>,
5394 lhs: Self::SimdVec<S>,
5395 real_rhs: Self::SimdVec<S>,
5396 ) -> Self::SimdVec<S> {
5397 qd::simd::mul(*ctx, lhs, real_rhs)
5398 }
5399
5400 #[inline(always)]
5401 fn simd_mul<S: Simd>(
5402 ctx: &Self::SimdCtx<S>,
5403 lhs: Self::SimdVec<S>,
5404 rhs: Self::SimdVec<S>,
5405 ) -> Self::SimdVec<S> {
5406 qd::simd::mul(*ctx, lhs, rhs)
5407 }
5408
5409 #[inline(always)]
5410 fn simd_conj_mul<S: Simd>(
5411 ctx: &Self::SimdCtx<S>,
5412 lhs: Self::SimdVec<S>,
5413 rhs: Self::SimdVec<S>,
5414 ) -> Self::SimdVec<S> {
5415 qd::simd::mul(*ctx, lhs, rhs)
5416 }
5417
5418 #[inline(always)]
5419 fn simd_mul_add<S: Simd>(
5420 ctx: &Self::SimdCtx<S>,
5421 lhs: Self::SimdVec<S>,
5422 rhs: Self::SimdVec<S>,
5423 acc: Self::SimdVec<S>,
5424 ) -> Self::SimdVec<S> {
5425 qd::simd::add_estimate(*ctx, qd::simd::mul(*ctx, lhs, rhs), acc)
5426 }
5427
5428 #[inline(always)]
5429 fn simd_conj_mul_add<S: Simd>(
5430 ctx: &Self::SimdCtx<S>,
5431 lhs: Self::SimdVec<S>,
5432 rhs: Self::SimdVec<S>,
5433 acc: Self::SimdVec<S>,
5434 ) -> Self::SimdVec<S> {
5435 qd::simd::add_estimate(*ctx, qd::simd::mul(*ctx, lhs, rhs), acc)
5436 }
5437
5438 #[inline(always)]
5439 fn simd_abs2<S: Simd>(
5440 ctx: &Self::SimdCtx<S>,
5441 value: Self::SimdVec<S>,
5442 ) -> Self::SimdVec<S> {
5443 qd::simd::mul(*ctx, value, value)
5444 }
5445
5446 #[inline(always)]
5447 fn simd_abs2_add<S: Simd>(
5448 ctx: &Self::SimdCtx<S>,
5449 value: Self::SimdVec<S>,
5450 acc: Self::SimdVec<S>,
5451 ) -> Self::SimdVec<S> {
5452 qd::simd::add_estimate(*ctx, qd::simd::mul(*ctx, value, value), acc)
5453 }
5454
5455 #[inline(always)]
5456 fn simd_reduce_sum<S: Simd>(
5457 _: &Self::SimdCtx<S>,
5458 value: Self::SimdVec<S>,
5459 ) -> Self {
5460 let a = value.0;
5461 let b = value.1;
5462 let a: &[f64] = bytemuck::cast_slice(core::slice::from_ref(&a));
5463 let b: &[f64] = bytemuck::cast_slice(core::slice::from_ref(&b));
5464 let mut acc = Quad::ZERO;
5465 for (&a, &b) in core::iter::zip(a, b) {
5466 acc += Quad(a, b);
5467 }
5468 acc
5469 }
5470
5471 #[inline(always)]
5472 fn simd_reduce_max<S: Simd>(
5473 _: &Self::SimdCtx<S>,
5474 value: Self::SimdVec<S>,
5475 ) -> Self {
5476 let a = value.0;
5477 let b = value.1;
5478 let a: &[f64] = bytemuck::cast_slice(core::slice::from_ref(&a));
5479 let b: &[f64] = bytemuck::cast_slice(core::slice::from_ref(&b));
5480 let mut acc = Quad::NEG_INFINITY;
5481 for (&a, &b) in core::iter::zip(a, b) {
5482 let val = Quad(a, b);
5483 if val > acc {
5484 acc = val
5485 }
5486 }
5487 acc
5488 }
5489
5490 #[inline(always)]
5491 fn simd_equal<S: Simd>(
5492 ctx: &Self::SimdCtx<S>,
5493 real_lhs: Self::SimdVec<S>,
5494 real_rhs: Self::SimdVec<S>,
5495 ) -> Self::SimdMask<S> {
5496 qd::simd::eq(*ctx, real_lhs, real_rhs)
5497 }
5498
5499 #[inline(always)]
5500 fn simd_less_than<S: Simd>(
5501 ctx: &Self::SimdCtx<S>,
5502 real_lhs: Self::SimdVec<S>,
5503 real_rhs: Self::SimdVec<S>,
5504 ) -> Self::SimdMask<S> {
5505 qd::simd::less_than(*ctx, real_lhs, real_rhs)
5506 }
5507
5508 #[inline(always)]
5509 fn simd_less_than_or_equal<S: Simd>(
5510 ctx: &Self::SimdCtx<S>,
5511 real_lhs: Self::SimdVec<S>,
5512 real_rhs: Self::SimdVec<S>,
5513 ) -> Self::SimdMask<S> {
5514 qd::simd::less_than_or_equal(*ctx, real_lhs, real_rhs)
5515 }
5516
5517 #[inline(always)]
5518 fn simd_greater_than<S: Simd>(
5519 ctx: &Self::SimdCtx<S>,
5520 real_lhs: Self::SimdVec<S>,
5521 real_rhs: Self::SimdVec<S>,
5522 ) -> Self::SimdMask<S> {
5523 qd::simd::greater_than(*ctx, real_lhs, real_rhs)
5524 }
5525
5526 #[inline(always)]
5527 fn simd_greater_than_or_equal<S: Simd>(
5528 ctx: &Self::SimdCtx<S>,
5529 real_lhs: Self::SimdVec<S>,
5530 real_rhs: Self::SimdVec<S>,
5531 ) -> Self::SimdMask<S> {
5532 qd::simd::greater_than_or_equal(*ctx, real_lhs, real_rhs)
5533 }
5534
5535 #[inline(always)]
5536 fn simd_select<S: Simd>(
5537 ctx: &Self::SimdCtx<S>,
5538 mask: Self::SimdMask<S>,
5539 lhs: Self::SimdVec<S>,
5540 rhs: Self::SimdVec<S>,
5541 ) -> Self::SimdVec<S> {
5542 Quad(
5543 ctx.select_f64s(mask, lhs.0, rhs.0),
5544 ctx.select_f64s(mask, lhs.1, rhs.1),
5545 )
5546 }
5547
5548 #[inline(always)]
5549 fn simd_index_select<S: Simd>(
5550 ctx: &Self::SimdCtx<S>,
5551 mask: Self::SimdMask<S>,
5552 lhs: Self::SimdIndex<S>,
5553 rhs: Self::SimdIndex<S>,
5554 ) -> Self::SimdIndex<S> {
5555 ctx.select_u64s(mask, lhs, rhs)
5556 }
5557
5558 #[inline(always)]
5559 fn simd_index_splat<S: Simd>(
5560 ctx: &Self::SimdCtx<S>,
5561 value: Self::Index,
5562 ) -> Self::SimdIndex<S> {
5563 ctx.splat_u64s(value as u64)
5564 }
5565
5566 #[inline(always)]
5567 fn simd_index_add<S: Simd>(
5568 ctx: &Self::SimdCtx<S>,
5569 lhs: Self::SimdIndex<S>,
5570 rhs: Self::SimdIndex<S>,
5571 ) -> Self::SimdIndex<S> {
5572 ctx.add_u64s(lhs, rhs)
5573 }
5574
5575 #[inline(always)]
5576 fn simd_index_less_than<S: Simd>(
5577 ctx: &Self::SimdCtx<S>,
5578 lhs: Self::SimdIndex<S>,
5579 rhs: Self::SimdIndex<S>,
5580 ) -> Self::SimdMask<S> {
5581 ctx.less_than_u64s(lhs, rhs)
5582 }
5583
5584 #[inline(always)]
5585 fn simd_and_mask<S: Simd>(
5586 ctx: &Self::SimdCtx<S>,
5587 lhs: Self::SimdMask<S>,
5588 rhs: Self::SimdMask<S>,
5589 ) -> Self::SimdMask<S> {
5590 ctx.and_m64s(lhs, rhs)
5591 }
5592
5593 #[inline(always)]
5594 fn simd_or_mask<S: Simd>(
5595 ctx: &Self::SimdCtx<S>,
5596 lhs: Self::SimdMask<S>,
5597 rhs: Self::SimdMask<S>,
5598 ) -> Self::SimdMask<S> {
5599 ctx.or_m64s(lhs, rhs)
5600 }
5601
5602 #[inline(always)]
5603 fn simd_not_mask<S: Simd>(
5604 ctx: &Self::SimdCtx<S>,
5605 mask: Self::SimdMask<S>,
5606 ) -> Self::SimdMask<S> {
5607 ctx.not_m64s(mask)
5608 }
5609
5610 #[inline(always)]
5611 fn simd_first_true_mask<S: Simd>(
5612 ctx: &Self::SimdCtx<S>,
5613 value: Self::SimdMask<S>,
5614 ) -> usize {
5615 ctx.first_true_m64s(value)
5616 }
5617}
5618impl RealField for fx128 {
5619 #[inline(always)]
5620 fn epsilon_impl() -> Self {
5621 let mut x = Quad::EPSILON;
5622 x.0 *= 8.0;
5623 x.1 *= 8.0;
5624 x
5625 }
5626
5627 #[inline(always)]
5628 fn nbits_impl() -> usize {
5629 100
5630 }
5631
5632 #[inline(always)]
5633 fn min_positive_impl() -> Self {
5634 Quad::MIN_POSITIVE
5635 }
5636
5637 #[inline(always)]
5638 fn max_positive_impl() -> Self {
5639 Quad::MIN_POSITIVE.recip()
5640 }
5641
5642 #[inline(always)]
5643 fn sqrt_min_positive_impl() -> Self {
5644 Quad::MIN_POSITIVE.sqrt()
5645 }
5646
5647 #[inline(always)]
5648 fn sqrt_max_positive_impl() -> Self {
5649 Quad::MIN_POSITIVE.recip().sqrt()
5650 }
5651}
5652pub mod ext {
5653 use super::*;
5654 pub use super::{ComplexField, RealField};
5655 pub trait ComplexFieldExt: ComplexField {
5656 #[inline(always)]
5657 #[must_use]
5658 fn nbits() -> usize {
5659 Self::Real::nbits_impl()
5660 }
5661 #[inline(always)]
5662 #[must_use]
5663 fn zero() -> Self {
5664 Self::zero_impl()
5665 }
5666 #[inline(always)]
5667 #[must_use]
5668 fn one() -> Self {
5669 Self::one_impl()
5670 }
5671 #[inline(always)]
5672 #[must_use]
5673 fn nan() -> Self {
5674 Self::nan_impl()
5675 }
5676 #[inline(always)]
5677 #[must_use]
5678 fn infinity() -> Self {
5679 Self::infinity_impl()
5680 }
5681 #[inline(always)]
5682 #[must_use]
5683 fn as_real(&self) -> Self {
5684 Self::from_real_impl(&Self::real_part_impl(self))
5685 }
5686 #[inline(always)]
5687 #[must_use]
5688 fn real(&self) -> Self::Real {
5689 Self::real_part_impl(self)
5690 }
5691 #[inline(always)]
5692 #[must_use]
5693 fn imag(&self) -> Self::Real {
5694 Self::imag_part_impl(self)
5695 }
5696 #[inline(always)]
5697 #[must_use]
5698 fn copy(&self) -> Self {
5699 Self::copy_impl(self)
5700 }
5701 #[inline(always)]
5702 #[must_use]
5703 fn conj(&self) -> Self {
5704 Self::conj_impl(self)
5705 }
5706 #[inline(always)]
5707 #[must_use]
5708 fn mul_real(&self, rhs: impl ByRef<Self::Real>) -> Self {
5709 Self::mul_real_impl(self, rhs.by_ref())
5710 }
5711 #[inline(always)]
5712 #[must_use]
5713 fn mul_pow2(&self, rhs: impl ByRef<Self::Real>) -> Self {
5714 Self::mul_real_impl(self, rhs.by_ref())
5715 }
5716 #[inline(always)]
5717 #[must_use]
5718 fn abs1(&self) -> Self::Real {
5719 Self::abs1_impl(self)
5720 }
5721 #[inline(always)]
5722 #[must_use]
5723 fn absmax(&self) -> Self::Real {
5724 if const { Self::IS_REAL } {
5725 Self::abs1_impl(self)
5726 } else {
5727 &Self::Real::abs1_impl(&real(self))
5728 + &Self::Real::abs1_impl(&imag(self))
5729 }
5730 }
5731 #[inline(always)]
5732 #[must_use]
5733 fn abs(&self) -> Self::Real {
5734 Self::abs_impl(self)
5735 }
5736 #[inline(always)]
5737 #[must_use]
5738 fn abs2(&self) -> Self::Real {
5739 Self::abs2_impl(self)
5740 }
5741 #[inline(always)]
5742 #[must_use]
5743 fn is_nan(&self) -> bool {
5744 Self::is_nan_impl(self)
5745 }
5746 #[inline(always)]
5747 #[must_use]
5748 fn is_finite(&self) -> bool {
5749 Self::is_finite_impl(self)
5750 }
5751 #[inline(always)]
5752 #[must_use]
5753 fn sqrt(&self) -> Self {
5754 Self::sqrt_impl(self)
5755 }
5756 #[inline(always)]
5757 #[must_use]
5758 fn recip(&self) -> Self {
5759 Self::recip_impl(self)
5760 }
5761 #[inline(always)]
5762 #[must_use]
5763 fn from_f64(value: f64) -> Self {
5764 Self::from_f64_impl(value)
5765 }
5766 }
5767 pub trait RealFieldExt: RealField {
5768 #[inline(always)]
5769 #[must_use]
5770 fn eps<T: RealField>() -> T {
5771 T::Real::epsilon_impl()
5772 }
5773 #[inline(always)]
5774 #[must_use]
5775 fn nbits<T: ComplexField>() -> usize {
5776 T::Real::nbits_impl()
5777 }
5778 #[inline(always)]
5779 #[must_use]
5780 fn min_positive<T: RealField>() -> T {
5781 T::min_positive_impl()
5782 }
5783 #[inline(always)]
5784 #[must_use]
5785 fn max_positive<T: RealField>() -> T {
5786 T::max_positive_impl()
5787 }
5788 #[inline(always)]
5789 #[must_use]
5790 fn sqrt_min_positive<T: RealField>() -> T {
5791 T::sqrt_min_positive_impl()
5792 }
5793 #[inline(always)]
5794 #[must_use]
5795 fn sqrt_max_positive<T: RealField>() -> T {
5796 T::sqrt_max_positive_impl()
5797 }
5798 #[inline(always)]
5799 #[must_use]
5800 fn to_cplx<T: ComplexField<Real = Self>>(&self) -> T {
5801 T::from_real_impl(self)
5802 }
5803 #[inline(always)]
5804 #[must_use]
5805 fn fmax(&self, rhs: impl ByRef<Self>) -> Self {
5806 math_utils::max(self, rhs.by_ref())
5807 }
5808 #[inline(always)]
5809 #[must_use]
5810 fn fmin(&self, rhs: impl ByRef<Self>) -> Self {
5811 math_utils::min(self, rhs.by_ref())
5812 }
5813 #[inline(always)]
5814 #[must_use]
5815 fn hypot(&self, rhs: impl ByRef<Self>) -> Self {
5816 math_utils::hypot(self, rhs.by_ref())
5817 }
5818 }
5819 impl<T: ComplexField> ComplexFieldExt for T {}
5820 impl<T: RealField> RealFieldExt for T {}
5821}
5822#[cfg(test)]
5823mod tests {
5824 use super::*;
5825 #[test]
5828 fn recip_of_subnormal() {
5829 let (re, im) = recip_impl(0.0f64, f64::MIN_POSITIVE / 2.0);
5830 assert_eq!((re, im), (0.0, -2.0 / f64::MIN_POSITIVE));
5831 let (re, im) = recip_impl(f64::MIN_POSITIVE / 4.0, 0.0);
5832 assert_eq!((re, im), (4.0 / f64::MIN_POSITIVE, 0.0));
5833 let (re, im) = recip_impl(0.0f32, f32::MIN_POSITIVE / 2.0);
5834 assert_eq!((re, im), (0.0, -2.0 / f32::MIN_POSITIVE));
5835 let (re, _) = recip_impl(f64::from_bits(1), 0.0);
5837 assert_eq!(re, f64::INFINITY);
5838 }
5839}