paholg / dimensioned

Compile-time dimensional analysis for various unit systems using Rust's type system.
https://crates.io/crates/dimensioned
MIT License
300 stars 23 forks source link

Any good idea how to integrate with `ordered_float`? #75

Open TonalidadeHidrica opened 2 years ago

TonalidadeHidrica commented 2 years ago

Sometimes we want to sort a list of physical quantities. For such purpose, ordered_float is useful; we want to handle with Vec<Meter<OrderedFloat<f64>>>. However, useful constants like M and KG are defined only for primitive types, so there seems no really easy way to multiply quantities. Any idea how to deal with such situation? Currently I'm thinking of making a module named ordered_float_f64_consts or something, copying entire contents of f64consts (expanded by cargo-expand) to my project. Maybe it would be useful if this library provides a macro for defining arbitrary-type constants for existing unit system.

Thanks for this amazing project, by the way! I'm enjoying exploring the type-safety world of physical computations.

paholg commented 2 years ago

I like the idea of allowing custom types for consts-generation. I'm (slowly) rewriting dimensioned to use proc-macros, so now is probably not the best time to add it.

It doesn't get you all the functionality you want, but you could define a trait to inject OrderedFloat inside a, say, SI type:

use dimensioned::si::{Meter, M, SI};
use ordered_float::OrderedFloat;

pub trait Wrap {
    type Output;

    fn wrap(self) -> Self::Output;
}

impl<U, V> Wrap for SI<V, U> {
    type Output = SI<OrderedFloat<V>, U>;

    fn wrap(self) -> Self::Output {
        SI::new(OrderedFloat(self.value_unsafe))
    }
}

fn main() {
    let mut v: Vec<Meter<OrderedFloat<f64>>> = Vec::new();

    v.push((7.0 * M).wrap());
}
TonalidadeHidrica commented 2 years ago

Thanks. That's indeed the most sensible way to do that. Another problem is that it is hard to do arithmetic operations between ordered-float-si-values, but maybe we should unwrap them before calculating, and only use the wrapped value when storing into, say, vecs or btreemaps?

paholg commented 2 years ago

Another problem is that it is hard to do arithmetic operations between ordered-float-si-values

Is it? What issue have you been having? It seem to work fine for me:

    let x = (7.0 * M).wrap();
    let y = (3.0 * M).wrap();
    println!("{}", x + y);