-
Notifications
You must be signed in to change notification settings - Fork 97
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
Specifying ad-hoc Quantities and functions generic over Quantities #295
Comments
Another related problem arises in the context of #289:
I have I kinda anticipated this, and wanted to make Ideally I'd like to have
Is it possible to implement these in a generic way? |
type InvertDimension<D> = ISQ<
<uom::typenum::Z0 as uom::lib::ops::Sub<<D as Dimension>::L>>::Output,
<uom::typenum::Z0 as uom::lib::ops::Sub<<D as Dimension>::M>>::Output,
<uom::typenum::Z0 as uom::lib::ops::Sub<<D as Dimension>::T>>::Output,
<uom::typenum::Z0 as uom::lib::ops::Sub<<D as Dimension>::I>>::Output,
<uom::typenum::Z0 as uom::lib::ops::Sub<<D as Dimension>::Th>>::Output,
<uom::typenum::Z0 as uom::lib::ops::Sub<<D as Dimension>::N>>::Output,
<uom::typenum::Z0 as uom::lib::ops::Sub<<D as Dimension>::J>>::Output>;
type PerQuantity<D> = Quantity<InvertDimension<D>, SI<f32>, f32>;
let l1 = Length::new::<meter>(15.0);
let i1: PerQuantity<uom::si::length::Dimension> = 1.0_f32 / l1; 2.a You can make this a generic function for any two types, fn invert2<Q, V>(q: Q) -> <V as std::ops::Div<Q>>::Output
where
V: uom::num::One + std::ops::Div<Q>
{
V::one() / q
} 2.b This can be expanded to be fn invert3<D, U, V>(q: Quantity<D, U, V>) -> <V as std::ops::Div<Quantity<D, U, V>>>::Output
where
D: Dimension + ?Sized,
U: Units<V> + ?Sized,
V: uom::num::Num + uom::Conversion<V> + std::ops::Div<Quantity<D, U, V>>
{
V::one() / q
}
|
To add to this when I first started working on Adding them back in could save end-users from having to write their own |
Thank you so much! This is very useful.
I think you meant: type PerQuantity<D> = Quantity<InvertDimension<D>, SI<f32>, f32>;
What you've given me already should get me over quite a few hurdles. Might take you up on it further down the line. |
Yep, too many changes in the test project and I missed copying over to my reply. |
Probably worth editing it, for the sake of future readers. As it stands, PerQuantity<uom::si::f32::Length> instead of PerQuantity<uom::si::length::Dimension> I'm also struggling with your
I would prefer to use |
While looking at the latest question I realized a
type InvertDimension<D> = ISQ<
<<D as Dimension>::L as uom::lib::ops::Neg>::Output,
<<D as Dimension>::M as uom::lib::ops::Neg>::Output,
<<D as Dimension>::T as uom::lib::ops::Neg>::Output,
<<D as Dimension>::I as uom::lib::ops::Neg>::Output,
<<D as Dimension>::Th as uom::lib::ops::Neg>::Output,
<<D as Dimension>::N as uom::lib::ops::Neg>::Output,
<<D as Dimension>::J as uom::lib::ops::Neg>::Output>; Looks like I never actually used let i1/*: Quantity<InvertDimension<uom::si::length::Dimension>, SI<f32>, f32>*/ = invert2::<_, f32>(l1); fn invert4<Q>(q: Q) -> <f32 as std::ops::Div<Q>>::Output
where
f32: std::ops::Div<Q>,
{
1.0_f32 / q
} I don't think you can make an type InvertQuantity<D, U, V> = Quantity<InvertDimension<D>, U, V>; If |
Unfortunately Meanwhile, I'm stumbling over another problem: I need a system with different base units ( pub mod mmps {
pub mod f32 {
use uom::{ISQ, system};
ISQ!(uom::si, f32, (millimeter, kilogram, picosecond, ampere, kelvin, mole, candela));
}
} That seems to be working OK [aside: it was a bit of a struggle to interpret the docs:
] But I completely fail to make a reciprocal-length type that uses inverse- |
This uncovers a limitation in Line 1631 in 66d3e85
You can also work around this by manually defining the trait based on what the macro does: type Units = dyn uom::si::Units<f32, L = millimeter, M = kilogram, ...>; With the trait alias made public or defined you can use the same diff --git a/examples/base.rs b/examples/base.rs
index b776f32..4677273 100644
--- a/examples/base.rs
+++ b/examples/base.rs
@@ -4,9 +4,19 @@
#[macro_use]
extern crate uom;
+use uom::si::Dimension;
use uom::si::length::{centimeter, meter};
use uom::si::time::second;
+type InvertDimension<D> = uom::si::ISQ<
+ <<D as Dimension>::L as uom::lib::ops::Neg>::Output,
+ <<D as Dimension>::M as uom::lib::ops::Neg>::Output,
+ <<D as Dimension>::T as uom::lib::ops::Neg>::Output,
+ <<D as Dimension>::I as uom::lib::ops::Neg>::Output,
+ <<D as Dimension>::Th as uom::lib::ops::Neg>::Output,
+ <<D as Dimension>::N as uom::lib::ops::Neg>::Output,
+ <<D as Dimension>::J as uom::lib::ops::Neg>::Output>;
+
mod cgs {
ISQ!(uom::si, f32, (centimeter, gram, second, ampere, kelvin, mole, candela));
}
@@ -15,6 +25,7 @@ fn main() {
let l1 = uom::si::f32::Length::new::<meter>(1.0);
let l2 = cgs::Length::new::<centimeter>(1.0);
let t1 = uom::si::f32::Time::new::<second>(15.0);
+ let r1: uom::si::Quantity<InvertDimension<uom::si::length::Dimension>, cgs::Units, f32> = l2.recip();
println!("{}: {:?}", uom::si::length::description(), l1);
println!("{}: {:?}", uom::si::length::description(), l2); In the documentation example it is briefly mentioned where
You're right that this is still confusing because the full context isn't shown. If you look at the example on the Lines 1574 to 1591 in 66d3e85
|
Part of #295 where the need to access the `Units` trait for a user-defined system of units was uncovered.
Just for reference,
|
Interseting! A similar macro should be possible in // Dividing quanties -> subtract dimensions
type Result = ISQ<
<$M1::Dimesion::L as uom::lib::ops::Sub<$M2::Dimension::L>>::Output,
<$M1::Dimension::M as uom::lib::ops::Sub<$M2::Dimension::M>>::Output,
<$M1::Dimension::T as uom::lib::ops::Sub<$M2::Dimension::T>>::Output,
<$M1::Dimension::I as uom::lib::ops::Sub<$M2::Dimension::I>>::Output,
<$M1::Dimension::Th as uom::lib::ops::Sub<$M2::Dimension::Th>>::Output,
<$M1::Dimension::N as uom::lib::ops::Sub<$M2::Dimension::N>>::Output,
<$M1::Dimension::J as uom::lib::ops::Sub<$M2::Dimension::J>>::Output>; |
Part of #295 where the need to access the `Units` trait for a user-defined system of units was uncovered.
Part of #295 where the need to access the `Units` trait for a user-defined system of units was uncovered.
Part of #295 where the need to access the `Units` trait for a user-defined system of units was uncovered.
There is still #295 (comment):
which, AFAICT, seems to be the only remaining unresolved point worth keeping in mind. Should I extract this into its own issue and close this one? |
The problem around which we had to hack, has now been fixed in `uom`, so remove the hack. iliekturtles/uom#295 (comment)
Sorry for the delays, I was off on vacation for a while! If you don't mind, please create a new issue about investigating implementing operations for |
Done: what remains has been exctrated into #362. |
Consider this toy function
Quantity
s such asPerLength
? Can I do better than thisNaively, I would like to write
Per<T>
can be expressed withtypenum
gymnastics, such as used in the return type ofsqrt
.fn invert<T>(x: T)
will probably look more likefn invert<D, U, V>(x: Quantity<D, U, V>)
, but when I try to add the necessary bounds onD
,U
andV
I always end up getting stuck.The text was updated successfully, but these errors were encountered: