uom
uom copied to clipboard
Use mathematical fn on generic quantity
Hi,
I am trying to use uom quantities in a generic context. More specifically, I am trying to use mathematical functions such as abs, ceil, floor, signum, etc on these generic quantities.
I have a function that applies kinematics on a quantity. This quantity can be a Length
or a Angle
quantity:
fn complex_kinematics_things<S>(input: S) -> S
where S: std::ops::Add<Output = S> + std::ops::Sub<Output = S> + PartialOrd + Copy + num_traits::identities::Zero {
if input.signum() < S::zero() {
// do something
} else {
// do something else
}
}
However, I am unable to call signum on type S
as it is a generic and the function is defined on the struct itself: https://github.com/iliekturtles/uom/blob/e943f8cb411ef8ab461df794b57dc841a68970c5/src/system.rs#L738-L748
Therefore, there is no way for me to specify that the generic has a signum. If however the quantity would implement the num_traits::sign::Signed
trait, I could specify that trait bound for my generic function.
Would it be possible to modify uom to define the signum function (and others) not on the struct, but instead implement the corresponding num trait? For example:
impl<D, U, V> num_traits::sign::Signed for Quantity<D, U, V>
where
D: Dimension + ?Sized,
U: Units<V> + ?Sized,
V: $crate::sign::Sign + $crate::Conversion<V>,
{
#[inline(always)]
fn signum(self) -> Self {
Quantity {
dimension: $crate::lib::marker::PhantomData,
units: $crate::lib::marker::PhantomData,
value: self.value.signum(),
}
}
// <Insert other fn of Sign here>
}
See also my playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=afacf8c47d6570e864dcd3f3f477f4ce
Thanks in advance! Tommas
Good suggestion. I'm going to clarify the subject. We'll also want to take a look at any other traits similar traits that could be implemented.
Started looking at this and it isn't possible to implement Signed
currently. Signed
inherits Num
which in turn inherits NumOps
which in turn inherits Mul<Rhs, Output = Output>
. uom
's quantity can't implement Mul<Rhs, Output = Output>
because the multiplication of two quantities is a different quantity. e.g. length * length = area
, not length
.
I'm going to leave the issue open for a bit longer to think on it, but we may be stuck unless the trait definition changes.
Hi,
Thank you for looking in to it. I did not investigate that far. The numtraits are indeed to restrictive in that sense. Ideally, numtraits would be modified to allow for this scenario. However, I do not think that is very likely to occur.
Perhaps a second option/plan B is to define the traits in the uom library itself. Although I think this is way less elegant than using the numtraits, it does allow the functions to be used in a generic context.
Thank you for your investigation! Tommas
For your fn complex_kinematics_things<S>
is the S
parameter always a quantity (e.g. Length
, Time
, Velocity
, ...) or completely different types (e.g. Length
, f32
, )? If you're always using quantities then you can adjust your generic parameter / function parameter to accept any quantity.