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