Skip to content

Commit

Permalink
Merge pull request #291 from jacg/exp-log
Browse files Browse the repository at this point in the history
Implement and test `exp` for Ratio
  • Loading branch information
iliekturtles authored Mar 26, 2022
2 parents 66a0546 + cbdb001 commit 66d3e85
Showing 1 changed file with 103 additions and 2 deletions.
105 changes: 103 additions & 2 deletions src/si/ratio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,49 +32,117 @@ quantity! {
}
}

/// Implementation of various stdlib inverse trigonometric functions
/// Implementation of various stdlib functions.
#[cfg(feature = "std")]
impl<U, V> Ratio<U, V>
where
U: crate::si::Units<V> + ?Sized,
V: crate::num::Float + crate::Conversion<V>,
radian: crate::Conversion<V, T = V::T>,
ratio: crate::Conversion<V, T = V::T>,
{
/// Computes the value of the inverse cosine of the ratio.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn acos(self) -> Angle<U, V> {
Angle::new::<radian>(self.value.acos())
}

/// Computes the value of the inverse hyperbolic cosine of the ratio.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn acosh(self) -> Angle<U, V> {
Angle::new::<radian>(self.value.acosh())
}

/// Computes the value of the inverse sine of the ratio.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn asin(self) -> Angle<U, V> {
Angle::new::<radian>(self.value.asin())
}

/// Computes the value of the inverse hyperbolic sine of the ratio.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn asinh(self) -> Angle<U, V> {
Angle::new::<radian>(self.value.asinh())
}

/// Computes the value of the inverse tangent of the ratio.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn atan(self) -> Angle<U, V> {
Angle::new::<radian>(self.value.atan())
}

/// Computes the value of the inverse hyperbolic tangent of the ratio.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn atanh(self) -> Angle<U, V> {
Angle::new::<radian>(self.value.atanh())
}

/// Returns `e^(self)`, (the exponential function).
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn exp(self) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.exp())
}

/// Returns 2^(self).
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn exp2(self) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.exp2())
}

/// Returns the natural logarithm of the number.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn ln(self) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.ln())
}

/// Returns the logarithm of the number with respect to an arbitrary base.
///
/// The result might not be correctly rounded owing to implementation
/// details; self.log2() can produce more accurate results for base 2, and
/// self.log10() can produce more accurate results for base 10.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn log(self, base: V) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.log(base))
}

/// Returns the base 2 logarithm of the number.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn log2(self) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.log2())
}

/// Returns the base 10 logarithm of the number.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn log10(self) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.log10())
}

/// Returns e^(self) - 1 in a way that is accurate even if the number is close to zero.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn exp_m1(self) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.exp_m1())
}

/// Returns ln(1+n) (natural logarithm) more accurately than if the
/// operations were performed separately.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn ln_1p(self) -> Ratio<U, V> {
Ratio::new::<ratio>(self.value.ln_1p())
}
}

mod convert {
Expand Down Expand Up @@ -153,11 +221,12 @@ mod tests {
}

#[cfg(feature = "std")]
mod inv_trig {
mod float {
storage_types! {
types: Float;

use crate::si::angle as a;
use crate::si::ratio as r;
use crate::si::quantities::*;
use crate::tests::Test;

Expand Down Expand Up @@ -185,6 +254,38 @@ mod tests {
fn atanh(x: V) -> bool {
Test::eq(&x.atanh(), &Ratio::from(x).atanh().get::<a::radian>())
}

fn exp(x: V) -> bool {
Test::eq(&x.exp(), &Ratio::from(x).exp().get::<r::ratio>())
}

fn exp2(x: V) -> bool {
Test::eq(&x.exp2(), &Ratio::from(x).exp2().get::<r::ratio>())
}

fn ln(x: V) -> bool {
Test::eq(&x.ln(), &Ratio::from(x).ln().get::<r::ratio>())
}

fn log(x: V, y: V) -> bool {
Test::eq(&x.log(y), &Ratio::from(x).log(y).get::<r::ratio>())
}

fn log2(x: V) -> bool {
Test::eq(&x.log2(), &Ratio::from(x).log2().get::<r::ratio>())
}

fn log10(x: V) -> bool {
Test::eq(&x.log10(), &Ratio::from(x).log10().get::<r::ratio>())
}

fn exp_m1(x: V) -> bool {
Test::eq(&x.exp_m1(), &Ratio::from(x).exp_m1().get::<r::ratio>())
}

fn ln_1p(x: V) -> bool {
Test::eq(&x.ln_1p(), &Ratio::from(x).ln_1p().get::<r::ratio>())
}
}
}
}
Expand Down

0 comments on commit 66d3e85

Please sign in to comment.