src/types.rs

branch
dev
changeset 63
7a8a55fd41c0
parent 61
4f468d35fa29
--- a/src/types.rs	Thu Feb 26 11:38:43 2026 -0500
+++ b/src/types.rs	Thu Feb 26 11:36:22 2026 -0500
@@ -21,6 +21,32 @@
 impl ClapFloat for f32 {}
 impl ClapFloat for f64 {}
 
+/// Structure for storing transport statistics
+#[derive(Debug, Clone, Serialize)]
+pub struct TransportInfo<F: Float = f64> {
+    /// Tuple of (untransported mass, source mass)
+    pub untransported_fraction: (F, F),
+    /// Tuple of (|destination mass - transported_mass|, transported mass)
+    pub transport_error: (F, F),
+    /// Number of readjustment iterations for transport
+    pub readjustment_iters: usize,
+    /// ($∫ c_2 dγ , ∫ dγ$)
+    pub dist: (F, F),
+}
+
+#[replace_float_literals(F::cast_from(literal))]
+impl<F: Float> TransportInfo<F> {
+    /// Initialise transport statistics
+    pub fn new() -> Self {
+        TransportInfo {
+            untransported_fraction: (0.0, 0.0),
+            transport_error: (0.0, 0.0),
+            readjustment_iters: 0,
+            dist: (0.0, 0.0),
+        }
+    }
+}
+
 /// Structure for storing iteration statistics
 #[derive(Debug, Clone, Serialize)]
 pub struct IterInfo<F: Float = f64> {
@@ -38,10 +64,8 @@
     pub pruned: usize,
     /// Number of inner iterations since last IterInfo statistic
     pub inner_iters: usize,
-    /// Tuple of (transported mass, source mass)
-    pub untransported_fraction: Option<(F, F)>,
-    /// Tuple of (|destination mass - untransported_mass|, transported mass)
-    pub transport_error: Option<(F, F)>,
+    /// Transport statistis
+    pub transport: Option<TransportInfo<F>>,
     /// Current tolerance
     pub ε: F,
     // /// Solve fin.dim problem for this measure to get the optimal `value`.
@@ -61,10 +85,17 @@
             inner_iters: 0,
             ε: F::NAN,
             // postprocessing : None,
-            untransported_fraction: None,
-            transport_error: None,
+            transport: None,
         }
     }
+
+    /// Get mutable reference to transport statistics, creating it if it is `None`.
+    pub fn get_transport_mut(&mut self) -> &mut TransportInfo<F> {
+        if self.transport.is_none() {
+            self.transport = Some(TransportInfo::new());
+        }
+        self.transport.as_mut().unwrap()
+    }
 }
 
 #[replace_float_literals(F::cast_from(literal))]
@@ -74,7 +105,7 @@
 {
     fn logrepr(&self) -> ColoredString {
         format!(
-            "{}\t| N = {}, ε = {:.8}, 𝔼inner_it = {}, 𝔼ins/mer/pru = {}/{}/{}{}{}",
+            "{}\t| N = {}, ε = {:.2e}, 𝔼inner_it = {}, 𝔼ins/mer/pru = {}/{}/{}{}",
             self.value.logrepr(),
             self.n_spikes,
             self.ε,
@@ -82,23 +113,20 @@
             self.inserted as float / self.this_iters.max(1) as float,
             self.merged as float / self.this_iters.max(1) as float,
             self.pruned as float / self.this_iters.max(1) as float,
-            match self.untransported_fraction {
+            match &self.transport {
                 None => format!(""),
-                Some((a, b)) =>
-                    if b > 0.0 {
-                        format!(", untransported {:.2}%", 100.0 * a / b)
-                    } else {
-                        format!("")
-                    },
-            },
-            match self.transport_error {
-                None => format!(""),
-                Some((a, b)) =>
-                    if b > 0.0 {
-                        format!(", transport error {:.2}%", 100.0 * a / b)
-                    } else {
-                        format!("")
-                    },
+                Some(t) => {
+                    let (a1, b1) = t.untransported_fraction;
+                    let (a2, b2) = t.transport_error;
+                    let (a3, b3) = t.dist;
+                    format!(
+                        ", γ-un/er/d/it = {:.2}%/{:.2}%/{:.2e}/{:.2}",
+                        if b1 > 0.0 { 100.0 * a1 / b1 } else { F::NAN },
+                        if b2 > 0.0 { 100.0 * a2 / b2 } else { F::NAN },
+                        if b3 > 0.0 { a3 / b3 } else { F::NAN },
+                        t.readjustment_iters as float / self.this_iters.max(1) as float,
+                    )
+                }
             }
         )
         .as_str()
@@ -120,10 +148,7 @@
 #[replace_float_literals(F::cast_from(literal))]
 impl<F: Float> Default for RefinementSettings<F> {
     fn default() -> Self {
-        RefinementSettings {
-            tolerance_mult: 0.1,
-            max_steps: 50000,
-        }
+        RefinementSettings { tolerance_mult: 0.1, max_steps: 50000 }
     }
 }
 

mercurial