#[cfg(feature = "std")]
use super::angle::{Angle, radian};
quantity! {
quantity: Ratio; "ratio";
dimension: ISQ<
Z0, Z0, Z0, Z0, Z0, Z0, Z0>; units {
@ratio: 1.0; "", "", "";
@part_per_hundred: 1.0_E-2; "parts per hundred", "part per hundred", "parts per hundred";
@percent: 1.0_E-2; "%", "percent", "percent";
@part_per_thousand: 1.0_E-3; "parts per thousand", "part per thousand",
"parts per thousand";
@per_mille: 1.0_E-3; "‰", "per mille", "per mille";
@part_per_ten_thousand: 1.0_E-4; "parts per ten thousand", "part per then thousand",
"parts per ten thousand"; @basis_point: 1.0_E-4; "bp", "basis point", "basis points";
@part_per_million: 1.0_E-6; "ppm", "part per million", "parts per million";
@part_per_billion: 1.0_E-9; "ppb", "part per billion", "parts per billion";
@part_per_trillion: 1.0_E-12; "ppt", "part per trillion", "parts per trillion";
@part_per_quadrillion: 1.0_E-15; "ppq", "part per quadrillion", "parts per quadrillion";
}
}
#[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>,
{
#[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())
}
#[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())
}
#[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())
}
#[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())
}
#[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())
}
#[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())
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn exp(self) -> Self {
Ratio::new::<ratio>(self.value.exp())
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn exp2(self) -> Self {
Ratio::new::<ratio>(self.value.exp2())
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn ln(self) -> Self {
Ratio::new::<ratio>(self.value.ln())
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn log(self, base: V) -> Self {
Ratio::new::<ratio>(self.value.log(base))
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn log2(self) -> Self {
Ratio::new::<ratio>(self.value.log2())
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn log10(self) -> Self {
Ratio::new::<ratio>(self.value.log10())
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn exp_m1(self) -> Self {
Ratio::new::<ratio>(self.value.exp_m1())
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
pub fn ln_1p(self) -> Self {
Ratio::new::<ratio>(self.value.ln_1p())
}
}
mod convert {
use super::Ratio;
impl<U, V> From<V> for Ratio<U, V>
where
U: crate::si::Units<V> + ?Sized,
V: crate::num::Num + crate::Conversion<V>,
{
fn from(t: V) -> Self {
Ratio {
dimension: crate::lib::marker::PhantomData,
units: crate::lib::marker::PhantomData,
value: t,
}
}
}
storage_types! {
use super::Ratio;
impl<U> From<Ratio<U, Self>> for V
where
U: crate::si::Units<Self> + ?Sized,
Self: crate::num::Num + crate::Conversion<Self>,
{
fn from(t: Ratio<U, Self>) -> Self {
t.value
}
}
}
}
#[cfg(test)]
mod tests {
storage_types! {
use crate::num::{FromPrimitive, One};
use crate::si::quantities::*;
use crate::si::ratio as r;
use crate::tests::Test;
#[test]
fn from() {
let r1: Ratio<V> = Ratio::<V>::from(V::one());
let r2: Ratio<V> = V::one().into();
let _: V = V::from(r1);
let _: V = r2.into();
}
#[test]
fn check_units() {
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E2).unwrap()),
&Ratio::new::<r::part_per_hundred>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E2).unwrap()),
&Ratio::new::<r::percent>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E3).unwrap()),
&Ratio::new::<r::part_per_thousand>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E3).unwrap()),
&Ratio::new::<r::per_mille>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E4).unwrap()),
&Ratio::new::<r::part_per_ten_thousand>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E4).unwrap()),
&Ratio::new::<r::basis_point>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E6).unwrap()),
&Ratio::new::<r::part_per_million>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one() / V::from_f64(1.0_E9).unwrap()),
&Ratio::new::<r::part_per_billion>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one()
/ V::from_f64(1.0_E12).unwrap()),
&Ratio::new::<r::part_per_trillion>(V::one()));
Test::assert_eq(&Ratio::new::<r::ratio>(V::one()
/ V::from_f64(1.0_E15).unwrap()),
&Ratio::new::<r::part_per_quadrillion>(V::one()));
}
}
#[cfg(feature = "std")]
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;
quickcheck! {
fn acos(x: V) -> bool {
Test::eq(&x.acos(), &Ratio::from(x).acos().get::<a::radian>())
}
fn acosh(x: V) -> bool {
Test::eq(&x.acosh(), &Ratio::from(x).acosh().get::<a::radian>())
}
fn asin(x: V) -> bool {
Test::eq(&x.asin(), &Ratio::from(x).asin().get::<a::radian>())
}
fn asinh(x: V) -> bool {
Test::eq(&x.asinh(), &Ratio::from(x).asinh().get::<a::radian>())
}
fn atan(x: V) -> bool {
Test::eq(&x.atan(), &Ratio::from(x).atan().get::<a::radian>())
}
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>())
}
}
}
}
}