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