Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversion now has both a value and a factor type #453

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,13 +408,15 @@ pub enum ConstantOp {
/// Trait to identify [units][units] which have a [conversion factor][factor].
///
/// ## Generic Parameters
/// * `V`: Underlying storage type trait is implemented for.
///
/// * `T`: The type of the conversion factor. Usually same as `VT`, but for example complex storage types have this as float as it needs `PartialEq`
/// * `VT`: Underlying storage type trait is implemented for. Does not have to implement `PartialEq`, so its viable for complex data types.
/// [units]: https://jcgm.bipm.org/vim/en/1.13.html
/// [factor]: https://jcgm.bipm.org/vim/en/1.24.html
pub trait Conversion<V> {
/// Conversion factor type specific to the underlying storage type.
type T: ConversionFactor<V>;
type T: ConversionFactor<V> + PartialOrd;
/// Value type of the underlying type.
type VT: ConversionFactor<V> + From<Self::T>;

/// Coefficient portion of [conversion factor](https://jcgm.bipm.org/vim/en/1.24.html) for
/// converting the given unit. To convert to the base unit for the quantity use `(value +
Expand All @@ -436,21 +438,17 @@ pub trait Conversion<V> {
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
#[allow(unused_variables)]
fn constant(op: ConstantOp) -> Self::T {
<Self::T as num::Zero>::zero()
fn constant(op: ConstantOp) -> Self::VT {
<Self::VT as num::Zero>::zero()
}

/// Instance [conversion factor](https://jcgm.bipm.org/vim/en/1.24.html).
///
/// Default implementation returns the coefficient: `Self::coefficient()`.
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline(always)]
fn conversion(&self) -> Self::T
fn conversion(&self) -> Self::VT
where
Self: Sized,
{
Self::coefficient()
}
Self: Sized;
}

/// Trait representing a [conversion factor][factor].
Expand All @@ -461,8 +459,7 @@ pub trait Conversion<V> {
/// [factor]: https://jcgm.bipm.org/vim/en/1.24.html
#[allow(unused_qualifications)] // lib:cmp::PartialOrder false positive.
pub trait ConversionFactor<V>:
lib::cmp::PartialOrd
+ lib::ops::Add<Self, Output = Self>
lib::ops::Add<Self, Output = Self>
+ lib::ops::Sub<Self, Output = Self>
+ lib::ops::Mul<Self, Output = Self>
+ lib::ops::Div<Self, Output = Self>
Expand Down Expand Up @@ -515,19 +512,20 @@ pub trait Kind:
storage_types! {
types: Float;

impl crate::Conversion<Self> for V {
impl crate::Conversion<V> for V {
type T = Self;
type VT = Self::T;

#[inline(always)]
fn constant(op: crate::ConstantOp) -> Self::T {
fn constant(op: crate::ConstantOp) -> Self::VT {
match op {
crate::ConstantOp::Add => -<Self::T as crate::num::Zero>::zero(),
crate::ConstantOp::Sub => <Self::T as crate::num::Zero>::zero(),
crate::ConstantOp::Add => -<Self::VT as crate::num::Zero>::zero(),
crate::ConstantOp::Sub => <Self::VT as crate::num::Zero>::zero(),
}
}

#[inline(always)]
fn conversion(&self) -> Self::T {
fn conversion(&self) -> Self::VT {
*self
}
}
Expand All @@ -554,9 +552,10 @@ storage_types! {

impl crate::Conversion<V> for V {
type T = crate::num::rational::Ratio<V>;
type VT = Self::T;

#[inline(always)]
fn conversion(&self) -> Self::T {
fn conversion(&self) -> Self::VT {
(*self).into()
}
}
Expand All @@ -583,9 +582,10 @@ storage_types! {

impl crate::Conversion<V> for V {
type T = crate::num::rational::Ratio<V>;
type VT = Self::T;

#[inline(always)]
fn conversion(&self) -> Self::T {
fn conversion(&self) -> Self::VT {
self.clone().into()
}
}
Expand All @@ -612,9 +612,10 @@ storage_types! {

impl crate::Conversion<V> for V {
type T = V;
type VT = Self::T;

#[inline(always)]
fn conversion(&self) -> Self::T {
fn conversion(&self) -> Self::VT {
*self
}
}
Expand All @@ -637,9 +638,10 @@ storage_types! {

impl crate::Conversion<V> for V {
type T = V;
type VT = Self::T;

#[inline(always)]
fn conversion(&self) -> Self::T {
fn conversion(&self) -> Self::VT {
self.clone()
}
}
Expand All @@ -665,20 +667,21 @@ storage_types! {
types: Complex;
impl crate::Conversion<V> for V {
type T = VV;
type VT = V;

#[inline(always)]
fn constant(op: crate::ConstantOp) -> Self::T {
fn constant(op: crate::ConstantOp) -> Self::VT {
match op {
crate::ConstantOp::Add => -<Self::T as crate::num::Zero>::zero(),
crate::ConstantOp::Sub => <Self::T as crate::num::Zero>::zero(),
crate::ConstantOp::Add => -<Self::VT as crate::num::Zero>::zero(),
crate::ConstantOp::Sub => <Self::VT as crate::num::Zero>::zero(),
}
}

#[inline(always)]
fn conversion(&self) -> Self::T {
fn conversion(&self) -> Self::VT {
// Conversion factor is the norm of the number. Scaling with length again yields the
// same number.
self.norm()
*self
}
}

Expand All @@ -695,6 +698,18 @@ storage_types! {
V::new(self, 0.0)
}
}

impl crate::ConversionFactor<V> for V {
#[inline(always)]
fn powi(self, e: i32) -> Self {
crate::num::complex::Complex::powi(&self,e)
}

#[inline(always)]
fn value(self) -> V {
self
}
}
}

/// Utilities for formatting and printing quantities.
Expand Down
16 changes: 8 additions & 8 deletions src/quantity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ macro_rules! quantity {
/// [units]: https://jcgm.bipm.org/vim/en/1.13.html
/// [factor]: https://jcgm.bipm.org/vim/en/1.24.html
#[allow(dead_code)]
pub trait Conversion<V>: Unit + $crate::Conversion<V, T = <V as $crate::Conversion<V>>::T>
pub trait Conversion<V>: Unit + $crate::Conversion<V, T = <V as $crate::Conversion<V>>::T, VT = <V as $crate::Conversion<V>>::VT>
where
V: $crate::Conversion<V>,
{
Expand Down Expand Up @@ -218,7 +218,7 @@ macro_rules! quantity {
#[inline(always)]
pub fn new<N>(v: V) -> Self
where
N: Unit + $crate::Conversion<V, T = V::T>,
N: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>,
{
$quantity {
dimension: $crate::lib::marker::PhantomData,
Expand All @@ -235,7 +235,7 @@ macro_rules! quantity {
#[inline(always)]
pub fn get<N>(&self) -> V
where
N: Unit + $crate::Conversion<V, T = V::T>,
N: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>,
{
__system::from_base::<Dimension, U, V, N>(&self.value)
}
Expand All @@ -250,7 +250,7 @@ macro_rules! quantity {
pub fn floor<N>(self) -> Self
where
V: $crate::num::Float,
N: Unit + $crate::Conversion<V, T = V::T>,
N: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>,
{
Self::new::<N>(self.get::<N>().floor())
}
Expand All @@ -265,7 +265,7 @@ macro_rules! quantity {
pub fn ceil<N>(self) -> Self
where
V: $crate::num::Float,
N: Unit + $crate::Conversion<V, T = V::T>,
N: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>,
{
Self::new::<N>(self.get::<N>().ceil())
}
Expand All @@ -280,7 +280,7 @@ macro_rules! quantity {
pub fn round<N>(self) -> Self
where
V: $crate::num::Float,
N: Unit + $crate::Conversion<V, T = V::T>,
N: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>,
{
Self::new::<N>(self.get::<N>().round())
}
Expand All @@ -294,7 +294,7 @@ macro_rules! quantity {
pub fn trunc<N>(self) -> Self
where
V: $crate::num::Float,
N: Unit + $crate::Conversion<V, T = V::T>,
N: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>,
{
Self::new::<N>(self.get::<N>().trunc())
}
Expand All @@ -308,7 +308,7 @@ macro_rules! quantity {
pub fn fract<N>(self) -> Self
where
V: $crate::num::Float,
N: Unit + $crate::Conversion<V, T = V::T>,
N: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>,
{
Self::new::<N>(self.get::<N>().fract())
}
Expand Down
2 changes: 1 addition & 1 deletion src/si/angle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ where
D: crate::si::Dimension + ?Sized,
U: crate::si::Units<V> + ?Sized,
V: crate::num::Float + crate::Conversion<V>,
radian: crate::Conversion<V, T = V::T>,
radian: crate::Conversion<V, T = V::T, VT = V::VT>,
{
/// Computes the four quadrant arctangent of self (y) and other (x).
#[must_use = "method returns a new number and does not mutate the original value"]
Expand Down
4 changes: 2 additions & 2 deletions src/si/ratio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ 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>,
radian: crate::Conversion<V, T = V::T, VT = V::VT>,
ratio: crate::Conversion<V, T = V::T, VT = V::VT>,
{
/// Computes the value of the inverse cosine of the ratio.
#[must_use = "method returns a new number and does not mutate the original value"]
Expand Down
8 changes: 4 additions & 4 deletions src/si/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ impl<U, V> crate::lib::convert::TryFrom<Time<U, V>> for Duration
where
U: crate::si::Units<V> + ?Sized,
V: crate::num::Num + crate::Conversion<V> + PartialOrd + ToPrimitive,
second: crate::Conversion<V, T = V::T>,
nanosecond: crate::Conversion<V, T = V::T>,
second: crate::Conversion<V, T = V::T, VT = V::VT>,
nanosecond: crate::Conversion<V, T = V::T, VT = V::VT>,
{
type Error = TryFromError;

Expand Down Expand Up @@ -117,8 +117,8 @@ impl<U, V> crate::lib::convert::TryFrom<Duration> for Time<U, V>
where
U: crate::si::Units<V> + ?Sized,
V: crate::num::Num + crate::Conversion<V> + FromPrimitive,
second: crate::Conversion<V, T = V::T>,
nanosecond: crate::Conversion<V, T = V::T>,
second: crate::Conversion<V, T = V::T, VT = V::VT>,
nanosecond: crate::Conversion<V, T = V::T, VT = V::VT>,
{
type Error = TryFromError;

Expand Down
20 changes: 10 additions & 10 deletions src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ macro_rules! system {
///
/// Base unit.
#[allow(non_camel_case_types)]
type $name: Unit + $crate::Conversion<V, T = V::T>;)+
type $name: Unit + $crate::Conversion<V, T = V::T, VT = V::VT>;)+
}

/// Trait to identify [measurement units][measurement] of individual
Expand Down Expand Up @@ -307,7 +307,7 @@ macro_rules! system {
D: Dimension + ?Sized,
U: Units<V> + ?Sized,
V: $crate::Conversion<V>,
N: $crate::Conversion<V, T = V::T>,
N: $crate::Conversion<V, T = V::T, VT = V::VT>,
{
use $crate::typenum::Integer;
use $crate::{Conversion, ConversionFactor};
Expand All @@ -318,10 +318,10 @@ macro_rules! system {
let n_cons = N::constant($crate::ConstantOp::Sub);

if n_coef < f {
(v * (f / n_coef) - n_cons).value()
(v * (f / n_coef).into() - n_cons.into()).value()
}
else {
(v / (n_coef / f) - n_cons).value()
(v / (n_coef / f).into() - n_cons.into()).value()
}
}

Expand All @@ -338,7 +338,7 @@ macro_rules! system {
D: Dimension + ?Sized,
U: Units<V> + ?Sized,
V: $crate::Conversion<V>,
N: $crate::Conversion<V, T = V::T>,
N: $crate::Conversion<V, T = V::T, VT= V::VT>,
{
use $crate::typenum::Integer;
use $crate::{Conversion, ConversionFactor};
Expand All @@ -349,10 +349,10 @@ macro_rules! system {
let n_cons = N::constant($crate::ConstantOp::Add);

if n_coef >= f {
((v + n_cons) * (n_coef / f)).value()
((v + n_cons.into()) * (n_coef / f).into()).value()
}
else {
(((v + n_cons) * n_coef) / f).value()
(((v + n_cons.into()) * n_coef.into()) / f.into()).value()
}
}

Expand All @@ -376,8 +376,8 @@ macro_rules! system {
use $crate::typenum::Integer;
use $crate::{Conversion, ConversionFactor};

(v.conversion() $(* Ur::$name::coefficient().powi(D::$symbol::to_i32())
/ Ul::$name::coefficient().powi(D::$symbol::to_i32()))+)
(v.conversion() $(* Ur::$name::coefficient().powi(D::$symbol::to_i32()).into()
/ Ul::$name::coefficient().powi(D::$symbol::to_i32()).into())+)
.value()
}}

Expand Down Expand Up @@ -1508,7 +1508,7 @@ macro_rules! system {
D: Dimension + ?Sized,
U: Units<V> + ?Sized,
V: Num + Conversion<V> + fmt::$style,
N: Unit + Conversion<V, T = V::T>,
N: Unit + Conversion<V, T = V::T, VT = V::VT>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let value = from_base::<D, U, V, N>(&self.quantity.value);
Expand Down
Loading