diff --git a/src/si/ratio.rs b/src/si/ratio.rs index 47abeba9..bd789871 100644 --- a/src/si/ratio.rs +++ b/src/si/ratio.rs @@ -32,49 +32,117 @@ quantity! { } } -/// Implementation of various stdlib inverse trigonometric functions +/// Implementation of various stdlib functions. #[cfg(feature = "std")] impl Ratio where U: crate::si::Units + ?Sized, V: crate::num::Float + crate::Conversion, radian: crate::Conversion, + ratio: crate::Conversion, { /// 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 { Angle::new::(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 { Angle::new::(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 { Angle::new::(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 { Angle::new::(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 { Angle::new::(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 { Angle::new::(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 { + Ratio::new::(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 { + Ratio::new::(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 { + Ratio::new::(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 { + Ratio::new::(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 { + Ratio::new::(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 { + Ratio::new::(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 { + Ratio::new::(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 { + Ratio::new::(self.value.ln_1p()) + } } mod convert { @@ -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; @@ -185,6 +254,38 @@ mod tests { fn atanh(x: V) -> bool { Test::eq(&x.atanh(), &Ratio::from(x).atanh().get::()) } + + fn exp(x: V) -> bool { + Test::eq(&x.exp(), &Ratio::from(x).exp().get::()) + } + + fn exp2(x: V) -> bool { + Test::eq(&x.exp2(), &Ratio::from(x).exp2().get::()) + } + + fn ln(x: V) -> bool { + Test::eq(&x.ln(), &Ratio::from(x).ln().get::()) + } + + fn log(x: V, y: V) -> bool { + Test::eq(&x.log(y), &Ratio::from(x).log(y).get::()) + } + + fn log2(x: V) -> bool { + Test::eq(&x.log2(), &Ratio::from(x).log2().get::()) + } + + fn log10(x: V) -> bool { + Test::eq(&x.log10(), &Ratio::from(x).log10().get::()) + } + + fn exp_m1(x: V) -> bool { + Test::eq(&x.exp_m1(), &Ratio::from(x).exp_m1().get::()) + } + + fn ln_1p(x: V) -> bool { + Test::eq(&x.ln_1p(), &Ratio::from(x).ln_1p().get::()) + } } } }