1 // Keeps us from accidentally creating a recursive impl rather than a real one.
2 #![deny(unconditional_recursion)]
3 
4 use core::ops::Neg;
5 
6 use num_traits::{Float, FloatConst, Num, NumCast};
7 
8 use crate::Complex;
9 
10 mod private {
11     use num_traits::{Float, FloatConst};
12 
13     use crate::Complex;
14 
15     pub trait Seal {}
16 
17     impl<T> Seal for T where T: Float + FloatConst {}
18     impl<T: Float + FloatConst> Seal for Complex<T> {}
19 }
20 
21 /// Generic trait for floating point complex numbers.
22 ///
23 /// This trait defines methods which are common to complex floating point
24 /// numbers and regular floating point numbers.
25 ///
26 /// This trait is sealed to prevent it from being implemented by anything other
27 /// than floating point scalars and [Complex] floats.
28 pub trait ComplexFloat: Num + NumCast + Copy + Neg<Output = Self> + private::Seal {
29     /// The type used to represent the real coefficients of this complex number.
30     type Real: Float + FloatConst;
31 
32     /// Returns `true` if this value is `NaN` and false otherwise.
is_nan(self) -> bool33     fn is_nan(self) -> bool;
34 
35     /// Returns `true` if this value is positive infinity or negative infinity and
36     /// false otherwise.
is_infinite(self) -> bool37     fn is_infinite(self) -> bool;
38 
39     /// Returns `true` if this number is neither infinite nor `NaN`.
is_finite(self) -> bool40     fn is_finite(self) -> bool;
41 
42     /// Returns `true` if the number is neither zero, infinite,
43     /// [subnormal](http://en.wikipedia.org/wiki/Denormal_number), or `NaN`.
is_normal(self) -> bool44     fn is_normal(self) -> bool;
45 
46     /// Take the reciprocal (inverse) of a number, `1/x`. See also [Complex::finv].
recip(self) -> Self47     fn recip(self) -> Self;
48 
49     /// Raises `self` to a signed integer power.
powi(self, exp: i32) -> Self50     fn powi(self, exp: i32) -> Self;
51 
52     /// Raises `self` to a real power.
powf(self, exp: Self::Real) -> Self53     fn powf(self, exp: Self::Real) -> Self;
54 
55     /// Raises `self` to a complex power.
powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real>56     fn powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real>;
57 
58     /// Take the square root of a number.
sqrt(self) -> Self59     fn sqrt(self) -> Self;
60 
61     /// Returns `e^(self)`, (the exponential function).
exp(self) -> Self62     fn exp(self) -> Self;
63 
64     /// Returns `2^(self)`.
exp2(self) -> Self65     fn exp2(self) -> Self;
66 
67     /// Returns `base^(self)`.
expf(self, base: Self::Real) -> Self68     fn expf(self, base: Self::Real) -> Self;
69 
70     /// Returns the natural logarithm of the number.
ln(self) -> Self71     fn ln(self) -> Self;
72 
73     /// Returns the logarithm of the number with respect to an arbitrary base.
log(self, base: Self::Real) -> Self74     fn log(self, base: Self::Real) -> Self;
75 
76     /// Returns the base 2 logarithm of the number.
log2(self) -> Self77     fn log2(self) -> Self;
78 
79     /// Returns the base 10 logarithm of the number.
log10(self) -> Self80     fn log10(self) -> Self;
81 
82     /// Take the cubic root of a number.
cbrt(self) -> Self83     fn cbrt(self) -> Self;
84 
85     /// Computes the sine of a number (in radians).
sin(self) -> Self86     fn sin(self) -> Self;
87 
88     /// Computes the cosine of a number (in radians).
cos(self) -> Self89     fn cos(self) -> Self;
90 
91     /// Computes the tangent of a number (in radians).
tan(self) -> Self92     fn tan(self) -> Self;
93 
94     /// Computes the arcsine of a number. Return value is in radians in
95     /// the range [-pi/2, pi/2] or NaN if the number is outside the range
96     /// [-1, 1].
asin(self) -> Self97     fn asin(self) -> Self;
98 
99     /// Computes the arccosine of a number. Return value is in radians in
100     /// the range [0, pi] or NaN if the number is outside the range
101     /// [-1, 1].
acos(self) -> Self102     fn acos(self) -> Self;
103 
104     /// Computes the arctangent of a number. Return value is in radians in the
105     /// range [-pi/2, pi/2];
atan(self) -> Self106     fn atan(self) -> Self;
107 
108     /// Hyperbolic sine function.
sinh(self) -> Self109     fn sinh(self) -> Self;
110 
111     /// Hyperbolic cosine function.
cosh(self) -> Self112     fn cosh(self) -> Self;
113 
114     /// Hyperbolic tangent function.
tanh(self) -> Self115     fn tanh(self) -> Self;
116 
117     /// Inverse hyperbolic sine function.
asinh(self) -> Self118     fn asinh(self) -> Self;
119 
120     /// Inverse hyperbolic cosine function.
acosh(self) -> Self121     fn acosh(self) -> Self;
122 
123     /// Inverse hyperbolic tangent function.
atanh(self) -> Self124     fn atanh(self) -> Self;
125 
126     /// Returns the real part of the number.
re(self) -> Self::Real127     fn re(self) -> Self::Real;
128 
129     /// Returns the imaginary part of the number.
im(self) -> Self::Real130     fn im(self) -> Self::Real;
131 
132     /// Returns the absolute value of the number. See also [Complex::norm]
abs(self) -> Self::Real133     fn abs(self) -> Self::Real;
134 
135     /// Returns the L1 norm `|re| + |im|` -- the [Manhattan distance] from the origin.
136     ///
137     /// [Manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry
l1_norm(&self) -> Self::Real138     fn l1_norm(&self) -> Self::Real;
139 
140     /// Computes the argument of the number.
arg(self) -> Self::Real141     fn arg(self) -> Self::Real;
142 
143     /// Computes the complex conjugate of the number.
144     ///
145     /// Formula: `a+bi -> a-bi`
conj(self) -> Self146     fn conj(self) -> Self;
147 }
148 
149 macro_rules! forward {
150     ($( $base:ident :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
151         => {$(
152             #[inline]
153             fn $method(self $( , $arg : $ty )* ) -> $ret {
154                 $base::$method(self $( , $arg )* )
155             }
156         )*};
157 }
158 
159 macro_rules! forward_ref {
160     ($( Self :: $method:ident ( & self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
161         => {$(
162             #[inline]
163             fn $method(self $( , $arg : $ty )* ) -> $ret {
164                 Self::$method(&self $( , $arg )* )
165             }
166         )*};
167 }
168 
169 impl<T> ComplexFloat for T
170 where
171     T: Float + FloatConst,
172 {
173     type Real = T;
174 
re(self) -> Self::Real175     fn re(self) -> Self::Real {
176         self
177     }
178 
im(self) -> Self::Real179     fn im(self) -> Self::Real {
180         T::zero()
181     }
182 
l1_norm(&self) -> Self::Real183     fn l1_norm(&self) -> Self::Real {
184         self.abs()
185     }
186 
arg(self) -> Self::Real187     fn arg(self) -> Self::Real {
188         if self.is_nan() {
189             self
190         } else if self.is_sign_negative() {
191             T::PI()
192         } else {
193             T::zero()
194         }
195     }
196 
powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real>197     fn powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real> {
198         Complex::new(self, T::zero()).powc(exp)
199     }
200 
conj(self) -> Self201     fn conj(self) -> Self {
202         self
203     }
204 
expf(self, base: Self::Real) -> Self205     fn expf(self, base: Self::Real) -> Self {
206         base.powf(self)
207     }
208 
209     forward! {
210         Float::is_normal(self) -> bool;
211         Float::is_infinite(self) -> bool;
212         Float::is_finite(self) -> bool;
213         Float::is_nan(self) -> bool;
214         Float::recip(self) -> Self;
215         Float::powi(self, n: i32) -> Self;
216         Float::powf(self, f: Self) -> Self;
217         Float::sqrt(self) -> Self;
218         Float::cbrt(self) -> Self;
219         Float::exp(self) -> Self;
220         Float::exp2(self) -> Self;
221         Float::ln(self) -> Self;
222         Float::log(self, base: Self) -> Self;
223         Float::log2(self) -> Self;
224         Float::log10(self) -> Self;
225         Float::sin(self) -> Self;
226         Float::cos(self) -> Self;
227         Float::tan(self) -> Self;
228         Float::asin(self) -> Self;
229         Float::acos(self) -> Self;
230         Float::atan(self) -> Self;
231         Float::sinh(self) -> Self;
232         Float::cosh(self) -> Self;
233         Float::tanh(self) -> Self;
234         Float::asinh(self) -> Self;
235         Float::acosh(self) -> Self;
236         Float::atanh(self) -> Self;
237         Float::abs(self) -> Self;
238     }
239 }
240 
241 impl<T: Float + FloatConst> ComplexFloat for Complex<T> {
242     type Real = T;
243 
re(self) -> Self::Real244     fn re(self) -> Self::Real {
245         self.re
246     }
247 
im(self) -> Self::Real248     fn im(self) -> Self::Real {
249         self.im
250     }
251 
abs(self) -> Self::Real252     fn abs(self) -> Self::Real {
253         self.norm()
254     }
255 
recip(self) -> Self256     fn recip(self) -> Self {
257         self.finv()
258     }
259 
260     // `Complex::l1_norm` uses `Signed::abs` to let it work
261     // for integers too, but we can just use `Float::abs`.
l1_norm(&self) -> Self::Real262     fn l1_norm(&self) -> Self::Real {
263         self.re.abs() + self.im.abs()
264     }
265 
266     // `Complex::is_*` methods use `T: FloatCore`, but we
267     // have `T: Float` that can do them as well.
is_nan(self) -> bool268     fn is_nan(self) -> bool {
269         self.re.is_nan() || self.im.is_nan()
270     }
271 
is_infinite(self) -> bool272     fn is_infinite(self) -> bool {
273         !self.is_nan() && (self.re.is_infinite() || self.im.is_infinite())
274     }
275 
is_finite(self) -> bool276     fn is_finite(self) -> bool {
277         self.re.is_finite() && self.im.is_finite()
278     }
279 
is_normal(self) -> bool280     fn is_normal(self) -> bool {
281         self.re.is_normal() && self.im.is_normal()
282     }
283 
284     forward! {
285         Complex::arg(self) -> Self::Real;
286         Complex::powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real>;
287         Complex::exp2(self) -> Self;
288         Complex::log(self, base: Self::Real) -> Self;
289         Complex::log2(self) -> Self;
290         Complex::log10(self) -> Self;
291         Complex::powf(self, f: Self::Real) -> Self;
292         Complex::sqrt(self) -> Self;
293         Complex::cbrt(self) -> Self;
294         Complex::exp(self) -> Self;
295         Complex::expf(self, base: Self::Real) -> Self;
296         Complex::ln(self) -> Self;
297         Complex::sin(self) -> Self;
298         Complex::cos(self) -> Self;
299         Complex::tan(self) -> Self;
300         Complex::asin(self) -> Self;
301         Complex::acos(self) -> Self;
302         Complex::atan(self) -> Self;
303         Complex::sinh(self) -> Self;
304         Complex::cosh(self) -> Self;
305         Complex::tanh(self) -> Self;
306         Complex::asinh(self) -> Self;
307         Complex::acosh(self) -> Self;
308         Complex::atanh(self) -> Self;
309     }
310 
311     forward_ref! {
312         Self::powi(&self, n: i32) -> Self;
313         Self::conj(&self) -> Self;
314     }
315 }
316 
317 #[cfg(test)]
318 mod test {
319     use crate::{
320         complex_float::ComplexFloat,
321         test::{_0_0i, _0_1i, _1_0i, _1_1i, float::close},
322         Complex,
323     };
324     use std::f64; // for constants before Rust 1.43.
325 
closef(a: f64, b: f64) -> bool326     fn closef(a: f64, b: f64) -> bool {
327         close_to_tolf(a, b, 1e-10)
328     }
329 
close_to_tolf(a: f64, b: f64, tol: f64) -> bool330     fn close_to_tolf(a: f64, b: f64, tol: f64) -> bool {
331         // returns true if a and b are reasonably close
332         let close = (a == b) || (a - b).abs() < tol;
333         if !close {
334             println!("{:?} != {:?}", a, b);
335         }
336         close
337     }
338 
339     #[test]
test_exp2()340     fn test_exp2() {
341         assert!(close(ComplexFloat::exp2(_0_0i), _1_0i));
342         assert!(closef(<f64 as ComplexFloat>::exp2(0.), 1.));
343     }
344 
345     #[test]
test_exp()346     fn test_exp() {
347         assert!(close(ComplexFloat::exp(_0_0i), _1_0i));
348         assert!(closef(ComplexFloat::exp(0.), 1.));
349     }
350 
351     #[test]
test_powi()352     fn test_powi() {
353         assert!(close(ComplexFloat::powi(_0_1i, 4), _1_0i));
354         assert!(closef(ComplexFloat::powi(-1., 4), 1.));
355     }
356 
357     #[test]
test_powz()358     fn test_powz() {
359         assert!(close(ComplexFloat::powc(_1_0i, _0_1i), _1_0i));
360         assert!(close(ComplexFloat::powc(1., _0_1i), _1_0i));
361     }
362 
363     #[test]
test_log2()364     fn test_log2() {
365         assert!(close(ComplexFloat::log2(_1_0i), _0_0i));
366         assert!(closef(ComplexFloat::log2(1.), 0.));
367     }
368 
369     #[test]
test_log10()370     fn test_log10() {
371         assert!(close(ComplexFloat::log10(_1_0i), _0_0i));
372         assert!(closef(ComplexFloat::log10(1.), 0.));
373     }
374 
375     #[test]
test_conj()376     fn test_conj() {
377         assert_eq!(ComplexFloat::conj(_0_1i), Complex::new(0., -1.));
378         assert_eq!(ComplexFloat::conj(1.), 1.);
379     }
380 
381     #[test]
test_is_nan()382     fn test_is_nan() {
383         assert!(!ComplexFloat::is_nan(_1_0i));
384         assert!(!ComplexFloat::is_nan(1.));
385 
386         assert!(ComplexFloat::is_nan(Complex::new(f64::NAN, f64::NAN)));
387         assert!(ComplexFloat::is_nan(f64::NAN));
388     }
389 
390     #[test]
test_is_infinite()391     fn test_is_infinite() {
392         assert!(!ComplexFloat::is_infinite(_1_0i));
393         assert!(!ComplexFloat::is_infinite(1.));
394 
395         assert!(ComplexFloat::is_infinite(Complex::new(
396             f64::INFINITY,
397             f64::INFINITY
398         )));
399         assert!(ComplexFloat::is_infinite(f64::INFINITY));
400     }
401 
402     #[test]
test_is_finite()403     fn test_is_finite() {
404         assert!(ComplexFloat::is_finite(_1_0i));
405         assert!(ComplexFloat::is_finite(1.));
406 
407         assert!(!ComplexFloat::is_finite(Complex::new(
408             f64::INFINITY,
409             f64::INFINITY
410         )));
411         assert!(!ComplexFloat::is_finite(f64::INFINITY));
412     }
413 
414     #[test]
test_is_normal()415     fn test_is_normal() {
416         assert!(ComplexFloat::is_normal(_1_1i));
417         assert!(ComplexFloat::is_normal(1.));
418 
419         assert!(!ComplexFloat::is_normal(Complex::new(
420             f64::INFINITY,
421             f64::INFINITY
422         )));
423         assert!(!ComplexFloat::is_normal(f64::INFINITY));
424     }
425 
426     #[test]
test_arg()427     fn test_arg() {
428         assert!(closef(
429             ComplexFloat::arg(_0_1i),
430             core::f64::consts::FRAC_PI_2
431         ));
432 
433         assert!(closef(ComplexFloat::arg(-1.), core::f64::consts::PI));
434         assert!(closef(ComplexFloat::arg(-0.), core::f64::consts::PI));
435         assert!(closef(ComplexFloat::arg(0.), 0.));
436         assert!(closef(ComplexFloat::arg(1.), 0.));
437         assert!(ComplexFloat::arg(f64::NAN).is_nan());
438     }
439 }
440