From 12909553a4802e2cd8f5528d11defc3ba4fd94e0 Mon Sep 17 00:00:00 2001 From: Paho Lurie-Gregg Date: Sun, 24 Jul 2016 16:33:25 -0700 Subject: [PATCH] Beginning of conversion API --- CHANGELOG.md | 7 +- Cargo.toml | 4 +- examples/conversion.rs | 53 ++++++++++ examples/vector3b.rs | 4 +- src/cgs.rs | 19 ---- src/dimensioned.rs | 198 ++++++++++++++++++++++------------- src/lib.rs | 7 +- src/make_units.rs | 70 +++++++------ src/unit_systems/cgs.rs | 31 ++++++ src/unit_systems/mks.rs | 31 ++++++ src/unit_systems/mod.rs | 3 + src/{ => unit_systems}/si.rs | 0 tests/derived.rs | 17 +++ tests/dim-ops.rs | 2 +- 14 files changed, 314 insertions(+), 132 deletions(-) create mode 100644 examples/conversion.rs delete mode 100644 src/cgs.rs create mode 100644 src/unit_systems/cgs.rs create mode 100644 src/unit_systems/mks.rs create mode 100644 src/unit_systems/mod.rs rename src/{ => unit_systems}/si.rs (100%) create mode 100644 tests/derived.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 31de2c0c..42978d71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,11 @@ This project follows semantic versioning. +### Unpublished +- `[added]` Unit conversion example +- `[changed]` Removed `Dimensioned` constraint for `D` in `Dim`. This enables derived types to work properly. It is a temporary change only until the bug with Rust is fixed. See [issue #6](https://github.com/paholg/dimensioned/issues/6). + ### 0.5.0 (2015-12-02) - `[added]` This change log! -- `[changed]` **BREAKING** Use typenum instead of peano for faster and more complete type-level numbers. ([#3](https://github.com/paholg/dimensioned/pull/3)) +- `[changed]` **BREAKING** Use typenum instead of peano for faster and more complete type-level numbers. ([PR #3](https://github.com/paholg/dimensioned/pull/3)) - `[added]` Re-export useful things from typenum so that crates downstream don't need to depend on it. - diff --git a/Cargo.toml b/Cargo.toml index f3d82130..a1673431 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,5 @@ name = "dimensioned" [dependencies] - num = "0.1.28" - typenum = "1.1.0" + num = "0.1.34" + typenum = "1.3.2" diff --git a/examples/conversion.rs b/examples/conversion.rs new file mode 100644 index 00000000..b81e7500 --- /dev/null +++ b/examples/conversion.rs @@ -0,0 +1,53 @@ +#[macro_use] +extern crate dimensioned as dim; +extern crate typenum; + +use dim::{Dim}; +use dim::cgs::{self, CGS, FromCGS}; +use typenum::int::Integer; + +use std::ops::{Mul, Div}; + +type Quot = >::Output; + + +mod fps { + make_units_adv! { + FPS, Unitless, one, f64, 1.0; + base { + P2, Foot, ft, ft; + P2, Pound, lb, lb; + P1, Second, s, s; + } + derived { + } + } + pub trait FromFPS where Self: Sized { + fn from_fps(from: Dim, V>) -> Dim; + } +} + +use fps::{FPS, FromFPS}; + +impl FromCGS for FPS + where V: Mul, Centimeter: Integer, Gram: Integer, Second: Integer, { + fn from_cgs(from: Dim, V>) -> Dim { + Dim::new( from.0 * 0.0328084f64.sqrt().powi(Centimeter::to_i32()) * 0.00220462f64.sqrt().powi(Gram::to_i32()) ) + } +} + + +fn main() { + let speed = 35.0 * cgs::cm / cgs::s; + + let t2 = 10.0 * cgs::cm; + let t2f = FPS::from_cgs(t2); + + println!("t2: {}, t2f: {}", t2, t2f); + + // let speed2 = speed.convert_to(); + + // let speed2 = MKS::from_cgs(speedc); + + // println!("I was going {}, which is {}. Boo: {}", speedc, speed2, speed2); +} diff --git a/examples/vector3b.rs b/examples/vector3b.rs index 89c99542..a985ba66 100644 --- a/examples/vector3b.rs +++ b/examples/vector3b.rs @@ -3,8 +3,6 @@ extern crate num; use vector3b::{Vector3, Norm2, Cross}; -use num::Float; - use dim::Sqrt; use dim::si::{one, m, kg, s}; @@ -56,7 +54,7 @@ fn main() { } mod vector3b { - use num::traits::Float; + use num::Float; use std::ops::{Add, Sub, Mul, Div}; use std::fmt::{self, Display}; diff --git a/src/cgs.rs b/src/cgs.rs deleted file mode 100644 index 9dc49e33..00000000 --- a/src/cgs.rs +++ /dev/null @@ -1,19 +0,0 @@ -/*! -The **cgs** module provides a unit system for use with Gaussian CGS units. It was -generated using the `make_units!` macro. See its documentation for more information. - -It will also define derived units, although this is not implemented yet. -*/ - -#![allow(missing_docs)] - -make_units_adv! { - CGS, Unitless, one, f64, 1.0; - base { - P2, Centimeter, cm, cm; - P2, Gram, g, g; - P1, Second, s, s; - } - derived { - } -} diff --git a/src/dimensioned.rs b/src/dimensioned.rs index 7b4ae4ab..4f0c0a37 100644 --- a/src/dimensioned.rs +++ b/src/dimensioned.rs @@ -45,16 +45,16 @@ pub trait DimToString: Dimension { } /// This is the primary struct that users of this library will interact with. -pub struct Dim(pub V, pub PhantomData); +pub struct Dim(pub V, pub PhantomData); use std::clone::Clone; use std::marker::Copy; -impl Clone for Dim { +impl Clone for Dim { fn clone(&self) -> Self { Dim::new(self.0.clone()) } } -impl Copy for Dim {} +impl Copy for Dim {} -impl Dim { +impl Dim { /** Construct a new `Dim` object. @@ -103,7 +103,7 @@ This trait is implemented by default for everything that is not Dim. It al #[doc(hidden)] pub trait NotDim {} impl NotDim for .. {} -impl !NotDim for Dim {} +impl !NotDim for Dim {} /// **Sqrt** is used for implementing a `sqrt()` member for types that don't `impl Float`. pub trait Sqrt { @@ -124,7 +124,7 @@ pub trait Sqrt { fn sqrt(self) -> Self::Output; } -impl Sqrt for Dim where D: Dimension + Root, V: Float, >::Output: Dimension { +impl Sqrt for Dim where D: Root, V: Float, >::Output: Dimension { type Output = Dim<>::Output, V>; #[inline] fn sqrt(self) -> Self::Output { Dim( (self.0).sqrt(), PhantomData) } @@ -149,7 +149,7 @@ pub trait Cbrt { fn cbrt(self) -> Self::Output; } -impl Cbrt for Dim where D: Dimension + Root, V: Float, >::Output: Dimension { +impl Cbrt for Dim where D: Root, V: Float, >::Output: Dimension { type Output = Dim<>::Output, V>; #[inline] fn cbrt(self) -> Self::Output { Dim( (self.0).cbrt(), PhantomData) } @@ -181,7 +181,7 @@ pub trait Root { */ fn root(radicand: Radicand) -> Self::Output; } -impl Root> for Degree where D: Dimension + Root, V: Float, Degree: Integer, >::Output: Dimension { +impl Root> for Degree where D: Root, V: Float, Degree: Integer, >::Output: Dimension { type Output = Dim<>::Output, V>; fn root(base: Dim) -> Self::Output { let x: V = NumCast::from(Degree::to_i32()).expect("Attempted to take nth root of a Dim, but could not convert from i32 to V to compute n."); @@ -214,7 +214,7 @@ pub trait Pow { */ fn pow(base: Base) -> Self::Output; } -impl Pow> for Exp where D: Dimension + Pow, V: Float, Exp: Integer, >::Output: Dimension { +impl Pow> for Exp where D: Pow, V: Float, Exp: Integer, >::Output: Dimension { type Output = Dim<>::Output, V>; fn pow(base: Dim) -> Self::Output { Dim::new( (base.0).powi(Exp::to_i32()) ) @@ -238,13 +238,73 @@ pub trait Recip { */ fn recip(self) -> Self::Output; } -impl Recip for Dim where D: Dimension + Recip, V: Float, ::Output: Dimension { +impl Recip for Dim where D: Recip, V: Float, ::Output: Dimension { type Output = Dim<::Output, V>; fn recip(self) -> Self::Output { Dim::new( (self.0).recip() ) } } +// /** +// **Convert** provides a useful trait for allowing unit conversions. The trait `std::convert::From` can't be used because it doesn't have an associated type. + +// # Example +// ``` +// #[macro_use] +// extern crate dimensioned as dim; +// extern crate typenum; + +// use dim::{Dim, FromDim}; +// use dim::cgs::{self, CGS}; +// use typenum::int::Integer; +// use typenum::consts::P2; + +// use std::ops::{Mul, Div}; + +// type Quot = >::Output; + +// mod mks { +// make_units_adv! { +// CGS, Unitless, one, f64, 1.0; +// base { +// P2, Centimeter, cm, cm; +// P2, Gram, g, g; +// P1, Second, s, s; +// } +// derived { +// } +// } +// } +// use mks::MKS; + +// impl FromDim, V>> for MKS, Quot, S> +// where V: Mul, CM: Integer + Div, G: Integer + Div, S: Integer, +// Quot: Integer, Quot: Integer, +// { +// type Output = Dim; +// fn from_dim(origin: Dim, V>) -> Self::Output { +// Dim::new( origin.0 * 0.01f64.powi(CM::to_i32()) * 0.001f64.powi(G::to_i32()) ) +// } +// } + + +// fn main() { +// let speed = 35.0 * cgs::cm / cgs::s; + +// println!("I was going {}, which is {}.", speed, MKS::from_dim(speed)); +// } + +// ``` +// */ +// pub trait ConvertFrom where Self: Sized { +// fn convert_from(from: Dim) -> Dim; +// } +// pub trait ConvertTo { +// type Output; +// fn convert_to(self) -> Self::Output; +// } + + /** Used for implementing unary members of `V` for `Dim` @@ -312,7 +372,7 @@ macro_rules! dim_impl_unary { ($Trait:ident, $fun:ident, $op:ident, $In:ty => $O type Output; fn $fun(self) -> Self::Output; } - impl $Trait for Dim where D: Dimension + $op, ::Output: Dimension { + impl $Trait for Dim where D: $op, ::Output: Dimension { type Output = Dim<::Output, $Out>; fn $fun(self) -> Self::Output { Dim::new( (self.0).$fun() ) } } @@ -409,7 +469,7 @@ dim_fmt!(UpperExp, "{:E} {}"); //------------------------------------------------------------------------------ // Traits from std::cmp //------------------------------------------------------------------------------ -impl PartialEq> for Dim where Dl: Dimension + Same, Dr: Dimension, Vl: PartialEq { +impl PartialEq> for Dim where Dl: Same, Vl: PartialEq { fn eq(&self, other: &Dim) -> bool { (self.0).eq(&(other.0)) } @@ -417,9 +477,9 @@ impl PartialEq> for Dim where Dl: Dimension (self.0).ne(&(other.0)) } } -impl Eq for Dim {} +impl Eq for Dim {} -impl PartialOrd> for Dim where Dl: Dimension + Same, Dr: Dimension, Vl: PartialOrd { +impl PartialOrd> for Dim where Dl: Same, Vl: PartialOrd { fn partial_cmp(&self, other: &Dim) -> Option { (self.0).partial_cmp(&(other.0)) } @@ -436,7 +496,7 @@ impl PartialOrd> for Dim where Dl: Dimension (self.0).ge(&(other.0)) } } -impl Ord for Dim { +impl Ord for Dim { fn cmp(&self, other: &Self) -> Ordering { (self.0).cmp(&(other.0)) } @@ -447,36 +507,35 @@ impl Ord for Dim { /// Multiplying! impl Mul> for Dim - where Dl: Dimension + Mul, Dr: Dimension, Vl: Mul,
>::Output: Dimension { - type Output = Dim<
>::Output, >::Output>; + where Dl: Dimension + Mul, Dr: Dimension, Vl: Mul,
>::Output: Dimension +{ + type Output = Dim<
>::Output, >::Output>; - #[inline] - fn mul(self, rhs: Dim) -> Self::Output { - Dim::new(self.0 * rhs.0) - } + #[inline] + fn mul(self, rhs: Dim) -> Self::Output { + Dim::new(self.0 * rhs.0) + } } /// Scalar multiplication (with scalar on RHS)! -impl Mul for Dim - where D: Dimension, V: Mul, RHS: NotDim { - type Output = Dim>::Output>; - #[inline] - fn mul(self, rhs: RHS) -> Dim>::Output> { - Dim(self.0 * rhs, PhantomData) - } +impl Mul for Dim where V: Mul, RHS: NotDim { + type Output = Dim>::Output>; + #[inline] + fn mul(self, rhs: RHS) -> Dim>::Output> { + Dim(self.0 * rhs, PhantomData) } +} /// Scalar multiplication (with scalar on LHS)! macro_rules! dim_lhs_mult { ($t: ty) => ( - impl> Mul> for $t - where D: Dimension { - type Output = Dim>::Output>; - #[inline] - fn mul(self, rhs: Dim) -> Self::Output { - Dim( rhs.0 * self, PhantomData ) - } + impl Mul> for $t where $t: Mul { + type Output = Dim>::Output>; + #[inline] + fn mul(self, rhs: Dim) -> Self::Output { + Dim( self * rhs.0, PhantomData ) } + } ); } dim_lhs_mult!(f32); @@ -495,36 +554,34 @@ dim_lhs_mult!(usize); /// Dividing! impl Div> for Dim - where Dl: Dimension + Div, Dr: Dimension, Vl: Div,
>::Output: Dimension { - type Output = Dim<
>::Output, >::Output>; - #[inline] - fn div(self, rhs: Dim) -> Dim<
>::Output, >::Output> { - Dim(self.0 / rhs.0, PhantomData) - } + where Dl: Dimension + Div, Dr: Dimension, Vl: Div,
>::Output: Dimension +{ + type Output = Dim<
>::Output, >::Output>; + #[inline] + fn div(self, rhs: Dim) -> Dim<
>::Output, >::Output> { + Dim(self.0 / rhs.0, PhantomData) } +} /// Scalar division (with scalar on RHS)! -impl Div for Dim - where D: Dimension, V: Div, RHS: NotDim { - type Output = Dim>::Output>; - #[inline] - fn div(self, rhs: RHS) -> Dim>::Output> { - Dim(self.0 / rhs, PhantomData) - } +impl Div for Dim where V: Div, RHS: NotDim { + type Output = Dim>::Output>; + #[inline] + fn div(self, rhs: RHS) -> Dim>::Output> { + Dim(self.0 / rhs, PhantomData) } +} /// Scalar division (with scalar on LHS)! -// fixme: Switch to Dim's impl of Recip? macro_rules! dim_lhs_div { ($t: ty) => ( - impl Div> for $t - where D: Dimension + Recip, ::Output: Dimension { - type Output = Dim<::Output, <$t as Div>::Output>; - #[inline] - fn div(self, rhs: Dim) -> Self::Output { - Dim( self / rhs.0, PhantomData ) - } + impl Div> for $t where D: Recip, ::Output: Dimension, $t: Div { + type Output = Dim<::Output, <$t as Div>::Output>; + #[inline] + fn div(self, rhs: Dim) -> Self::Output { + Dim( self / rhs.0, PhantomData ) } + } ); } dim_lhs_div!(f32); @@ -545,7 +602,7 @@ dim_lhs_div!(usize); macro_rules! dim_unary { ($Trait:ident, $op: ident, $($fun:ident),*) => ( impl $Trait for Dim - where D: Dimension + $op, V: $Trait, >::Output: Dimension { + where D:$op, V: $Trait, >::Output: Dimension { type Output = Dim<>::Output, ::Output>; #[inline] $(fn $fun(self) -> Dim<>::Output, ::Output> { @@ -601,7 +658,7 @@ macro_rules! cast_from { ); } -impl FromPrimitive for Dim where D: Dimension, V: FromPrimitive { +impl FromPrimitive for Dim where V: FromPrimitive { cast_from!(from_i64, i64); cast_from!(from_u64, u64); cast_from!(from_isize, isize); @@ -624,7 +681,7 @@ macro_rules! cast_to { ); } -impl ToPrimitive for Dim where D: Dimension, V: ToPrimitive { +impl ToPrimitive for Dim where V: ToPrimitive { cast_to!(to_i64, i64); cast_to!(to_u64, u64); cast_to!(to_isize, isize); @@ -639,7 +696,7 @@ impl ToPrimitive for Dim where D: Dimension, V: ToPrimitive { cast_to!(to_f64, f64); } -impl NumCast for Dim where D: Dimension, V: NumCast { +impl NumCast for Dim where V: NumCast { #[inline] fn from(n: N) -> Option where N: ToPrimitive { match NumCast::from(n) { @@ -650,20 +707,20 @@ impl NumCast for Dim where D: Dimension, V: NumCast { } //------------------------------------------------------------------------------ -impl ::std::num::Zero for Dim where D: Dimension, V: ::std::num::Zero { - fn zero() -> Self { - Dim::new(V::zero()) - } -} +// impl ::std::num::Zero for Dim where V: ::std::num::Zero { +// fn zero() -> Self { +// Dim::new(V::zero()) +// } +// } //------------------------------------------------------------------------------ // DIMENSIONLESS THINGS HERE //------------------------------------------------------------------------------ -impl ::std::num::One for Dim where D: Dimensionless + Mul, V: ::std::num::One + Mul { - fn one() -> Self { - Dim::new(V::one()) - } -} +// impl ::std::num::One for Dim where D: Dimensionless + Mul, V: ::std::num::One + Mul { +// fn one() -> Self { +// Dim::new(V::one()) +// } +// } //------------------------------------------------------------------------------ // Num @@ -743,3 +800,4 @@ impl ::std::num::One for Dim where D: Dimensionless + Mul, V: ::s // } + diff --git a/src/lib.rs b/src/lib.rs index 33c830e1..52b1efbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ For in depth tutorials, check [here](http://paholg.com/project/dimensioned). html_root_url = "http://paholg.com/dimensioned")] #![warn(missing_docs)] -#![feature(optin_builtin_traits, zero_one, const_fn)] +#![feature(optin_builtin_traits, const_fn)] #![feature(type_macros)] @@ -28,5 +28,6 @@ pub mod dimensioned; #[macro_use] mod make_units; -pub mod si; -pub mod cgs; +pub mod unit_systems; +pub use unit_systems::{si, cgs, mks}; + diff --git a/src/make_units.rs b/src/make_units.rs index a8638e1e..ccd8c5d0 100644 --- a/src/make_units.rs +++ b/src/make_units.rs @@ -141,7 +141,7 @@ macro_rules! make_units_adv { impl<$($Type: Integer),*> Dimension for $System<$($Type),*> {} // using $Type and $constant for these traits is confusing. It should really be $Type_Left and - // $Type_Right or something, but as far as I can tell, that is not supported by Rust + // $Type_Right or something, but that is not yet supported by Rust #[allow(non_camel_case_types)] impl<$($Type),*, $($constant),*> Mul<$System<$($constant),*>> for $System<$($Type),*> where $($Type: Integer + Add<$constant>),*, @@ -149,34 +149,34 @@ macro_rules! make_units_adv { $(<$Type as Add<$constant>>::Output: Integer),*, $System<$(<$Type as Add<$constant>>::Output),*>: Dimension, { - type Output = $System<$(<$Type as Add<$constant>>::Output),*>; - #[allow(unused_variables)] - fn mul(self, rhs: $System<$($constant),*>) -> Self::Output { unreachable!() } - } + type Output = $System<$(<$Type as Add<$constant>>::Output),*>; + #[allow(unused_variables)] + fn mul(self, rhs: $System<$($constant),*>) -> Self::Output { unreachable!() } + } #[allow(non_camel_case_types)] impl<$($Type),*, $($constant),*> Div<$System<$($constant),*>> for $System<$($Type),*> where $($Type: Integer + Sub<$constant>),*, $($constant: Integer),*, $(<$Type as Sub<$constant>>::Output: Integer),* { - type Output = $System<$(<$Type as Sub<$constant>>::Output),*>; - #[allow(unused_variables)] - fn div(self, rhs: $System<$($constant),*>) -> Self::Output { unreachable!() } - } + type Output = $System<$(<$Type as Sub<$constant>>::Output),*>; + #[allow(unused_variables)] + fn div(self, rhs: $System<$($constant),*>) -> Self::Output { unreachable!() } + } impl<$($Type),*, RHS> Pow for $System<$($Type),*> where $($Type: Integer + Mul),*, RHS: Integer, $(<$Type as Mul>::Output: Integer),* { - type Output = $System<$(<$Type as Mul>::Output),*>; - #[allow(unused_variables)] - fn pow(rhs: RHS) -> Self::Output { unreachable!() } - } + type Output = $System<$(<$Type as Mul>::Output),*>; + #[allow(unused_variables)] + fn pow(rhs: RHS) -> Self::Output { unreachable!() } + } impl<$($Type),*, RHS> Root for $System<$($Type),*> where $($Type: Integer + Div),*, RHS: Integer, $(<$Type as Div>::Output: Integer),* { - type Output = $System<$(<$Type as Div>::Output),*>; - #[allow(unused_variables)] - fn root(radicand: RHS) -> Self::Output { unreachable!() } - } + type Output = $System<$(<$Type as Div>::Output),*>; + #[allow(unused_variables)] + fn root(radicand: RHS) -> Self::Output { unreachable!() } + } impl<$($Type),*> Recip for $System<$($Type),*> where $($Type: Integer + Neg),*, $(<$Type as Neg>::Output: Integer),* { - type Output = $System<$(<$Type as Neg>::Output),*>; - fn recip(self) -> Self::Output { unreachable!() } - } + type Output = $System<$(<$Type as Neg>::Output),*>; + fn recip(self) -> Self::Output { unreachable!() } + } fn pretty_dim(roots: [i32; count_args!($($Type),*)], exps: [i32; count_args!($($Type),*)], tokens: [&'static str; count_args!($($Type),*)]) -> String { @@ -184,8 +184,14 @@ macro_rules! make_units_adv { for ((&root, &exp), &token) in roots.iter().zip(exps.iter()).zip(tokens.iter()) { let __temp: (&'static str, String) = match exp { 0 => ("", "".to_owned()), - 1 => (token, "*".to_owned()), - _ => (token, format!("^{}*", exp/root)), + _ if exp == root => (token, "*".to_owned()), + _ => { + if exp % root == 0 { + (token, format!("^{}*", exp/root)) + } else { + (token, format!("^{:.2}*", exp as f32/root as f32)) + } + }, }; __string = format!("{}{}{}", __string, __temp.0, __temp.1); } @@ -196,20 +202,20 @@ macro_rules! make_units_adv { impl<$($Type),*> DimToString for $System<$($Type),*> where $($Type: Integer),* { - fn to_string() -> String { - // fixme: add #[allow(unused_variables)] lints for these. Not working - // for me for some reason. - let allowed_roots = [$($Root::to_i32()),*]; - let exponents = [$($Type::to_i32()),*]; - let print_tokens = [$(stringify!($print_as)),*]; - - pretty_dim(allowed_roots, exponents, print_tokens) - } + fn to_string() -> String { + // fixme: add #[allow(unused_variables)] lints for these. Not working + // for me for some reason. + let allowed_roots = [$($Root::to_i32()),*]; + let exponents = [$($Type::to_i32()),*]; + let print_tokens = [$(stringify!($print_as)),*]; + + pretty_dim(allowed_roots, exponents, print_tokens) } + } pub type $Unitless = $System; impl Dimensionless for $Unitless {} - #[allow(non_upper_case_globals)] + #[allow(non_upper_case_globals, dead_code)] pub const $one: Dim<$Unitless, $OneType> = Dim($val, PhantomData); __make_base_types!($System, $($Type, $Root),+ |); diff --git a/src/unit_systems/cgs.rs b/src/unit_systems/cgs.rs new file mode 100644 index 00000000..d814d315 --- /dev/null +++ b/src/unit_systems/cgs.rs @@ -0,0 +1,31 @@ +/*! +The **cgs** module provides a unit system for use with Gaussian CGS units. It was +generated using the `make_units!` macro. See its documentation for more information. + +It will also define derived units, although this is not implemented yet. +*/ + +#![allow(missing_docs)] + +make_units_adv! { + CGS, Unitless, one, f64, 1.0; + base { + P2, Centimeter, cm, cm; + P2, Gram, g, g; + P1, Second, s, s; + } + derived { + } +} + +pub trait FromCGS where Self: Sized { + fn from_cgs(from: Dim, V>) -> Dim; +} + +use mks::{MKS, FromMKS}; +impl FromMKS for CGS + where V: Mul, Meter: Integer, Kilogram: Integer, Second: Integer, { + fn from_mks(from: Dim, V>) -> Dim { + Dim::new( from.0 * 100f64.sqrt().powi(Meter::to_i32()) * 1000f64.sqrt().powi(Kilogram::to_i32()) ) + } +} diff --git a/src/unit_systems/mks.rs b/src/unit_systems/mks.rs new file mode 100644 index 00000000..c60c1885 --- /dev/null +++ b/src/unit_systems/mks.rs @@ -0,0 +1,31 @@ +/*! +The **mks** module provides a unit system for use with Gaussian MKS units. It was +generated using the `make_units!` macro. See its documentation for more information. + +It will also define derived units, although this is not implemented yet. +*/ + +#![allow(missing_docs)] + +make_units_adv! { + MKS, Unitless, one, f64, 1.0; + base { + P2, Meter, m, m; + P2, Kilogram, kg, kg; + P1, Second, s, s; + } + derived { + } +} + +pub trait FromMKS where Self: Sized { + fn from_mks(from: Dim, V>) -> Dim; +} + +use cgs::{CGS, FromCGS}; +impl FromCGS for MKS + where V: Mul, Centimeter: Integer, Gram: Integer, Second: Integer, { + fn from_cgs(from: Dim, V>) -> Dim { + Dim::new( from.0 * 0.01f64.sqrt().powi(Centimeter::to_i32()) * 0.001f64.sqrt().powi(Gram::to_i32()) ) + } +} diff --git a/src/unit_systems/mod.rs b/src/unit_systems/mod.rs new file mode 100644 index 00000000..1f1ef523 --- /dev/null +++ b/src/unit_systems/mod.rs @@ -0,0 +1,3 @@ +pub mod si; +pub mod cgs; +pub mod mks; diff --git a/src/si.rs b/src/unit_systems/si.rs similarity index 100% rename from src/si.rs rename to src/unit_systems/si.rs diff --git a/tests/derived.rs b/tests/derived.rs new file mode 100644 index 00000000..21f244ea --- /dev/null +++ b/tests/derived.rs @@ -0,0 +1,17 @@ +extern crate dimensioned as dim; + +use dim::Dim; +use dim::si::{Meter, Second}; +use std::ops::Div; + +type MPS = >::Output; + +// fn doodoo() -> Dim { +// Dim::new(1.0) +// } + +#[test] +fn derived() { + let v: Dim = Dim::new(1.0); + println!("v: {}!", v); +} diff --git a/tests/dim-ops.rs b/tests/dim-ops.rs index 536ac486..e2022ef2 100644 --- a/tests/dim-ops.rs +++ b/tests/dim-ops.rs @@ -17,5 +17,5 @@ fn pows() { #[test] fn rhs_multiplication() { - let x = m*2.0; + let _ = m*2.0; }