-
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
Multiply Ratio and Angle #315
Comments
Short answer is that - .map(|x| x / total_weight)
+ .map(|x| (x / total_weight).into()) The long answer is that The current implementation of multiplication and division sets the output type's I guessed = note: expected enum `Option<Quantity<(dyn Dimension<Th = Z0, N = Z0, I = Z0, L = Z0, M = Z0, T = Z0, Kind = (dyn AngleKind + 'static), J = Z0> + 'static), (dyn uom::si::Units<f32, thermodynamic_temperature = uom::si::thermodynamic_temperature::kelvin, time = uom::si::time::s econd, length = uom::si::length::meter, mass = uom::si::mass::kilogram, electric_current = uom::si::electric_current::ampere, luminous_inten sity = uom::si::luminous_intensity::candela, amount_of_substance = uom::si::amount_of_substance::mole> + 'static), _>>` found enum `Option<Quantity<dyn Dimension<Th = Z0, N = Z0, I = Z0, L = Z0, M = Z0, T = Z0, Kind = (dyn Kind + 'static), J = Z0 >, dyn uom::si::Units<f32, thermodynamic_temperature = uom::si::thermodynamic_temperature::kelvin, time = uom::si::time::second, length = uo m::si::length::meter, mass = uom::si::mass::kilogram, electric_current = uom::si::electric_current::ampere, luminous_intensity = uom::si::lu minous_intensity::candela, amount_of_substance = uom::si::amount_of_substance::mole>, _>>` |
Apologies, I should have stated explicitly that it was obvious to me (so obvious, apparently, that it didn't seem worth mentioning) that Kinds were getting in the way, and why Kinds exist. What I didn't understand is how to work around the problem, which you've explained. Thank you. Going off on a slight tangent, I'm trying to make a generic This version pub fn weighted_mean<T>(data: &[T], weights: &[Ratio]) -> Option<T>
where
T: Mul<Ratio> + Div<Ratio> + Add<Output = T> + Clone,
<T as Mul<Ratio>>::Output: Into<T>,
<T as Div<Ratio>>::Output: Into<T>,
{
assert_eq!(data.len(), weights.len());
let total_weight: Ratio = weights.iter().cloned().sum();
data.iter().cloned()
.zip(weights.iter().cloned())
.map( |(d, w)| (d * w).into())
.reduce(| a, b | a + b )
.map( | x | (x / total_weight).into())
} seems to work. Here are some tests that I'm using, in case it's useful#[cfg(test)]
mod tests {
use super::*;
pub fn mm (x: f32) -> Length { Length::new::<uom::si::length::millimeter>(x) }
pub fn ratio (x: f32) -> Ratio { Ratio::new::<uom::si::ratio ::ratio >(x) }
pub fn radian(x: f32) -> Angle { Angle::new::<uom::si::angle ::radian >(x) }
#[test]
fn length() {
let lengths = vec![ mm(2.0), mm(4.0)];
let weights = vec![ratio(8.0), ratio(2.0)];
let wav: Length = weighted_mean(&lengths, &weights).unwrap();
assert_eq!(wav, mm(2.4))
}
#[test]
fn angle() {
let angles = vec![radian(2.0), radian(4.0)];
let weights = vec![ ratio(8.0), ratio(2.0)];
let wav: Angle = weighted_mean(&angles, &weights).unwrap();
assert_eq!(wav, mm(2.4))
}
} The two tests are essentially identical, with the second using Does this look like a reasonable approach, or have I missed something? |
Everything else looks reasonable. Will be even better once #307 is merged since you'll be able to drop the |
Thanks. Good point about zero-weight-sum. Yes, intended the |
Ratio
andAngle
cannot be multiplied, because of mismatchingKind
s.Why would I want this to work? Imagine a weighted-mean function, here hard-wired for
Length
:I should be able to write such a function for any Quantity, not just
Length
. And it fails to compile ifLength
is replaced withAngle
:The text was updated successfully, but these errors were encountered: