/rust/registry/src/index.crates.io-1949cf8c6b5b557f/simba-0.10.2/src/scalar/complex.rs
Line | Count | Source |
1 | | use num::{One, Signed, Zero}; |
2 | | use num_traits::FromPrimitive; |
3 | | use std::any::Any; |
4 | | use std::fmt::{Debug, Display}; |
5 | | use std::ops::Neg; |
6 | | use std::{f32, f64}; |
7 | | |
8 | | use crate::scalar::{Field, RealField, SubsetOf, SupersetOf}; |
9 | | #[cfg(all(not(feature = "std"), not(feature = "libm_force"), feature = "libm"))] |
10 | | use num::Float; |
11 | | //#[cfg(feature = "decimal")] |
12 | | //use decimal::d128; |
13 | | |
14 | | /// Trait shared by all complex fields and its subfields (like real numbers). |
15 | | /// |
16 | | /// Complex numbers are equipped with functions that are commonly used on complex numbers and reals. |
17 | | /// The results of those functions only have to be approximately equal to the actual theoretical values. |
18 | | // TODO: SubsetOf should be removed when specialization will be supported by rustc. This will |
19 | | // allow a blanket impl: impl<T: Clone> SubsetOf<T> for T { ... } |
20 | | #[allow(missing_docs)] |
21 | | pub trait ComplexField: |
22 | | SubsetOf<Self> |
23 | | + SupersetOf<f32> |
24 | | + SupersetOf<f64> |
25 | | + FromPrimitive |
26 | | + Field<Element=Self, SimdBool=bool> |
27 | | + Neg<Output=Self> |
28 | | + Clone |
29 | | // + MeetSemilattice |
30 | | // + JoinSemilattice |
31 | | + Send |
32 | | + Sync |
33 | | + Any |
34 | | + 'static |
35 | | + Debug |
36 | | + Display |
37 | | { |
38 | | type RealField: RealField;/// Builds a pure-real complex number from the given value. |
39 | | fn from_real(re: Self::RealField) -> Self; |
40 | | |
41 | | /// The real part of this complex number. |
42 | | fn real(self) -> Self::RealField; |
43 | | |
44 | | /// The imaginary part of this complex number. |
45 | | fn imaginary(self) -> Self::RealField; |
46 | | |
47 | | /// The modulus of this complex number. |
48 | | fn modulus(self) -> Self::RealField; |
49 | | |
50 | | /// The squared modulus of this complex number. |
51 | | fn modulus_squared(self) -> Self::RealField; |
52 | | |
53 | | /// The argument of this complex number. |
54 | | fn argument(self) -> Self::RealField; |
55 | | |
56 | | /// The sum of the absolute value of this complex number's real and imaginary part. |
57 | | fn norm1(self) -> Self::RealField; |
58 | | |
59 | | /// Multiplies this complex number by `factor`. |
60 | | fn scale(self, factor: Self::RealField) -> Self; |
61 | | |
62 | | /// Divides this complex number by `factor`. |
63 | | fn unscale(self, factor: Self::RealField) -> Self; |
64 | | |
65 | | /// The polar form of this complex number: (modulus, arg) |
66 | | fn to_polar(self) -> (Self::RealField, Self::RealField) { |
67 | | (self.clone().modulus(), self.argument()) |
68 | | } |
69 | | |
70 | | /// The exponential form of this complex number: (modulus, e^{i arg}) |
71 | | fn to_exp(self) -> (Self::RealField, Self) { |
72 | | let m = self.clone().modulus(); |
73 | | |
74 | | if !m.is_zero() { |
75 | | (m.clone(), self.unscale(m)) |
76 | | } else { |
77 | | (Self::RealField::zero(), Self::one()) |
78 | | } |
79 | | } |
80 | | |
81 | | /// The exponential part of this complex number: `self / self.modulus()` |
82 | | fn signum(self) -> Self { |
83 | | self.to_exp().1 |
84 | | } |
85 | | |
86 | | fn floor(self) -> Self; |
87 | | fn ceil(self) -> Self; |
88 | | fn round(self) -> Self; |
89 | | fn trunc(self) -> Self; |
90 | | fn fract(self) -> Self; |
91 | | fn mul_add(self, a: Self, b: Self) -> Self; |
92 | | |
93 | | /// The absolute value of this complex number: `self / self.signum()`. |
94 | | /// |
95 | | /// This is equivalent to `self.modulus()`. |
96 | | fn abs(self) -> Self::RealField; |
97 | | |
98 | | /// Computes (self.conjugate() * self + other.conjugate() * other).sqrt() |
99 | | fn hypot(self, other: Self) -> Self::RealField; |
100 | | |
101 | | fn recip(self) -> Self; |
102 | | fn conjugate(self) -> Self; |
103 | | fn sin(self) -> Self; |
104 | | fn cos(self) -> Self; |
105 | | fn sin_cos(self) -> (Self, Self); |
106 | | #[inline] |
107 | | fn sinh_cosh(self) -> (Self, Self) { |
108 | | (self.clone().sinh(), self.cosh()) |
109 | | } |
110 | | fn tan(self) -> Self; |
111 | | fn asin(self) -> Self; |
112 | | fn acos(self) -> Self; |
113 | | fn atan(self) -> Self; |
114 | | fn sinh(self) -> Self; |
115 | | fn cosh(self) -> Self; |
116 | | fn tanh(self) -> Self; |
117 | | fn asinh(self) -> Self; |
118 | | fn acosh(self) -> Self; |
119 | | fn atanh(self) -> Self; |
120 | | |
121 | | /// Cardinal sine |
122 | | #[inline] |
123 | | fn sinc(self) -> Self { |
124 | | if self.is_zero() { |
125 | | Self::one() |
126 | | } else { |
127 | | self.clone().sin() / self |
128 | | } |
129 | | } |
130 | | |
131 | | #[inline] |
132 | | fn sinhc(self) -> Self { |
133 | | if self.is_zero() { |
134 | | Self::one() |
135 | | } else { |
136 | | self.clone().sinh() / self |
137 | | } |
138 | | } |
139 | | |
140 | | /// Cardinal cos |
141 | | #[inline] |
142 | | fn cosc(self) -> Self { |
143 | | if self.is_zero() { |
144 | | Self::one() |
145 | | } else { |
146 | | self.clone().cos() / self |
147 | | } |
148 | | } |
149 | | |
150 | | #[inline] |
151 | | fn coshc(self) -> Self { |
152 | | if self.is_zero() { |
153 | | Self::one() |
154 | | } else { |
155 | | self.clone().cosh() / self |
156 | | } |
157 | | } |
158 | | |
159 | | fn log(self, base: Self::RealField) -> Self; |
160 | | fn log2(self) -> Self; |
161 | | fn log10(self) -> Self; |
162 | | fn ln(self) -> Self; |
163 | | fn ln_1p(self) -> Self; |
164 | | fn sqrt(self) -> Self; |
165 | | fn exp(self) -> Self; |
166 | | fn exp2(self) -> Self; |
167 | | fn exp_m1(self) -> Self; |
168 | | fn powi(self, n: i32) -> Self; |
169 | | fn powf(self, n: Self::RealField) -> Self; |
170 | | fn powc(self, n: Self) -> Self; |
171 | | fn cbrt(self) -> Self; |
172 | | fn is_finite(&self) -> bool; |
173 | | fn try_sqrt(self) -> Option<Self>; |
174 | | } |
175 | | |
176 | | #[cfg(not(feature = "libm_force"))] |
177 | | macro_rules! impl_complex ( |
178 | | ($($T:ty, $M:ident, $libm: ident);*) => ($( |
179 | | impl ComplexField for $T { |
180 | | type RealField = $T; |
181 | | |
182 | | #[inline] |
183 | 0 | fn from_real(re: Self::RealField) -> Self { |
184 | 0 | re |
185 | 0 | } |
186 | | |
187 | | #[inline] |
188 | 458 | fn real(self) -> Self::RealField { |
189 | 458 | self |
190 | 458 | } |
191 | | |
192 | | #[inline] |
193 | | fn imaginary(self) -> Self::RealField { |
194 | | Self::zero() |
195 | | } |
196 | | |
197 | | #[inline] |
198 | 0 | fn norm1(self) -> Self::RealField { |
199 | 0 | $libm::abs(self) |
200 | 0 | } |
201 | | |
202 | | #[inline] |
203 | 0 | fn modulus(self) -> Self::RealField { |
204 | 0 | $libm::abs(self) |
205 | 0 | } |
206 | | |
207 | | #[inline] |
208 | 0 | fn modulus_squared(self) -> Self::RealField { |
209 | 0 | self * self |
210 | 0 | } |
211 | | |
212 | | #[inline] |
213 | | fn argument(self) -> Self::RealField { |
214 | | if self >= Self::zero() { |
215 | | Self::zero() |
216 | | } else { |
217 | | Self::pi() |
218 | | } |
219 | | } |
220 | | |
221 | | #[inline] |
222 | 0 | fn to_exp(self) -> (Self, Self) { |
223 | 0 | if self >= Self::zero() { |
224 | 0 | (self, Self::one()) |
225 | | } else { |
226 | 0 | (-self, -Self::one()) |
227 | | } |
228 | 0 | } |
229 | | |
230 | | #[inline] |
231 | | fn recip(self) -> Self { |
232 | | $M::recip(self) |
233 | | } |
234 | | |
235 | | #[inline] |
236 | 1.37k | fn conjugate(self) -> Self { |
237 | 1.37k | self |
238 | 1.37k | } |
239 | | |
240 | | #[inline] |
241 | 0 | fn scale(self, factor: Self::RealField) -> Self { |
242 | 0 | self * factor |
243 | 0 | } |
244 | | |
245 | | #[inline] |
246 | 0 | fn unscale(self, factor: Self::RealField) -> Self { |
247 | 0 | self / factor |
248 | 0 | } |
249 | | |
250 | | #[inline] |
251 | | fn floor(self) -> Self { |
252 | | $libm::floor(self) |
253 | | } |
254 | | |
255 | | #[inline] |
256 | | fn ceil(self) -> Self { |
257 | | $libm::ceil(self) |
258 | | } |
259 | | |
260 | | #[inline] |
261 | | fn round(self) -> Self { |
262 | | $libm::round(self) |
263 | | } |
264 | | |
265 | | #[inline] |
266 | | fn trunc(self) -> Self { |
267 | | $libm::trunc(self) |
268 | | } |
269 | | |
270 | | #[inline] |
271 | | fn fract(self) -> Self { |
272 | | $libm::fract(self) |
273 | | } |
274 | | |
275 | | #[inline] |
276 | 0 | fn abs(self) -> Self { |
277 | 0 | $libm::abs(self) |
278 | 0 | } |
279 | | |
280 | | #[inline] |
281 | 0 | fn signum(self) -> Self { |
282 | 0 | Signed::signum(&self) |
283 | 0 | } |
284 | | |
285 | | #[inline] |
286 | | fn mul_add(self, a: Self, b: Self) -> Self { |
287 | | $libm::mul_add(self, a, b) |
288 | | } |
289 | | |
290 | | #[cfg(feature = "std")] |
291 | | #[inline] |
292 | | fn powi(self, n: i32) -> Self { |
293 | | self.powi(n) |
294 | | } |
295 | | |
296 | | #[cfg(not(feature = "std"))] |
297 | | #[inline] |
298 | | fn powi(self, n: i32) -> Self { |
299 | | // TODO: is there a more accurate solution? |
300 | | $libm::powf(self, n as $T) |
301 | | } |
302 | | |
303 | | #[inline] |
304 | | fn powf(self, n: Self) -> Self { |
305 | | $libm::powf(self, n) |
306 | | } |
307 | | |
308 | | #[inline] |
309 | | fn powc(self, n: Self) -> Self { |
310 | | // Same as powf. |
311 | | $libm::powf(self, n) |
312 | | } |
313 | | |
314 | | #[inline] |
315 | 164 | fn sqrt(self) -> Self { |
316 | 164 | $libm::sqrt(self) |
317 | 164 | } |
318 | | |
319 | | #[inline] |
320 | 0 | fn try_sqrt(self) -> Option<Self> { |
321 | 0 | if self >= Self::zero() { |
322 | 0 | Some($libm::sqrt(self)) |
323 | | } else { |
324 | 0 | None |
325 | | } |
326 | 0 | } |
327 | | |
328 | | #[inline] |
329 | | fn exp(self) -> Self { |
330 | | $libm::exp(self) |
331 | | } |
332 | | |
333 | | #[inline] |
334 | | fn exp2(self) -> Self { |
335 | | $libm::exp2(self) |
336 | | } |
337 | | |
338 | | |
339 | | #[inline] |
340 | | fn exp_m1(self) -> Self { |
341 | | $libm::exp_m1(self) |
342 | | } |
343 | | |
344 | | #[inline] |
345 | | fn ln_1p(self) -> Self { |
346 | | $libm::ln_1p(self) |
347 | | } |
348 | | |
349 | | #[inline] |
350 | | fn ln(self) -> Self { |
351 | | $libm::ln(self) |
352 | | } |
353 | | |
354 | | #[inline] |
355 | | fn log(self, base: Self) -> Self { |
356 | | $libm::log(self, base) |
357 | | } |
358 | | |
359 | | #[inline] |
360 | | fn log2(self) -> Self { |
361 | | $libm::log2(self) |
362 | | } |
363 | | |
364 | | #[inline] |
365 | | fn log10(self) -> Self { |
366 | | $libm::log10(self) |
367 | | } |
368 | | |
369 | | #[inline] |
370 | | fn cbrt(self) -> Self { |
371 | | $libm::cbrt(self) |
372 | | } |
373 | | |
374 | | #[inline] |
375 | | fn hypot(self, other: Self) -> Self::RealField { |
376 | | $libm::hypot(self, other) |
377 | | } |
378 | | |
379 | | #[inline] |
380 | | fn sin(self) -> Self { |
381 | | $libm::sin(self) |
382 | | } |
383 | | |
384 | | #[inline] |
385 | | fn cos(self) -> Self { |
386 | | $libm::cos(self) |
387 | | } |
388 | | |
389 | | #[inline] |
390 | | fn tan(self) -> Self { |
391 | | $libm::tan(self) |
392 | | } |
393 | | |
394 | | #[inline] |
395 | | fn asin(self) -> Self { |
396 | | $libm::asin(self) |
397 | | } |
398 | | |
399 | | #[inline] |
400 | 0 | fn acos(self) -> Self { |
401 | 0 | $libm::acos(self) |
402 | 0 | } |
403 | | |
404 | | #[inline] |
405 | | fn atan(self) -> Self { |
406 | | $libm::atan(self) |
407 | | } |
408 | | |
409 | | #[inline] |
410 | | fn sin_cos(self) -> (Self, Self) { |
411 | | $libm::sin_cos(self) |
412 | | } |
413 | | |
414 | | // #[inline] |
415 | | // fn exp_m1(self) -> Self { |
416 | | // $libm::exp_m1(self) |
417 | | // } |
418 | | // |
419 | | // #[inline] |
420 | | // fn ln_1p(self) -> Self { |
421 | | // $libm::ln_1p(self) |
422 | | // } |
423 | | // |
424 | | #[inline] |
425 | | fn sinh(self) -> Self { |
426 | | $libm::sinh(self) |
427 | | } |
428 | | |
429 | | #[inline] |
430 | | fn cosh(self) -> Self { |
431 | | $libm::cosh(self) |
432 | | } |
433 | | |
434 | | #[inline] |
435 | | fn tanh(self) -> Self { |
436 | | $libm::tanh(self) |
437 | | } |
438 | | |
439 | | #[inline] |
440 | | fn asinh(self) -> Self { |
441 | | $libm::asinh(self) |
442 | | } |
443 | | |
444 | | #[inline] |
445 | | fn acosh(self) -> Self { |
446 | | $libm::acosh(self) |
447 | | } |
448 | | |
449 | | #[inline] |
450 | | fn atanh(self) -> Self { |
451 | | $libm::atanh(self) |
452 | | } |
453 | | |
454 | | #[inline] |
455 | | fn is_finite(&self) -> bool { |
456 | | $M::is_finite(*self) |
457 | | } |
458 | | } |
459 | | )*) |
460 | | ); |
461 | | |
462 | | #[cfg(all(not(feature = "std"), not(feature = "libm_force"), feature = "libm"))] |
463 | | impl_complex!( |
464 | | f32, f32, Float; |
465 | | f64, f64, Float |
466 | | ); |
467 | | |
468 | | #[cfg(all(feature = "std", not(feature = "libm_force")))] |
469 | | impl_complex!( |
470 | | f32,f32,f32; |
471 | | f64,f64,f64 |
472 | | ); |
473 | | |
474 | | #[cfg(feature = "libm_force")] |
475 | | impl ComplexField for f32 { |
476 | | type RealField = f32; |
477 | | |
478 | | #[inline] |
479 | | fn from_real(re: Self::RealField) -> Self { |
480 | | re |
481 | | } |
482 | | |
483 | | #[inline] |
484 | | fn real(self) -> Self::RealField { |
485 | | self |
486 | | } |
487 | | |
488 | | #[inline] |
489 | | fn imaginary(self) -> Self::RealField { |
490 | | Self::zero() |
491 | | } |
492 | | |
493 | | #[inline] |
494 | | fn norm1(self) -> Self::RealField { |
495 | | libm_force::fabsf(self) |
496 | | } |
497 | | |
498 | | #[inline] |
499 | | fn modulus(self) -> Self::RealField { |
500 | | libm_force::fabsf(self) |
501 | | } |
502 | | |
503 | | #[inline] |
504 | | fn modulus_squared(self) -> Self::RealField { |
505 | | self * self |
506 | | } |
507 | | |
508 | | #[inline] |
509 | | fn argument(self) -> Self::RealField { |
510 | | if self >= Self::zero() { |
511 | | Self::zero() |
512 | | } else { |
513 | | Self::pi() |
514 | | } |
515 | | } |
516 | | |
517 | | #[inline] |
518 | | fn to_exp(self) -> (Self, Self) { |
519 | | if self >= Self::zero() { |
520 | | (self, Self::one()) |
521 | | } else { |
522 | | (-self, -Self::one()) |
523 | | } |
524 | | } |
525 | | |
526 | | #[inline] |
527 | | fn recip(self) -> Self { |
528 | | f32::recip(self) |
529 | | } |
530 | | |
531 | | #[inline] |
532 | | fn conjugate(self) -> Self { |
533 | | self |
534 | | } |
535 | | |
536 | | #[inline] |
537 | | fn scale(self, factor: Self::RealField) -> Self { |
538 | | self * factor |
539 | | } |
540 | | |
541 | | #[inline] |
542 | | fn unscale(self, factor: Self::RealField) -> Self { |
543 | | self / factor |
544 | | } |
545 | | |
546 | | #[inline] |
547 | | fn floor(self) -> Self { |
548 | | libm_force::floorf(self) |
549 | | } |
550 | | |
551 | | #[inline] |
552 | | fn ceil(self) -> Self { |
553 | | libm_force::ceilf(self) |
554 | | } |
555 | | |
556 | | #[inline] |
557 | | fn round(self) -> Self { |
558 | | libm_force::roundf(self) |
559 | | } |
560 | | |
561 | | #[inline] |
562 | | fn trunc(self) -> Self { |
563 | | libm_force::truncf(self) |
564 | | } |
565 | | |
566 | | #[inline] |
567 | | fn fract(self) -> Self { |
568 | | self - libm_force::truncf(self) |
569 | | } |
570 | | |
571 | | #[inline] |
572 | | fn abs(self) -> Self { |
573 | | libm_force::fabsf(self) |
574 | | } |
575 | | |
576 | | #[inline] |
577 | | fn signum(self) -> Self { |
578 | | Signed::signum(&self) |
579 | | } |
580 | | |
581 | | #[inline] |
582 | | fn mul_add(self, a: Self, b: Self) -> Self { |
583 | | libm_force::fmaf(self, a, b) |
584 | | } |
585 | | |
586 | | #[inline] |
587 | | fn powi(self, n: i32) -> Self { |
588 | | // TODO: implement a more accurate/efficient solution? |
589 | | libm_force::powf(self, n as f32) |
590 | | } |
591 | | |
592 | | #[inline] |
593 | | fn powf(self, n: Self) -> Self { |
594 | | libm_force::powf(self, n) |
595 | | } |
596 | | |
597 | | #[inline] |
598 | | fn powc(self, n: Self) -> Self { |
599 | | // Same as powf. |
600 | | libm_force::powf(self, n) |
601 | | } |
602 | | |
603 | | #[inline] |
604 | | fn sqrt(self) -> Self { |
605 | | libm_force::sqrtf(self) |
606 | | } |
607 | | |
608 | | #[inline] |
609 | | fn try_sqrt(self) -> Option<Self> { |
610 | | if self >= Self::zero() { |
611 | | Some(libm_force::sqrtf(self)) |
612 | | } else { |
613 | | None |
614 | | } |
615 | | } |
616 | | |
617 | | #[inline] |
618 | | fn exp(self) -> Self { |
619 | | libm_force::expf(self) |
620 | | } |
621 | | |
622 | | #[inline] |
623 | | fn exp2(self) -> Self { |
624 | | libm_force::exp2f(self) |
625 | | } |
626 | | |
627 | | #[inline] |
628 | | fn exp_m1(self) -> Self { |
629 | | libm_force::expm1f(self) |
630 | | } |
631 | | |
632 | | #[inline] |
633 | | fn ln_1p(self) -> Self { |
634 | | libm_force::log1pf(self) |
635 | | } |
636 | | |
637 | | #[inline] |
638 | | fn ln(self) -> Self { |
639 | | libm_force::logf(self) |
640 | | } |
641 | | |
642 | | #[inline] |
643 | | fn log(self, base: Self) -> Self { |
644 | | libm_force::logf(self) / libm_force::logf(base) |
645 | | } |
646 | | |
647 | | #[inline] |
648 | | fn log2(self) -> Self { |
649 | | libm_force::log2f(self) |
650 | | } |
651 | | |
652 | | #[inline] |
653 | | fn log10(self) -> Self { |
654 | | libm_force::log10f(self) |
655 | | } |
656 | | |
657 | | #[inline] |
658 | | fn cbrt(self) -> Self { |
659 | | libm_force::cbrtf(self) |
660 | | } |
661 | | |
662 | | #[inline] |
663 | | fn hypot(self, other: Self) -> Self::RealField { |
664 | | libm_force::hypotf(self, other) |
665 | | } |
666 | | |
667 | | #[inline] |
668 | | fn sin(self) -> Self { |
669 | | libm_force::sinf(self) |
670 | | } |
671 | | |
672 | | #[inline] |
673 | | fn cos(self) -> Self { |
674 | | libm_force::cosf(self) |
675 | | } |
676 | | |
677 | | #[inline] |
678 | | fn tan(self) -> Self { |
679 | | libm_force::tanf(self) |
680 | | } |
681 | | |
682 | | #[inline] |
683 | | fn asin(self) -> Self { |
684 | | libm_force::asinf(self) |
685 | | } |
686 | | |
687 | | #[inline] |
688 | | fn acos(self) -> Self { |
689 | | libm_force::acosf(self) |
690 | | } |
691 | | |
692 | | #[inline] |
693 | | fn atan(self) -> Self { |
694 | | libm_force::atanf(self) |
695 | | } |
696 | | |
697 | | #[inline] |
698 | | fn sin_cos(self) -> (Self, Self) { |
699 | | libm_force::sincosf(self) |
700 | | } |
701 | | |
702 | | // #[inline] |
703 | | // fn exp_m1(self) -> Self { |
704 | | // libm_force::exp_m1(self) |
705 | | // } |
706 | | // |
707 | | // #[inline] |
708 | | // fn ln_1p(self) -> Self { |
709 | | // libm_force::ln_1p(self) |
710 | | // } |
711 | | // |
712 | | #[inline] |
713 | | fn sinh(self) -> Self { |
714 | | libm_force::sinhf(self) |
715 | | } |
716 | | |
717 | | #[inline] |
718 | | fn cosh(self) -> Self { |
719 | | libm_force::coshf(self) |
720 | | } |
721 | | |
722 | | #[inline] |
723 | | fn tanh(self) -> Self { |
724 | | libm_force::tanhf(self) |
725 | | } |
726 | | |
727 | | #[inline] |
728 | | fn asinh(self) -> Self { |
729 | | libm_force::asinhf(self) |
730 | | } |
731 | | |
732 | | #[inline] |
733 | | fn acosh(self) -> Self { |
734 | | libm_force::acoshf(self) |
735 | | } |
736 | | |
737 | | #[inline] |
738 | | fn atanh(self) -> Self { |
739 | | libm_force::atanhf(self) |
740 | | } |
741 | | |
742 | | #[inline] |
743 | | fn is_finite(&self) -> bool { |
744 | | f32::is_finite(*self) |
745 | | } |
746 | | } |
747 | | |
748 | | #[cfg(feature = "libm_force")] |
749 | | impl ComplexField for f64 { |
750 | | type RealField = f64; |
751 | | |
752 | | #[inline] |
753 | | fn from_real(re: Self::RealField) -> Self { |
754 | | re |
755 | | } |
756 | | |
757 | | #[inline] |
758 | | fn real(self) -> Self::RealField { |
759 | | self |
760 | | } |
761 | | |
762 | | #[inline] |
763 | | fn imaginary(self) -> Self::RealField { |
764 | | Self::zero() |
765 | | } |
766 | | |
767 | | #[inline] |
768 | | fn norm1(self) -> Self::RealField { |
769 | | libm_force::fabs(self) |
770 | | } |
771 | | |
772 | | #[inline] |
773 | | fn modulus(self) -> Self::RealField { |
774 | | libm_force::fabs(self) |
775 | | } |
776 | | |
777 | | #[inline] |
778 | | fn modulus_squared(self) -> Self::RealField { |
779 | | self * self |
780 | | } |
781 | | |
782 | | #[inline] |
783 | | fn argument(self) -> Self::RealField { |
784 | | if self >= Self::zero() { |
785 | | Self::zero() |
786 | | } else { |
787 | | Self::pi() |
788 | | } |
789 | | } |
790 | | |
791 | | #[inline] |
792 | | fn to_exp(self) -> (Self, Self) { |
793 | | if self >= Self::zero() { |
794 | | (self, Self::one()) |
795 | | } else { |
796 | | (-self, -Self::one()) |
797 | | } |
798 | | } |
799 | | |
800 | | #[inline] |
801 | | fn recip(self) -> Self { |
802 | | f64::recip(self) |
803 | | } |
804 | | |
805 | | #[inline] |
806 | | fn conjugate(self) -> Self { |
807 | | self |
808 | | } |
809 | | |
810 | | #[inline] |
811 | | fn scale(self, factor: Self::RealField) -> Self { |
812 | | self * factor |
813 | | } |
814 | | |
815 | | #[inline] |
816 | | fn unscale(self, factor: Self::RealField) -> Self { |
817 | | self / factor |
818 | | } |
819 | | |
820 | | #[inline] |
821 | | fn floor(self) -> Self { |
822 | | libm_force::floor(self) |
823 | | } |
824 | | |
825 | | #[inline] |
826 | | fn ceil(self) -> Self { |
827 | | libm_force::ceil(self) |
828 | | } |
829 | | |
830 | | #[inline] |
831 | | fn round(self) -> Self { |
832 | | libm_force::round(self) |
833 | | } |
834 | | |
835 | | #[inline] |
836 | | fn trunc(self) -> Self { |
837 | | libm_force::trunc(self) |
838 | | } |
839 | | |
840 | | #[inline] |
841 | | fn fract(self) -> Self { |
842 | | self - libm_force::trunc(self) |
843 | | } |
844 | | |
845 | | #[inline] |
846 | | fn abs(self) -> Self { |
847 | | libm_force::fabs(self) |
848 | | } |
849 | | |
850 | | #[inline] |
851 | | fn signum(self) -> Self { |
852 | | Signed::signum(&self) |
853 | | } |
854 | | |
855 | | #[inline] |
856 | | fn mul_add(self, a: Self, b: Self) -> Self { |
857 | | libm_force::fma(self, a, b) |
858 | | } |
859 | | |
860 | | #[inline] |
861 | | fn powi(self, n: i32) -> Self { |
862 | | // TODO: implement a more accurate solution? |
863 | | libm_force::pow(self, n as f64) |
864 | | } |
865 | | |
866 | | #[inline] |
867 | | fn powf(self, n: Self) -> Self { |
868 | | libm_force::pow(self, n) |
869 | | } |
870 | | |
871 | | #[inline] |
872 | | fn powc(self, n: Self) -> Self { |
873 | | // Same as powf. |
874 | | libm_force::pow(self, n) |
875 | | } |
876 | | |
877 | | #[inline] |
878 | | fn sqrt(self) -> Self { |
879 | | libm_force::sqrt(self) |
880 | | } |
881 | | |
882 | | #[inline] |
883 | | fn try_sqrt(self) -> Option<Self> { |
884 | | if self >= Self::zero() { |
885 | | Some(libm_force::sqrt(self)) |
886 | | } else { |
887 | | None |
888 | | } |
889 | | } |
890 | | |
891 | | #[inline] |
892 | | fn exp(self) -> Self { |
893 | | libm_force::exp(self) |
894 | | } |
895 | | |
896 | | #[inline] |
897 | | fn exp2(self) -> Self { |
898 | | libm_force::exp2(self) |
899 | | } |
900 | | |
901 | | #[inline] |
902 | | fn exp_m1(self) -> Self { |
903 | | libm_force::expm1(self) |
904 | | } |
905 | | |
906 | | #[inline] |
907 | | fn ln_1p(self) -> Self { |
908 | | libm_force::log1p(self) |
909 | | } |
910 | | |
911 | | #[inline] |
912 | | fn ln(self) -> Self { |
913 | | libm_force::log(self) |
914 | | } |
915 | | |
916 | | #[inline] |
917 | | fn log(self, base: Self) -> Self { |
918 | | libm_force::log(self) / libm_force::log(base) |
919 | | } |
920 | | |
921 | | #[inline] |
922 | | fn log2(self) -> Self { |
923 | | libm_force::log2(self) |
924 | | } |
925 | | |
926 | | #[inline] |
927 | | fn log10(self) -> Self { |
928 | | libm_force::log10(self) |
929 | | } |
930 | | |
931 | | #[inline] |
932 | | fn cbrt(self) -> Self { |
933 | | libm_force::cbrt(self) |
934 | | } |
935 | | |
936 | | #[inline] |
937 | | fn hypot(self, other: Self) -> Self::RealField { |
938 | | libm_force::hypot(self, other) |
939 | | } |
940 | | |
941 | | #[inline] |
942 | | fn sin(self) -> Self { |
943 | | libm_force::sin(self) |
944 | | } |
945 | | |
946 | | #[inline] |
947 | | fn cos(self) -> Self { |
948 | | libm_force::cos(self) |
949 | | } |
950 | | |
951 | | #[inline] |
952 | | fn tan(self) -> Self { |
953 | | libm_force::tan(self) |
954 | | } |
955 | | |
956 | | #[inline] |
957 | | fn asin(self) -> Self { |
958 | | libm_force::asin(self) |
959 | | } |
960 | | |
961 | | #[inline] |
962 | | fn acos(self) -> Self { |
963 | | libm_force::acos(self) |
964 | | } |
965 | | |
966 | | #[inline] |
967 | | fn atan(self) -> Self { |
968 | | libm_force::atan(self) |
969 | | } |
970 | | |
971 | | #[inline] |
972 | | fn sin_cos(self) -> (Self, Self) { |
973 | | libm_force::sincos(self) |
974 | | } |
975 | | |
976 | | // #[inline] |
977 | | // fn exp_m1(self) -> Self { |
978 | | // libm_force::exp_m1(self) |
979 | | // } |
980 | | // |
981 | | // #[inline] |
982 | | // fn ln_1p(self) -> Self { |
983 | | // libm_force::ln_1p(self) |
984 | | // } |
985 | | // |
986 | | #[inline] |
987 | | fn sinh(self) -> Self { |
988 | | libm_force::sinh(self) |
989 | | } |
990 | | |
991 | | #[inline] |
992 | | fn cosh(self) -> Self { |
993 | | libm_force::cosh(self) |
994 | | } |
995 | | |
996 | | #[inline] |
997 | | fn tanh(self) -> Self { |
998 | | libm_force::tanh(self) |
999 | | } |
1000 | | |
1001 | | #[inline] |
1002 | | fn asinh(self) -> Self { |
1003 | | libm_force::asinh(self) |
1004 | | } |
1005 | | |
1006 | | #[inline] |
1007 | | fn acosh(self) -> Self { |
1008 | | libm_force::acosh(self) |
1009 | | } |
1010 | | |
1011 | | #[inline] |
1012 | | fn atanh(self) -> Self { |
1013 | | libm_force::atanh(self) |
1014 | | } |
1015 | | |
1016 | | #[inline] |
1017 | | fn is_finite(&self) -> bool { |
1018 | | f64::is_finite(*self) |
1019 | | } |
1020 | | } |
1021 | | |
1022 | | //#[cfg(feature = "decimal")] |
1023 | | //impl_real!(d128, d128, d128); |
1024 | | |
1025 | | // NOTE: all those impls have been copied-pasted to `simd_impl.rs` to implement |
1026 | | // SimdComplexField for Complex. |
1027 | | impl<N: RealField + PartialOrd> ComplexField for num_complex::Complex<N> { |
1028 | | type RealField = N; |
1029 | | |
1030 | | #[inline] |
1031 | | fn from_real(re: Self::RealField) -> Self { |
1032 | | Self::new(re, Self::RealField::zero()) |
1033 | | } |
1034 | | |
1035 | | #[inline] |
1036 | | fn real(self) -> Self::RealField { |
1037 | | self.re |
1038 | | } |
1039 | | |
1040 | | #[inline] |
1041 | | fn imaginary(self) -> Self::RealField { |
1042 | | self.im |
1043 | | } |
1044 | | |
1045 | | #[inline] |
1046 | | fn argument(self) -> Self::RealField { |
1047 | | self.im.atan2(self.re) |
1048 | | } |
1049 | | |
1050 | | #[inline] |
1051 | | fn modulus(self) -> Self::RealField { |
1052 | | self.re.hypot(self.im) |
1053 | | } |
1054 | | |
1055 | | #[inline] |
1056 | | fn modulus_squared(self) -> Self::RealField { |
1057 | | self.re.clone() * self.re + self.im.clone() * self.im |
1058 | | } |
1059 | | |
1060 | | #[inline] |
1061 | | fn norm1(self) -> Self::RealField { |
1062 | | self.re.abs() + self.im.abs() |
1063 | | } |
1064 | | |
1065 | | #[inline] |
1066 | | fn recip(self) -> Self { |
1067 | | Self::one() / self |
1068 | | } |
1069 | | |
1070 | | #[inline] |
1071 | | fn conjugate(self) -> Self { |
1072 | | self.conj() |
1073 | | } |
1074 | | |
1075 | | #[inline] |
1076 | | fn scale(self, factor: Self::RealField) -> Self { |
1077 | | self * factor |
1078 | | } |
1079 | | |
1080 | | #[inline] |
1081 | | fn unscale(self, factor: Self::RealField) -> Self { |
1082 | | self / factor |
1083 | | } |
1084 | | |
1085 | | #[inline] |
1086 | | fn floor(self) -> Self { |
1087 | | Self::new(self.re.floor(), self.im.floor()) |
1088 | | } |
1089 | | |
1090 | | #[inline] |
1091 | | fn ceil(self) -> Self { |
1092 | | Self::new(self.re.ceil(), self.im.ceil()) |
1093 | | } |
1094 | | |
1095 | | #[inline] |
1096 | | fn round(self) -> Self { |
1097 | | Self::new(self.re.round(), self.im.round()) |
1098 | | } |
1099 | | |
1100 | | #[inline] |
1101 | | fn trunc(self) -> Self { |
1102 | | Self::new(self.re.trunc(), self.im.trunc()) |
1103 | | } |
1104 | | |
1105 | | #[inline] |
1106 | | fn fract(self) -> Self { |
1107 | | Self::new(self.re.fract(), self.im.fract()) |
1108 | | } |
1109 | | |
1110 | | #[inline] |
1111 | | fn mul_add(self, a: Self, b: Self) -> Self { |
1112 | | self * a + b |
1113 | | } |
1114 | | |
1115 | | #[inline] |
1116 | | fn abs(self) -> Self::RealField { |
1117 | | self.modulus() |
1118 | | } |
1119 | | |
1120 | | #[inline] |
1121 | | fn exp2(self) -> Self { |
1122 | | let _2 = N::one() + N::one(); |
1123 | | num_complex::Complex::new(_2, N::zero()).powc(self) |
1124 | | } |
1125 | | |
1126 | | #[inline] |
1127 | | fn exp_m1(self) -> Self { |
1128 | | self.exp() - Self::one() |
1129 | | } |
1130 | | |
1131 | | #[inline] |
1132 | | fn ln_1p(self) -> Self { |
1133 | | (Self::one() + self).ln() |
1134 | | } |
1135 | | |
1136 | | #[inline] |
1137 | | fn log2(self) -> Self { |
1138 | | let _2 = N::one() + N::one(); |
1139 | | self.log(_2) |
1140 | | } |
1141 | | |
1142 | | #[inline] |
1143 | | fn log10(self) -> Self { |
1144 | | let _10 = N::from_subset(&10.0f64); |
1145 | | self.log(_10) |
1146 | | } |
1147 | | |
1148 | | #[inline] |
1149 | | fn cbrt(self) -> Self { |
1150 | | let one_third = N::from_subset(&(1.0 / 3.0)); |
1151 | | self.powf(one_third) |
1152 | | } |
1153 | | |
1154 | | #[inline] |
1155 | | fn powi(self, n: i32) -> Self { |
1156 | | // TODO: is there a more accurate solution? |
1157 | | let n = N::from_subset(&(n as f64)); |
1158 | | self.powf(n) |
1159 | | } |
1160 | | |
1161 | | #[inline] |
1162 | | fn is_finite(&self) -> bool { |
1163 | | self.re.is_finite() && self.im.is_finite() |
1164 | | } |
1165 | | |
1166 | | /* |
1167 | | * |
1168 | | * |
1169 | | * Unfortunately we are forced to copy-paste all |
1170 | | * those impls from https://github.com/rust-num/num-complex/blob/master/src/lib.rs |
1171 | | * to avoid requiring `std`. |
1172 | | * |
1173 | | * |
1174 | | */ |
1175 | | /// Computes `e^(self)`, where `e` is the base of the natural logarithm. |
1176 | | #[inline] |
1177 | | fn exp(self) -> Self { |
1178 | | // formula: e^(a + bi) = e^a (cos(b) + i*sin(b)) |
1179 | | // = from_polar(e^a, b) |
1180 | | complex_from_polar(self.re.exp(), self.im) |
1181 | | } |
1182 | | |
1183 | | /// Computes the principal value of natural logarithm of `self`. |
1184 | | /// |
1185 | | /// This function has one branch cut: |
1186 | | /// |
1187 | | /// * `(-∞, 0]`, continuous from above. |
1188 | | /// |
1189 | | /// The branch satisfies `-π ≤ arg(ln(z)) ≤ π`. |
1190 | | #[inline] |
1191 | | fn ln(self) -> Self { |
1192 | | // formula: ln(z) = ln|z| + i*arg(z) |
1193 | | let (r, theta) = self.to_polar(); |
1194 | | Self::new(r.ln(), theta) |
1195 | | } |
1196 | | |
1197 | | /// Computes the principal value of the square root of `self`. |
1198 | | /// |
1199 | | /// This function has one branch cut: |
1200 | | /// |
1201 | | /// * `(-∞, 0)`, continuous from above. |
1202 | | /// |
1203 | | /// The branch satisfies `-π/2 ≤ arg(sqrt(z)) ≤ π/2`. |
1204 | | #[inline] |
1205 | | fn sqrt(self) -> Self { |
1206 | | // formula: sqrt(r e^(it)) = sqrt(r) e^(it/2) |
1207 | | let two = N::one() + N::one(); |
1208 | | let (r, theta) = self.to_polar(); |
1209 | | complex_from_polar(r.sqrt(), theta / two) |
1210 | | } |
1211 | | |
1212 | | #[inline] |
1213 | | fn try_sqrt(self) -> Option<Self> { |
1214 | | Some(self.sqrt()) |
1215 | | } |
1216 | | |
1217 | | #[inline] |
1218 | | fn hypot(self, b: Self) -> Self::RealField { |
1219 | | (self.modulus_squared() + b.modulus_squared()).sqrt() |
1220 | | } |
1221 | | |
1222 | | /// Raises `self` to a floating point power. |
1223 | | #[inline] |
1224 | | fn powf(self, exp: Self::RealField) -> Self { |
1225 | | // formula: x^y = (ρ e^(i θ))^y = ρ^y e^(i θ y) |
1226 | | // = from_polar(ρ^y, θ y) |
1227 | | let (r, theta) = self.to_polar(); |
1228 | | complex_from_polar(r.powf(exp.clone()), theta * exp) |
1229 | | } |
1230 | | |
1231 | | /// Returns the logarithm of `self` with respect to an arbitrary base. |
1232 | | #[inline] |
1233 | | fn log(self, base: N) -> Self { |
1234 | | // formula: log_y(x) = log_y(ρ e^(i θ)) |
1235 | | // = log_y(ρ) + log_y(e^(i θ)) = log_y(ρ) + ln(e^(i θ)) / ln(y) |
1236 | | // = log_y(ρ) + i θ / ln(y) |
1237 | | let (r, theta) = self.to_polar(); |
1238 | | Self::new(r.log(base.clone()), theta / base.ln()) |
1239 | | } |
1240 | | |
1241 | | /// Raises `self` to a complex power. |
1242 | | #[inline] |
1243 | | fn powc(self, exp: Self) -> Self { |
1244 | | // formula: x^y = (a + i b)^(c + i d) |
1245 | | // = (ρ e^(i θ))^c (ρ e^(i θ))^(i d) |
1246 | | // where ρ=|x| and θ=arg(x) |
1247 | | // = ρ^c e^(−d θ) e^(i c θ) ρ^(i d) |
1248 | | // = p^c e^(−d θ) (cos(c θ) |
1249 | | // + i sin(c θ)) (cos(d ln(ρ)) + i sin(d ln(ρ))) |
1250 | | // = p^c e^(−d θ) ( |
1251 | | // cos(c θ) cos(d ln(ρ)) − sin(c θ) sin(d ln(ρ)) |
1252 | | // + i(cos(c θ) sin(d ln(ρ)) + sin(c θ) cos(d ln(ρ)))) |
1253 | | // = p^c e^(−d θ) (cos(c θ + d ln(ρ)) + i sin(c θ + d ln(ρ))) |
1254 | | // = from_polar(p^c e^(−d θ), c θ + d ln(ρ)) |
1255 | | let (r, theta) = self.to_polar(); |
1256 | | complex_from_polar( |
1257 | | r.clone().powf(exp.re.clone()) * (-exp.im.clone() * theta.clone()).exp(), |
1258 | | exp.re * theta + exp.im * r.ln(), |
1259 | | ) |
1260 | | } |
1261 | | |
1262 | | /* |
1263 | | /// Raises a floating point number to the complex power `self`. |
1264 | | #[inline] |
1265 | | fn expf(&self, base: T) -> Self { |
1266 | | // formula: x^(a+bi) = x^a x^bi = x^a e^(b ln(x) i) |
1267 | | // = from_polar(x^a, b ln(x)) |
1268 | | Self::from_polar(&base.powf(self.re), &(self.im * base.ln())) |
1269 | | } |
1270 | | */ |
1271 | | |
1272 | | /// Computes the sine of `self`. |
1273 | | #[inline] |
1274 | | fn sin(self) -> Self { |
1275 | | // formula: sin(a + bi) = sin(a)cosh(b) + i*cos(a)sinh(b) |
1276 | | Self::new( |
1277 | | self.re.clone().sin() * self.im.clone().cosh(), |
1278 | | self.re.cos() * self.im.sinh(), |
1279 | | ) |
1280 | | } |
1281 | | |
1282 | | /// Computes the cosine of `self`. |
1283 | | #[inline] |
1284 | | fn cos(self) -> Self { |
1285 | | // formula: cos(a + bi) = cos(a)cosh(b) - i*sin(a)sinh(b) |
1286 | | Self::new( |
1287 | | self.re.clone().cos() * self.im.clone().cosh(), |
1288 | | -self.re.sin() * self.im.sinh(), |
1289 | | ) |
1290 | | } |
1291 | | |
1292 | | #[inline] |
1293 | | fn sin_cos(self) -> (Self, Self) { |
1294 | | let (rsin, rcos) = self.re.sin_cos(); |
1295 | | let (isinh, icosh) = self.im.sinh_cosh(); |
1296 | | let sin = Self::new(rsin.clone() * icosh.clone(), rcos.clone() * isinh.clone()); |
1297 | | let cos = Self::new(rcos * icosh, -rsin * isinh); |
1298 | | |
1299 | | (sin, cos) |
1300 | | } |
1301 | | |
1302 | | /// Computes the tangent of `self`. |
1303 | | #[inline] |
1304 | | fn tan(self) -> Self { |
1305 | | // formula: tan(a + bi) = (sin(2a) + i*sinh(2b))/(cos(2a) + cosh(2b)) |
1306 | | let (two_re, two_im) = (self.re.clone() + self.re, self.im.clone() + self.im); |
1307 | | Self::new(two_re.clone().sin(), two_im.clone().sinh()).unscale(two_re.cos() + two_im.cosh()) |
1308 | | } |
1309 | | |
1310 | | /// Computes the principal value of the inverse sine of `self`. |
1311 | | /// |
1312 | | /// This function has two branch cuts: |
1313 | | /// |
1314 | | /// * `(-∞, -1)`, continuous from above. |
1315 | | /// * `(1, ∞)`, continuous from below. |
1316 | | /// |
1317 | | /// The branch satisfies `-π/2 ≤ Re(asin(z)) ≤ π/2`. |
1318 | | #[inline] |
1319 | | fn asin(self) -> Self { |
1320 | | // formula: arcsin(z) = -i ln(sqrt(1-z^2) + iz) |
1321 | | let i = Self::i(); |
1322 | | -i.clone() * ((Self::one() - self.clone() * self.clone()).sqrt() + i * self).ln() |
1323 | | } |
1324 | | |
1325 | | /// Computes the principal value of the inverse cosine of `self`. |
1326 | | /// |
1327 | | /// This function has two branch cuts: |
1328 | | /// |
1329 | | /// * `(-∞, -1)`, continuous from above. |
1330 | | /// * `(1, ∞)`, continuous from below. |
1331 | | /// |
1332 | | /// The branch satisfies `0 ≤ Re(acos(z)) ≤ π`. |
1333 | | #[inline] |
1334 | | fn acos(self) -> Self { |
1335 | | // formula: arccos(z) = -i ln(i sqrt(1-z^2) + z) |
1336 | | let i = Self::i(); |
1337 | | -i.clone() * (i * (Self::one() - self.clone() * self.clone()).sqrt() + self).ln() |
1338 | | } |
1339 | | |
1340 | | /// Computes the principal value of the inverse tangent of `self`. |
1341 | | /// |
1342 | | /// This function has two branch cuts: |
1343 | | /// |
1344 | | /// * `(-∞i, -i]`, continuous from the left. |
1345 | | /// * `[i, ∞i)`, continuous from the right. |
1346 | | /// |
1347 | | /// The branch satisfies `-π/2 ≤ Re(atan(z)) ≤ π/2`. |
1348 | | #[inline] |
1349 | | fn atan(self) -> Self { |
1350 | | // formula: arctan(z) = (ln(1+iz) - ln(1-iz))/(2i) |
1351 | | let i = Self::i(); |
1352 | | let one = Self::one(); |
1353 | | let two = one.clone() + one.clone(); |
1354 | | |
1355 | | if self == i { |
1356 | | return Self::new(N::zero(), N::one() / N::zero()); |
1357 | | } else if self == -i.clone() { |
1358 | | return Self::new(N::zero(), -N::one() / N::zero()); |
1359 | | } |
1360 | | |
1361 | | ((one.clone() + i.clone() * self.clone()).ln() - (one - i.clone() * self).ln()) / (two * i) |
1362 | | } |
1363 | | |
1364 | | /// Computes the hyperbolic sine of `self`. |
1365 | | #[inline] |
1366 | | fn sinh(self) -> Self { |
1367 | | // formula: sinh(a + bi) = sinh(a)cos(b) + i*cosh(a)sin(b) |
1368 | | Self::new( |
1369 | | self.re.clone().sinh() * self.im.clone().cos(), |
1370 | | self.re.cosh() * self.im.sin(), |
1371 | | ) |
1372 | | } |
1373 | | |
1374 | | /// Computes the hyperbolic cosine of `self`. |
1375 | | #[inline] |
1376 | | fn cosh(self) -> Self { |
1377 | | // formula: cosh(a + bi) = cosh(a)cos(b) + i*sinh(a)sin(b) |
1378 | | Self::new( |
1379 | | self.re.clone().cosh() * self.im.clone().cos(), |
1380 | | self.re.sinh() * self.im.sin(), |
1381 | | ) |
1382 | | } |
1383 | | |
1384 | | #[inline] |
1385 | | fn sinh_cosh(self) -> (Self, Self) { |
1386 | | let (rsinh, rcosh) = self.re.sinh_cosh(); |
1387 | | let (isin, icos) = self.im.sin_cos(); |
1388 | | let sin = Self::new(rsinh.clone() * icos.clone(), rcosh.clone() * isin.clone()); |
1389 | | let cos = Self::new(rcosh * icos, rsinh * isin); |
1390 | | |
1391 | | (sin, cos) |
1392 | | } |
1393 | | |
1394 | | /// Computes the hyperbolic tangent of `self`. |
1395 | | #[inline] |
1396 | | fn tanh(self) -> Self { |
1397 | | // formula: tanh(a + bi) = (sinh(2a) + i*sin(2b))/(cosh(2a) + cos(2b)) |
1398 | | let (two_re, two_im) = (self.re.clone() + self.re, self.im.clone() + self.im); |
1399 | | Self::new(two_re.clone().sinh(), two_im.clone().sin()).unscale(two_re.cosh() + two_im.cos()) |
1400 | | } |
1401 | | |
1402 | | /// Computes the principal value of inverse hyperbolic sine of `self`. |
1403 | | /// |
1404 | | /// This function has two branch cuts: |
1405 | | /// |
1406 | | /// * `(-∞i, -i)`, continuous from the left. |
1407 | | /// * `(i, ∞i)`, continuous from the right. |
1408 | | /// |
1409 | | /// The branch satisfies `-π/2 ≤ Im(asinh(z)) ≤ π/2`. |
1410 | | #[inline] |
1411 | | fn asinh(self) -> Self { |
1412 | | // formula: arcsinh(z) = ln(z + sqrt(1+z^2)) |
1413 | | let one = Self::one(); |
1414 | | (self.clone() + (one + self.clone() * self).sqrt()).ln() |
1415 | | } |
1416 | | |
1417 | | /// Computes the principal value of inverse hyperbolic cosine of `self`. |
1418 | | /// |
1419 | | /// This function has one branch cut: |
1420 | | /// |
1421 | | /// * `(-∞, 1)`, continuous from above. |
1422 | | /// |
1423 | | /// The branch satisfies `-π ≤ Im(acosh(z)) ≤ π` and `0 ≤ Re(acosh(z)) < ∞`. |
1424 | | #[inline] |
1425 | | fn acosh(self) -> Self { |
1426 | | // formula: arccosh(z) = 2 ln(sqrt((z+1)/2) + sqrt((z-1)/2)) |
1427 | | let one = Self::one(); |
1428 | | let two = one.clone() + one.clone(); |
1429 | | two.clone() |
1430 | | * (((self.clone() + one.clone()) / two.clone()).sqrt() + ((self - one) / two).sqrt()) |
1431 | | .ln() |
1432 | | } |
1433 | | |
1434 | | /// Computes the principal value of inverse hyperbolic tangent of `self`. |
1435 | | /// |
1436 | | /// This function has two branch cuts: |
1437 | | /// |
1438 | | /// * `(-∞, -1]`, continuous from above. |
1439 | | /// * `[1, ∞)`, continuous from below. |
1440 | | /// |
1441 | | /// The branch satisfies `-π/2 ≤ Im(atanh(z)) ≤ π/2`. |
1442 | | #[inline] |
1443 | | fn atanh(self) -> Self { |
1444 | | // formula: arctanh(z) = (ln(1+z) - ln(1-z))/2 |
1445 | | let one = Self::one(); |
1446 | | let two = one.clone() + one.clone(); |
1447 | | if self == one { |
1448 | | return Self::new(N::one() / N::zero(), N::zero()); |
1449 | | } else if self == -one.clone() { |
1450 | | return Self::new(-N::one() / N::zero(), N::zero()); |
1451 | | } |
1452 | | ((one.clone() + self.clone()).ln() - (one - self).ln()) / two |
1453 | | } |
1454 | | } |
1455 | | |
1456 | | #[inline] |
1457 | | fn complex_from_polar<N: RealField>(r: N, theta: N) -> num_complex::Complex<N> { |
1458 | | num_complex::Complex::new(r.clone() * theta.clone().cos(), r * theta.sin()) |
1459 | | } |