Skip to content

Commit

Permalink
take both Unit and RuntimeUnit in value_in
Browse files Browse the repository at this point in the history
  • Loading branch information
Tehforsch committed Feb 25, 2024
1 parent 85e4eb1 commit b474fe0
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 10 deletions.
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Physical quantities are represented by the `Quantity<S, D>` struct, where `S` is
`Quantity` should behave like its underlying storage type whenever allowed by the dimensions.

## Arithmetics and math
Addition and subtraction of two quantities is allowed if the dimensions match.
Addition and subtraction of two quantities is allowed if the dimensions match:
```rust
let l: Length<f64> = 5.0 * meters + 10.0 * kilometers;
```
Expand All @@ -67,14 +67,14 @@ let l: Length<f64> = 5.0 * meters;
let t: Time<f64> = 2.0 * seconds;
let v: Velocity<f64> = l / t;
```
Addition and subtraction of a `Quantity` and a storage type is possible if and only if `D` is dimensionless.
Addition and subtraction of a `Quantity` and a storage type is possible if and only if `D` is dimensionless:
```rust
let l1: Length<f64> = 5.0 * meters;
let l2: Length<f64> = 10.0 * kilometers;
let x = l1 / l2 - 0.5;
let y = 0.5 - l1 / l2;
```
`Quantity` implements the dimensionless methods of `S`, such as `sin`, `cos`, etc. for dimensionless quantities.
`Quantity` implements the dimensionless methods of `S`, such as `sin`, `cos`, etc. for dimensionless quantities:
```rust
let l1: Length<f64> = 5.0 * meters;
let l2: Length<f64> = 10.0 * kilometers;
Expand All @@ -89,7 +89,7 @@ assert_eq!(area.sqrt(), length);
let vol = length.cubed();
assert_eq!(vol, 8.0 * cubic_meters);
assert_eq!(vol.cbrt(), length);
let questionable = length.powi::<4>();
let foo = length.powi::<4>();
```
Note that unlike its float equivalent, `powi` receives its exponent as a generic instead of as a normal function argument. Exponentiation of dimensionful quantities with an non-constant integer is not supported, since the compiler cannot infer the dimension of the return type. However, dimensionless quantities can be raised to arbitrary powers using `powf`:
```rust
Expand All @@ -105,12 +105,26 @@ let l2 = meters.new(2.0);
assert_eq!(l1, l2);
```
For a full list of the units supported by dimans `SI` module, see [the definitions](src/si.rs).
Composite units can be defined on the spot via multiplication/division of units:
```rust
let v1 = (kilometers / hour).new(3.6);
let v2 = 3.6 * kilometers / hour;
assert_eq!(v1, 1.0 * meters_per_second);
assert_eq!(v2, 1.0 * meters_per_second);
```
Note that at the moment, the creation of quantities via units defined in this composite way incurs
a small performance overhead compared to creation from just a single unit (which is just a single multiplication). This will be fixed once [const_fn_floating_point_arithmetic](https://github.com/rust-lang/rust/issues/57241) or a similar feature is stabilized.

Conversion into the underlying storage type can be done using the `value_in` function:
```rust
let length = 2.0f64 * kilometers;
assert_eq!(format!("{} m", length.value_in(meters)), "2000 m");
```
This also works for composite units:
```rust
let vel = 10.0f64 * meters_per_second;
assert_eq!(format!("{} km/h", vel.value_in(kilometers / hour)), "36 km/h");
```
For dimensionless quantities, `.value()` provides access to the underlying storage types. Alternatively, dimensionless quantities also implement `Deref` for the same operation.
```rust
let l1: Length<f64> = 5.0 * meters;
Expand Down
4 changes: 2 additions & 2 deletions crates/diman_unit_system/src/codegen/quantity_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ impl Codegen {
where
S: core::ops::Div<Magnitude, Output = S> + core::fmt::Debug,
{
pub fn value_in<const R: Magnitude>(self, _: Unit<D, R>) -> S {
self.value_unchecked() / R
pub fn value_in<A: Into<Magnitude>>(self, a: A) -> S {
self.value_unchecked() / a.into()
}
}

Expand Down
12 changes: 12 additions & 0 deletions crates/diman_unit_system/src/codegen/unit_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,18 @@ impl Codegen {
Quantity(val * self.0)
}
}

impl<const D: Dimension, const F: Magnitude> From<Unit<D, F>> for Magnitude {
fn from(_: Unit<D, F>) -> Magnitude {
F
}
}

impl<const D: Dimension> From<RuntimeUnit<D>> for Magnitude {
fn from(unit: RuntimeUnit<D>) -> Magnitude {
unit.0
}
}
}
}

Expand Down
15 changes: 11 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
//! `Quantity` should behave like its underlying storage type whenever allowed by the dimensions.
//!
//! ## Arithmetics and math
//! Addition and subtraction of two quantities is allowed if the dimensions match.
//! Addition and subtraction of two quantities is allowed if the dimensions match:
//! ```
//! # use diman::si::dimensions::{Length};
//! # use diman::si::units::{kilometers, meters};
Expand All @@ -72,7 +72,7 @@
//! let t: Time<f64> = 2.0 * seconds;
//! let v: Velocity<f64> = l / t;
//! ```
//! Addition and subtraction of a `Quantity` and a storage type is possible if and only if `D` is dimensionless.
//! Addition and subtraction of a `Quantity` and a storage type is possible if and only if `D` is dimensionless:
//! ```
//! # #![feature(generic_const_exprs)]
//! # use diman::si::dimensions::{Length};
Expand All @@ -82,7 +82,7 @@
//! let x = l1 / l2 - 0.5;
//! let y = 0.5 - l1 / l2;
//! ```
//! `Quantity` implements the dimensionless methods of `S`, such as `sin`, `cos`, etc. for dimensionless quantities.
//! `Quantity` implements the dimensionless methods of `S`, such as `sin`, `cos`, etc. for dimensionless quantities:
//! ```
//! # #![feature(generic_const_exprs)]
//! # use diman::si::dimensions::{Length};
Expand All @@ -102,7 +102,7 @@
//! let vol = length.cubed();
//! assert_eq!(vol, 8.0 * cubic_meters);
//! assert_eq!(vol.cbrt(), length);
//! let questionable = length.powi::<4>();
//! let foo = length.powi::<4>();
//! ```
//! Note that unlike its float equivalent, `powi` receives its exponent as a generic instead of as a normal function argument. Exponentiation of dimensionful quantities with an non-constant integer is not supported, since the compiler cannot infer the dimension of the return type. However, dimensionless quantities can be raised to arbitrary powers using `powf`:
//! ```
Expand Down Expand Up @@ -140,6 +140,13 @@
//! let length = 2.0f64 * kilometers;
//! assert_eq!(format!("{} m", length.value_in(meters)), "2000 m");
//! ```
//! This also works for composite units:
//! ```
//! # #![feature(generic_const_exprs)]
//! # use diman::si::units::{kilometers, meters_per_second, hour};
//! let vel = 10.0f64 * meters_per_second;
//! assert_eq!(format!("{} km/h", vel.value_in(kilometers / hour)), "36 km/h");
//! ```
//! For dimensionless quantities, `.value()` provides access to the underlying storage types. Alternatively, dimensionless quantities also implement `Deref` for the same operation.
//! ```
//! # #![feature(generic_const_exprs)]
Expand Down

0 comments on commit b474fe0

Please sign in to comment.