diff options
| author | Brendan Zabarauskas <bjzaba@yahoo.com.au> | 2013-05-14 00:11:35 +1000 |
|---|---|---|
| committer | Brendan Zabarauskas <bjzaba@yahoo.com.au> | 2013-05-14 00:11:35 +1000 |
| commit | 8d4d2b00c551301348cc09583498c02fdfbd64d7 (patch) | |
| tree | b777a98cf8160baaa1a40378cda922afe447f191 | |
| parent | 830b945a9db072b68970b6f83dfafc1aaff8f837 (diff) | |
| download | rust-8d4d2b00c551301348cc09583498c02fdfbd64d7.tar.gz rust-8d4d2b00c551301348cc09583498c02fdfbd64d7.zip | |
Add inverse hyperbolic functions
| -rw-r--r-- | src/libcore/num/f32.rs | 89 | ||||
| -rw-r--r-- | src/libcore/num/f64.rs | 89 | ||||
| -rw-r--r-- | src/libcore/num/float.rs | 82 | ||||
| -rw-r--r-- | src/libcore/num/num.rs | 3 |
4 files changed, 263 insertions, 0 deletions
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index a872a6388ba..ec901d9e5f0 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -450,6 +450,58 @@ impl Hyperbolic for f32 { #[inline(always)] fn tanh(&self) -> f32 { tanh(*self) } + + /// + /// Inverse hyperbolic sine + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic sine of `self` will be returned + /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` + /// - `NaN` if `self` is `NaN` + /// + #[inline(always)] + fn asinh(&self) -> f32 { + match *self { + infinity => infinity, + neg_infinity => neg_infinity, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// + /// Inverse hyperbolic cosine + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic cosine of `self` will be returned + /// - `infinity` if `self` is `infinity` + /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) + /// + #[inline(always)] + fn acosh(&self) -> f32 { + match *self { + x if x < 1.0 => Float::NaN(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// + /// Inverse hyperbolic tangent + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic tangent of `self` will be returned + /// - `self` if `self` is `0.0` or `-0.0` + /// - `infinity` if `self` is `1.0` + /// - `neg_infinity` if `self` is `-1.0` + /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` + /// (including `infinity` and `neg_infinity`) + /// + #[inline(always)] + fn atanh(&self) -> f32 { + 0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p() + } } impl Real for f32 { @@ -973,6 +1025,43 @@ mod tests { } #[test] + fn test_asinh() { + assert_eq!(0.0f32.asinh(), 0.0f32); + assert_eq!((-0.0f32).asinh(), -0.0f32); + assert_eq!(Float::infinity::<f32>().asinh(), Float::infinity::<f32>()); + assert_eq!(Float::neg_infinity::<f32>().asinh(), Float::neg_infinity::<f32>()); + assert!(Float::NaN::<f32>().asinh().is_NaN()); + assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); + assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32); + } + + #[test] + fn test_acosh() { + assert_eq!(1.0f32.acosh(), 0.0f32); + assert!(0.999f32.acosh().is_NaN()); + assert_eq!(Float::infinity::<f32>().acosh(), Float::infinity::<f32>()); + assert!(Float::neg_infinity::<f32>().acosh().is_NaN()); + assert!(Float::NaN::<f32>().acosh().is_NaN()); + assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32); + assert_approx_eq!(3.0f32.acosh(), 1.76274717403908605046521864995958461f32); + } + + #[test] + fn test_atanh() { + assert_eq!(0.0f32.atanh(), 0.0f32); + assert_eq!((-0.0f32).atanh(), -0.0f32); + assert_eq!(1.0f32.atanh(), Float::infinity::<f32>()); + assert_eq!((-1.0f32).atanh(), Float::neg_infinity::<f32>()); + assert!(2f64.atanh().atanh().is_NaN()); + assert!((-2f64).atanh().atanh().is_NaN()); + assert!(Float::infinity::<f64>().atanh().is_NaN()); + assert!(Float::neg_infinity::<f64>().atanh().is_NaN()); + assert!(Float::NaN::<f32>().atanh().is_NaN()); + assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32); + assert_approx_eq!((-0.5f32).atanh(), -0.54930614433405484569762261846126285f32); + } + + #[test] fn test_real_consts() { assert_approx_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>()); assert_approx_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 8a17ae91934..acdec7dd368 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -463,6 +463,58 @@ impl Hyperbolic for f64 { #[inline(always)] fn tanh(&self) -> f64 { tanh(*self) } + + /// + /// Inverse hyperbolic sine + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic sine of `self` will be returned + /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` + /// - `NaN` if `self` is `NaN` + /// + #[inline(always)] + fn asinh(&self) -> f64 { + match *self { + infinity => infinity, + neg_infinity => neg_infinity, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// + /// Inverse hyperbolic cosine + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic cosine of `self` will be returned + /// - `infinity` if `self` is `infinity` + /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) + /// + #[inline(always)] + fn acosh(&self) -> f64 { + match *self { + x if x < 1.0 => Float::NaN(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// + /// Inverse hyperbolic tangent + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic tangent of `self` will be returned + /// - `self` if `self` is `0.0` or `-0.0` + /// - `infinity` if `self` is `1.0` + /// - `neg_infinity` if `self` is `-1.0` + /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` + /// (including `infinity` and `neg_infinity`) + /// + #[inline(always)] + fn atanh(&self) -> f64 { + 0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p() + } } impl Real for f64 { @@ -1020,6 +1072,43 @@ mod tests { } #[test] + fn test_asinh() { + assert_eq!(0.0f64.asinh(), 0.0f64); + assert_eq!((-0.0f64).asinh(), -0.0f64); + assert_eq!(Float::infinity::<f64>().asinh(), Float::infinity::<f64>()); + assert_eq!(Float::neg_infinity::<f64>().asinh(), Float::neg_infinity::<f64>()); + assert!(Float::NaN::<f64>().asinh().is_NaN()); + assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); + assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); + } + + #[test] + fn test_acosh() { + assert_eq!(1.0f64.acosh(), 0.0f64); + assert!(0.999f64.acosh().is_NaN()); + assert_eq!(Float::infinity::<f64>().acosh(), Float::infinity::<f64>()); + assert!(Float::neg_infinity::<f64>().acosh().is_NaN()); + assert!(Float::NaN::<f64>().acosh().is_NaN()); + assert_approx_eq!(2.0f64.acosh(), 1.31695789692481670862504634730796844f64); + assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64); + } + + #[test] + fn test_atanh() { + assert_eq!(0.0f64.atanh(), 0.0f64); + assert_eq!((-0.0f64).atanh(), -0.0f64); + assert_eq!(1.0f64.atanh(), Float::infinity::<f64>()); + assert_eq!((-1.0f64).atanh(), Float::neg_infinity::<f64>()); + assert!(2f64.atanh().atanh().is_NaN()); + assert!((-2f64).atanh().atanh().is_NaN()); + assert!(Float::infinity::<f64>().atanh().is_NaN()); + assert!(Float::neg_infinity::<f64>().atanh().is_NaN()); + assert!(Float::NaN::<f64>().atanh().is_NaN()); + assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64); + assert_approx_eq!((-0.5f64).atanh(), -0.54930614433405484569762261846126285f64); + } + + #[test] fn test_real_consts() { assert_approx_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>()); assert_approx_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index e6a2ed7ea97..879c9494105 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -585,6 +585,51 @@ impl Hyperbolic for float { fn tanh(&self) -> float { (*self as f64).tanh() as float } + + /// + /// Inverse hyperbolic sine + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic sine of `self` will be returned + /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` + /// - `NaN` if `self` is `NaN` + /// + #[inline(always)] + fn asinh(&self) -> float { + (*self as f64).asinh() as float + } + + /// + /// Inverse hyperbolic cosine + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic cosine of `self` will be returned + /// - `infinity` if `self` is `infinity` + /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) + /// + #[inline(always)] + fn acosh(&self) -> float { + (*self as f64).acosh() as float + } + + /// + /// Inverse hyperbolic tangent + /// + /// # Returns + /// + /// - on success, the inverse hyperbolic tangent of `self` will be returned + /// - `self` if `self` is `0.0` or `-0.0` + /// - `infinity` if `self` is `1.0` + /// - `neg_infinity` if `self` is `-1.0` + /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` + /// (including `infinity` and `neg_infinity`) + /// + #[inline(always)] + fn atanh(&self) -> float { + (*self as f64).atanh() as float + } } impl Real for float { @@ -973,6 +1018,43 @@ mod tests { } #[test] + fn test_asinh() { + assert_eq!(0.0f.asinh(), 0.0f); + assert_eq!((-0.0f).asinh(), -0.0f); + assert_eq!(Float::infinity::<float>().asinh(), Float::infinity::<float>()); + assert_eq!(Float::neg_infinity::<float>().asinh(), Float::neg_infinity::<float>()); + assert!(Float::NaN::<float>().asinh().is_NaN()); + assert_approx_eq!(2.0f.asinh(), 1.443635475178810342493276740273105f); + assert_approx_eq!((-2.0f).asinh(), -1.443635475178810342493276740273105f); + } + + #[test] + fn test_acosh() { + assert_eq!(1.0f.acosh(), 0.0f); + assert!(0.999f.acosh().is_NaN()); + assert_eq!(Float::infinity::<float>().acosh(), Float::infinity::<float>()); + assert!(Float::neg_infinity::<float>().acosh().is_NaN()); + assert!(Float::NaN::<float>().acosh().is_NaN()); + assert_approx_eq!(2.0f.acosh(), 1.31695789692481670862504634730796844f); + assert_approx_eq!(3.0f.acosh(), 1.76274717403908605046521864995958461f); + } + + #[test] + fn test_atanh() { + assert_eq!(0.0f.atanh(), 0.0f); + assert_eq!((-0.0f).atanh(), -0.0f); + assert_eq!(1.0f.atanh(), Float::infinity::<float>()); + assert_eq!((-1.0f).atanh(), Float::neg_infinity::<float>()); + assert!(2f64.atanh().atanh().is_NaN()); + assert!((-2f64).atanh().atanh().is_NaN()); + assert!(Float::infinity::<f64>().atanh().is_NaN()); + assert!(Float::neg_infinity::<f64>().atanh().is_NaN()); + assert!(Float::NaN::<float>().atanh().is_NaN()); + assert_approx_eq!(0.5f.atanh(), 0.54930614433405484569762261846126285f); + assert_approx_eq!((-0.5f).atanh(), -0.54930614433405484569762261846126285f); + } + + #[test] fn test_real_consts() { assert_approx_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>()); assert_approx_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f); diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 50ba55039d4..18d552c273c 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -133,6 +133,9 @@ pub trait Hyperbolic: Exponential { fn sinh(&self) -> Self; fn cosh(&self) -> Self; fn tanh(&self) -> Self; + fn asinh(&self) -> Self; + fn acosh(&self) -> Self; + fn atanh(&self) -> Self; } /// |
