David Peter 2 years ago
parent
commit
a415a68c63
3 changed files with 130 additions and 142 deletions
  1. 117 104
      insect/src/product.rs
  2. 5 14
      insect/src/quantity.rs
  3. 8 24
      insect/src/unit.rs

+ 117 - 104
insect/src/product.rs

@@ -1,7 +1,8 @@
 use std::ops::{Div, Mul};
 use std::ops::{Div, Mul};
 
 
-use crate::arithmetic::{Exponent, Power, Rational};
+use crate::arithmetic::{Exponent, Power};
 use itertools::Itertools;
 use itertools::Itertools;
+use num_rational::Ratio;
 
 
 pub trait Canonicalize {
 pub trait Canonicalize {
     type MergeKey: PartialEq;
     type MergeKey: PartialEq;
@@ -102,7 +103,11 @@ impl<Factor: Power + Clone + Canonicalize + Ord, const CANONICALIZE: bool>
     Product<Factor, CANONICALIZE>
     Product<Factor, CANONICALIZE>
 {
 {
     pub fn invert(self) -> Self {
     pub fn invert(self) -> Self {
-        self.power(Rational::from_integer(-1))
+        self.powi(-1)
+    }
+
+    pub fn powi(self, exp: i64) -> Self {
+        self.power(Ratio::from_integer(exp))
     }
     }
 }
 }
 
 
@@ -190,127 +195,135 @@ impl<Factor> Iterator for ProductIntoIter<Factor> {
 }
 }
 
 
 #[cfg(test)]
 #[cfg(test)]
-impl Canonicalize for i32 {
-    type MergeKey = ();
+mod tests {
+    use super::*;
+    use crate::arithmetic::Rational;
 
 
-    fn merge_key(&self) -> Self::MergeKey {
-        // merge everything
-    }
+    #[cfg(test)]
+    impl Canonicalize for i32 {
+        type MergeKey = ();
+
+        fn merge_key(&self) -> Self::MergeKey {
+            // merge everything
+        }
+
+        fn merge(self, other: Self) -> Self {
+            self * other
+        }
 
 
-    fn merge(self, other: Self) -> Self {
-        self * other
+        fn is_trivial(&self) -> bool {
+            *self == 1
+        }
     }
     }
 
 
-    fn is_trivial(&self) -> bool {
-        *self == 1
+    #[test]
+    fn multiply() {
+        let product1 = Product::<i32>::from_factors([5, 2, 3]);
+        let product2 = Product::<i32>::from_factors([6, 8]);
+        let result = product1 * product2;
+        assert_eq!(
+            result.into_iter().collect::<Vec<_>>().as_slice(),
+            [5, 2, 3, 6, 8]
+        );
     }
     }
-}
 
 
-#[test]
-fn multiply() {
-    let product1 = Product::<i32>::from_factors([5, 2, 3]);
-    let product2 = Product::<i32>::from_factors([6, 8]);
-    let result = product1 * product2;
-    assert_eq!(
-        result.into_iter().collect::<Vec<_>>().as_slice(),
-        [5, 2, 3, 6, 8]
-    );
-}
+    #[test]
+    fn multiply_canonicalize() {
+        use crate::arithmetic::Rational;
 
 
-#[test]
-fn multiply_canonicalize() {
-    let product1 = Product::<TestUnit, true>::from_factors([
-        TestUnit("meter".into(), Rational::from_integer(1)),
-        TestUnit("second".into(), Rational::from_integer(1)),
-    ]);
-    let product2 = Product::from_factor(TestUnit("meter".into(), Rational::from_integer(2)));
-    let result = product1 * product2;
-    assert_eq!(
-        result.into_vec(),
-        &[
-            TestUnit("meter".into(), Rational::from_integer(3)),
-            TestUnit("second".into(), Rational::from_integer(1))
-        ]
-    );
-}
+        let product1 = Product::<TestUnit, true>::from_factors([
+            TestUnit("meter".into(), Rational::from_integer(1)),
+            TestUnit("second".into(), Rational::from_integer(1)),
+        ]);
+        let product2 = Product::from_factor(TestUnit("meter".into(), Rational::from_integer(2)));
+        let result = product1 * product2;
+        assert_eq!(
+            result.into_vec(),
+            &[
+                TestUnit("meter".into(), Rational::from_integer(3)),
+                TestUnit("second".into(), Rational::from_integer(1))
+            ]
+        );
+    }
 
 
-#[cfg(test)]
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
-struct TestUnit(String, Exponent);
+    #[cfg(test)]
+    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+    struct TestUnit(String, Exponent);
 
 
-#[cfg(test)]
-impl Canonicalize for TestUnit {
-    type MergeKey = String;
+    #[cfg(test)]
+    impl Canonicalize for TestUnit {
+        type MergeKey = String;
 
 
-    fn merge_key(&self) -> Self::MergeKey {
-        self.0.clone()
-    }
+        fn merge_key(&self) -> Self::MergeKey {
+            self.0.clone()
+        }
 
 
-    fn merge(self, other: Self) -> Self {
-        TestUnit(self.0, self.1 + other.1)
-    }
+        fn merge(self, other: Self) -> Self {
+            TestUnit(self.0, self.1 + other.1)
+        }
 
 
-    fn is_trivial(&self) -> bool {
-        use num_traits::Zero;
-        self.1 == Rational::zero()
+        fn is_trivial(&self) -> bool {
+            use num_traits::Zero;
+            self.1 == Rational::zero()
+        }
     }
     }
-}
 
 
-#[cfg(test)]
-impl Power for TestUnit {
-    fn power(self, e: Exponent) -> Self {
-        TestUnit(self.0, self.1 * e)
+    #[cfg(test)]
+    impl Power for TestUnit {
+        fn power(self, e: Exponent) -> Self {
+            TestUnit(self.0, self.1 * e)
+        }
     }
     }
-}
 
 
-#[test]
-fn power() {
-    let product = Product::<TestUnit>::from_factors([
-        TestUnit("meter".into(), Rational::from_integer(1)),
-        TestUnit("second".into(), Rational::from_integer(-2)),
-    ]);
-    let result = product.power(Rational::from_integer(3));
-    assert_eq!(
-        result.into_vec(),
-        &[
-            TestUnit("meter".into(), Rational::from_integer(3)),
-            TestUnit("second".into(), Rational::from_integer(-6))
-        ]
-    );
-}
+    #[test]
+    fn power() {
+        let product = Product::<TestUnit>::from_factors([
+            TestUnit("meter".into(), Rational::from_integer(1)),
+            TestUnit("second".into(), Rational::from_integer(-2)),
+        ]);
+        let result = product.powi(3);
+        assert_eq!(
+            result.into_vec(),
+            &[
+                TestUnit("meter".into(), Rational::from_integer(3)),
+                TestUnit("second".into(), Rational::from_integer(-6))
+            ]
+        );
+    }
 
 
-#[test]
-fn divide() {
-    let product1 = Product::<TestUnit>::from_factors([
-        TestUnit("meter".into(), Rational::from_integer(1)),
-        TestUnit("second".into(), Rational::from_integer(1)),
-    ]);
-    let product2 = Product::from_factor(TestUnit("second".into(), Rational::from_integer(1)));
-    let result = product1 / product2;
-    assert_eq!(
-        result.into_vec(),
-        &[
+    #[test]
+    fn divide() {
+        let product1 = Product::<TestUnit>::from_factors([
             TestUnit("meter".into(), Rational::from_integer(1)),
             TestUnit("meter".into(), Rational::from_integer(1)),
             TestUnit("second".into(), Rational::from_integer(1)),
             TestUnit("second".into(), Rational::from_integer(1)),
-            TestUnit("second".into(), Rational::from_integer(-1))
-        ]
-    );
-}
+        ]);
+        let product2 = Product::from_factor(TestUnit("second".into(), Rational::from_integer(1)));
+        let result = product1 / product2;
+        assert_eq!(
+            result.into_vec(),
+            &[
+                TestUnit("meter".into(), Rational::from_integer(1)),
+                TestUnit("second".into(), Rational::from_integer(1)),
+                TestUnit("second".into(), Rational::from_integer(-1))
+            ]
+        );
+    }
 
 
-#[test]
-fn iter() {
-    let product = Product::<i32>::from_factors([5, 2, 3]);
-    let mut iter = product.iter();
-    assert_eq!(iter.next(), Some(&5));
-    assert_eq!(iter.next(), Some(&2));
-    assert_eq!(iter.next(), Some(&3));
-    assert_eq!(iter.next(), None);
-    assert_eq!(iter.next(), None);
-}
+    #[test]
+    fn iter() {
+        let product = Product::<i32>::from_factors([5, 2, 3]);
+        let mut iter = product.iter();
+        assert_eq!(iter.next(), Some(&5));
+        assert_eq!(iter.next(), Some(&2));
+        assert_eq!(iter.next(), Some(&3));
+        assert_eq!(iter.next(), None);
+        assert_eq!(iter.next(), None);
+    }
 
 
-#[test]
-fn canonicalize() {
-    let mut product = Product::<i32>::from_factors([5, 2, 3]);
-    product.canonicalize();
-    assert_eq!(product.into_iter().collect::<Vec<_>>().as_slice(), [30]);
+    #[test]
+    fn canonicalize() {
+        let mut product = Product::<i32>::from_factors([5, 2, 3]);
+        product.canonicalize();
+        assert_eq!(product.into_iter().collect::<Vec<_>>().as_slice(), [30]);
+    }
 }
 }

+ 5 - 14
insect/src/quantity.rs

@@ -216,8 +216,6 @@ impl std::fmt::Display for Quantity {
 
 
 #[cfg(test)]
 #[cfg(test)]
 mod tests {
 mod tests {
-    use num_rational::Ratio;
-
     use crate::prefix::Prefix;
     use crate::prefix::Prefix;
 
 
     use super::*;
     use super::*;
@@ -262,7 +260,6 @@ mod tests {
         use crate::prefix::Prefix;
         use crate::prefix::Prefix;
 
 
         use approx::assert_relative_eq;
         use approx::assert_relative_eq;
-        use num_rational::Ratio;
 
 
         let meter = Unit::meter();
         let meter = Unit::meter();
         let centimeter = Unit::meter().with_prefix(Prefix::centi());
         let centimeter = Unit::meter().with_prefix(Prefix::centi());
@@ -291,7 +288,7 @@ mod tests {
                 .expect("exponent is scalar");
                 .expect("exponent is scalar");
 
 
             let volume_in_centimeter3 = volume
             let volume_in_centimeter3 = volume
-                .convert_to(&centimeter.power(Ratio::from_integer(3)))
+                .convert_to(&centimeter.powi(3))
                 .expect("conversion succeeds");
                 .expect("conversion succeeds");
             assert_relative_eq!(
             assert_relative_eq!(
                 volume_in_centimeter3.unsafe_value().to_f64(),
                 volume_in_centimeter3.unsafe_value().to_f64(),
@@ -331,7 +328,7 @@ mod tests {
             );
             );
             let expected = Quantity::new(
             let expected = Quantity::new(
                 Number::from_f64(2.0),
                 Number::from_f64(2.0),
-                Unit::meter().power(Ratio::from_integer(2)) * Unit::second(),
+                Unit::meter().powi(2) * Unit::second(),
             );
             );
             assert_eq!(q.full_simplify(), expected);
             assert_eq!(q.full_simplify(), expected);
         }
         }
@@ -370,24 +367,18 @@ mod tests {
         //     let q = Quantity::new(Number::from_f64(5.0), Unit::centimeter() * Unit::meter());
         //     let q = Quantity::new(Number::from_f64(5.0), Unit::centimeter() * Unit::meter());
         //     let expected = Quantity::new(
         //     let expected = Quantity::new(
         //         Number::from_f64(500.0),
         //         Number::from_f64(500.0),
-        //         Unit::centimeter().power(Ratio::from_integer(2)),
+        //         Unit::centimeter().powi(2),
         //     );
         //     );
         //     assert_eq!(q.full_simplify(), expected);
         //     assert_eq!(q.full_simplify(), expected);
         // }
         // }
         {
         {
             let q = Quantity::new(Number::from_f64(5.0), Unit::meter() * Unit::centimeter());
             let q = Quantity::new(Number::from_f64(5.0), Unit::meter() * Unit::centimeter());
-            let expected = Quantity::new(
-                Number::from_f64(0.05),
-                Unit::meter().power(Ratio::from_integer(2)),
-            );
+            let expected = Quantity::new(Number::from_f64(0.05), Unit::meter().powi(2));
             assert_eq!(q.full_simplify(), expected);
             assert_eq!(q.full_simplify(), expected);
         }
         }
         {
         {
             let q = Quantity::new(Number::from_f64(1.0), Unit::hertz() / Unit::second());
             let q = Quantity::new(Number::from_f64(1.0), Unit::hertz() / Unit::second());
-            let expected = Quantity::new(
-                Number::from_f64(1.0),
-                Unit::second().power(Ratio::from_integer(-2)),
-            );
+            let expected = Quantity::new(Number::from_f64(1.0), Unit::second().powi(-2));
             assert_eq!(q.full_simplify(), expected);
             assert_eq!(q.full_simplify(), expected);
         }
         }
     }
     }

+ 8 - 24
insect/src/unit.rs

@@ -206,11 +206,7 @@ impl Unit {
 
 
     #[cfg(test)]
     #[cfg(test)]
     pub fn hertz() -> Self {
     pub fn hertz() -> Self {
-        Self::new_derived(
-            "hertz",
-            Number::from_f64(1.0),
-            Unit::second().power(Ratio::from_integer(-1)),
-        )
+        Self::new_derived("hertz", Number::from_f64(1.0), Unit::second().powi(-1))
     }
     }
 
 
     #[cfg(test)]
     #[cfg(test)]
@@ -318,21 +314,17 @@ mod tests {
         };
         };
 
 
         {
         {
-            let unit = Unit::meter()
-                * Unit::second()
-                * Unit::meter()
-                * Unit::second().power(Ratio::from_integer(2));
+            let unit = Unit::meter() * Unit::second() * Unit::meter() * Unit::second().powi(2);
             assert_same_representation(
             assert_same_representation(
                 unit.canonicalized(),
                 unit.canonicalized(),
-                Unit::meter().power(Ratio::from_integer(2))
-                    * Unit::second().power(Ratio::from_integer(3)),
+                Unit::meter().powi(2) * Unit::second().powi(3),
             );
             );
         }
         }
         {
         {
             let unit = Unit::meter() * Unit::second() * Unit::meter() * Unit::hertz();
             let unit = Unit::meter() * Unit::second() * Unit::meter() * Unit::hertz();
             assert_same_representation(
             assert_same_representation(
                 unit.canonicalized(),
                 unit.canonicalized(),
-                Unit::meter().power(Ratio::from_integer(2)) * Unit::second() * Unit::hertz(),
+                Unit::meter().powi(2) * Unit::second() * Unit::hertz(),
             );
             );
         }
         }
         {
         {
@@ -343,20 +335,12 @@ mod tests {
             );
             );
         }
         }
         {
         {
-            let unit = Unit::meter()
-                * Unit::second()
-                * Unit::meter()
-                * Unit::second().power(Ratio::from_integer(-1));
-            assert_same_representation(
-                unit.canonicalized(),
-                Unit::meter().power(Ratio::from_integer(2)),
-            );
+            let unit = Unit::meter() * Unit::second() * Unit::meter() * Unit::second().powi(-1);
+            assert_same_representation(unit.canonicalized(), Unit::meter().powi(2));
         }
         }
         {
         {
-            let unit = Unit::meter().power(Ratio::from_integer(-1))
-                * Unit::second()
-                * Unit::meter()
-                * Unit::second().power(Ratio::from_integer(-1));
+            let unit =
+                Unit::meter().powi(-1) * Unit::second() * Unit::meter() * Unit::second().powi(-1);
             assert_same_representation(unit.canonicalized(), Unit::scalar());
             assert_same_representation(unit.canonicalized(), Unit::scalar());
         }
         }
     }
     }