src/lingrid.rs

branch
dev
changeset 124
6aa955ad8122
parent 8
4e09b7829b51
--- a/src/lingrid.rs	Thu May 01 08:40:33 2025 -0500
+++ b/src/lingrid.rs	Thu May 01 13:06:58 2025 -0500
@@ -15,46 +15,54 @@
 iteration over the grid. Additional utility functions are in the [`Grid`] trait.
 */
 
-use crate::types::*;
+use crate::iter::{RestartableIterator, StatefulIterator};
 use crate::loc::Loc;
+use crate::maputil::{map2, map4};
 use crate::sets::Cube;
-use crate::iter::{RestartableIterator, StatefulIterator};
-use crate::maputil::{map2, map4};
-use serde::{Serialize, Deserialize};
+use crate::types::*;
+use serde::{Deserialize, Serialize};
 
 // TODO: rewrite this using crate::sets::Cube.
 
 /// An abstraction of possibly multi-dimensional linear grids.
 ///
 /// `U` is typically a `F` for a `Float` `F` for one-dimensional grids created by `linspace`,
-/// or [`Loc`]`<F, N>` for multi-dimensional grids created by `lingrid`.
+/// or [`Loc`]`<N, F>` for multi-dimensional grids created by `lingrid`.
 /// In the first case `count` of nodes is `usize`, and in the second case `[usize; N]`.
 #[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
 pub struct LinSpace<U, I> {
-    pub start : U,
-    pub end : U,
-    pub count : I,
+    pub start: U,
+    pub end: U,
+    pub count: I,
 }
 
 /// A `N`-dimensional interval divided into an indicated number of equally-spaced nodes along
 /// each dimension.
 #[allow(type_alias_bounds)] // Need it to access F::CompatibleSize.
-pub type LinGrid<F : Float, const N : usize> = LinSpace<Loc<F, N>, [usize; N]>;
+pub type LinGrid<const N: usize, F: Float = f64> = LinSpace<Loc<N, F>, [usize; N]>;
 
 /// Creates a [`LinSpace`] on the real line.
-pub fn linspace<F : Float>(start : F, end : F, count : usize) -> LinSpace<F, usize> {
-    LinSpace{ start : start, end : end, count : count }
+pub fn linspace<F: Float>(start: F, end: F, count: usize) -> LinSpace<F, usize> {
+    LinSpace {
+        start: start,
+        end: end,
+        count: count,
+    }
 }
 
 /// Creates a multi-dimensional linear grid.
 ///
 /// The first and last point in each dimension are the boundaries of the corresponding
 /// dimensions of `cube`, and there are `count` nodes along each dimension.
-pub fn lingrid<F : Float, const N : usize>(
-    cube : &Cube<F, N>,
-    count : &[usize; N]
-) -> LinSpace<Loc<F, N>, [usize; N]> {
-    LinSpace{ start : cube.span_start(), end : cube.span_end(), count : *count }
+pub fn lingrid<F: Float, const N: usize>(
+    cube: &Cube<N, F>,
+    count: &[usize; N],
+) -> LinSpace<Loc<N, F>, [usize; N]> {
+    LinSpace {
+        start: cube.span_start(),
+        end: cube.span_end(),
+        count: *count,
+    }
 }
 
 /// Create a multi-dimensional linear grid with centered nodes.
@@ -63,30 +71,33 @@
 /// inside `cube`. Thus, if $w\_i$ is the width of the cube along dimension $i$, and $n_i$ the number
 /// of nodes, the width of the subcube along this dimension is $h_i = w\_i/(n\_i+1)$, and the first
 /// and last nodes are at a distance $h\_i/2$ from the closest boundary.
-pub fn lingrid_centered<F : Float, const N : usize>(
-    cube : &Cube<F, N>,
-    count : &[usize; N]
-) -> LinSpace<Loc<F, N>, [usize; N]> {
+pub fn lingrid_centered<F: Float, const N: usize>(
+    cube: &Cube<N, F>,
+    count: &[usize; N],
+) -> LinSpace<Loc<N, F>, [usize; N]> {
     let h_div_2 = map2(cube.width(), count, |w, &n| w / F::cast_from(2 * (n + 1)));
     let span_start = map2(cube.span_start(), &h_div_2, |a, &t| a + t).into();
-    let span_end   = map2(cube.span_end(),   &h_div_2, |b, &t| b - t).into();
-    LinSpace{ start : span_start, end : span_end, count : *count }
+    let span_end = map2(cube.span_end(), &h_div_2, |b, &t| b - t).into();
+    LinSpace {
+        start: span_start,
+        end: span_end,
+        count: *count,
+    }
 }
 
-
 /// Iterator over a `LinSpace`.
 #[derive(Clone, Debug)]
 pub struct LinSpaceIterator<F, I> {
-    lingrid : LinSpace<F,I>,
-    current : Option<I>,
+    lingrid: LinSpace<F, I>,
+    current: Option<I>,
 }
 
 /// Abstraction of a linear grid over space `U` with multi-dimensional index set `I`.
 pub trait Grid<U, I> {
     /// Converts a linear index `i` into a grid point.
-    fn entry_linear_unchecked(&self, i : usize) -> U;
+    fn entry_linear_unchecked(&self, i: usize) -> U;
     // Converts a multi-dimensional index `i` into a grid point.
-    fn entry_unchecked(&self, i : &I) -> U;
+    fn entry_unchecked(&self, i: &I) -> U;
 
     // fn entry(&self, i : I) -> Option<F>
 }
@@ -97,7 +108,7 @@
     fn next_index(&mut self) -> Option<I>;
 }
 
-impl<F : Float + CastFrom<I>, I : Unsigned> Grid<F, I> for LinSpace<F, I> {
+impl<F: Float + CastFrom<I>, I: Unsigned> Grid<F, I> for LinSpace<F, I> {
     /*fn entry(&self, i : I) -> Option<F> {
          if i < self.count {
             Some(self.entry_unchecked(i))
@@ -107,37 +118,40 @@
     }*/
 
     #[inline]
-    fn entry_linear_unchecked(&self, i : usize) -> F {
+    fn entry_linear_unchecked(&self, i: usize) -> F {
         self.entry_unchecked(&I::cast_from(i))
     }
 
     #[inline]
-    fn entry_unchecked(&self, i : &I) -> F {
+    fn entry_unchecked(&self, i: &I) -> F {
         let idx = F::cast_from(*i);
-        let scale = F::cast_from(self.count-I::ONE);
-        self.start + (self.end-self.start)*idx/scale
+        let scale = F::cast_from(self.count - I::ONE);
+        self.start + (self.end - self.start) * idx / scale
     }
 }
 
-impl<F : Float + CastFrom<I>, I : Unsigned> GridIteration<F, I>
-for LinSpaceIterator<F, I> {
+impl<F: Float + CastFrom<I>, I: Unsigned> GridIteration<F, I> for LinSpaceIterator<F, I> {
     #[inline]
     fn next_index(&mut self) -> Option<I> {
         match self.current {
-            None if I::ZERO < self.lingrid.count
-                => { self.current = Some(I::ZERO); self.current }
-            Some(v) if v+I::ONE < self.lingrid.count
-                => { self.current = Some(v+I::ONE); self.current }
-            _
-                 => { None }
+            None if I::ZERO < self.lingrid.count => {
+                self.current = Some(I::ZERO);
+                self.current
+            }
+            Some(v) if v + I::ONE < self.lingrid.count => {
+                self.current = Some(v + I::ONE);
+                self.current
+            }
+            _ => None,
         }
     }
 }
 
-impl<F : Float + CastFrom<I>, I : Unsigned, const N : usize> Grid<Loc<F,N>, [I; N]>
-for LinSpace<Loc<F,N>, [I; N]> {
+impl<F: Float + CastFrom<I>, I: Unsigned, const N: usize> Grid<Loc<N, F>, [I; N]>
+    for LinSpace<Loc<N, F>, [I; N]>
+{
     #[inline]
-    fn entry_linear_unchecked(&self, i_ : usize) -> Loc<F, N> {
+    fn entry_linear_unchecked(&self, i_: usize) -> Loc<N, F> {
         let mut i = I::cast_from(i_);
         let mut tmp = [I::ZERO; N];
         for k in 0..N {
@@ -148,58 +162,66 @@
     }
 
     #[inline]
-    fn entry_unchecked(&self, i : &[I; N]) -> Loc<F, N> {
-        let LinSpace{ start, end, count } = self;
+    fn entry_unchecked(&self, i: &[I; N]) -> Loc<N, F> {
+        let LinSpace { start, end, count } = self;
         map4(i, start, end, count, |&ik, &sk, &ek, &ck| {
             let idx = F::cast_from(ik);
-            let scale = F::cast_from(ck-I::ONE);
+            let scale = F::cast_from(ck - I::ONE);
             sk + (ek - sk) * idx / scale
-        }).into()
+        })
+        .into()
     }
 }
 
-impl<F : Float + CastFrom<I>, I : Unsigned, const N : usize> GridIteration<Loc<F,N>, [I; N]>
-for LinSpaceIterator<Loc<F,N>, [I; N]> {
-
+impl<F: Float + CastFrom<I>, I: Unsigned, const N: usize> GridIteration<Loc<N, F>, [I; N]>
+    for LinSpaceIterator<Loc<N, F>, [I; N]>
+{
     #[inline]
     fn next_index(&mut self) -> Option<[I; N]> {
         match self.current {
-            None if self.lingrid.count.iter().all(|v| I::ZERO < *v)  => {
+            None if self.lingrid.count.iter().all(|v| I::ZERO < *v) => {
                 self.current = Some([I::ZERO; N]);
                 self.current
-            },
+            }
             Some(ref mut v) => {
                 for k in 0..N {
                     let a = v[k] + I::ONE;
                     if a < self.lingrid.count[k] {
                         v[k] = a;
-                        return self.current
+                        return self.current;
                     } else {
                         v[k] = I::ZERO;
                     }
                 }
                 None
-            },
-            _ => None
+            }
+            _ => None,
         }
     }
 }
 
-impl<F, I> IntoIterator for LinSpace<F,I>
-where LinSpace<F, I> : Grid<F, I>,
-      LinSpaceIterator<F, I> : GridIteration<F, I> {
+impl<F, I> IntoIterator for LinSpace<F, I>
+where
+    LinSpace<F, I>: Grid<F, I>,
+    LinSpaceIterator<F, I>: GridIteration<F, I>,
+{
     type Item = F;
-    type IntoIter = LinSpaceIterator<F,I>;
+    type IntoIter = LinSpaceIterator<F, I>;
 
     #[inline]
     fn into_iter(self) -> Self::IntoIter {
-        LinSpaceIterator { lingrid : self, current : None }
+        LinSpaceIterator {
+            lingrid: self,
+            current: None,
+        }
     }
 }
 
-impl<F, I> Iterator for LinSpaceIterator<F,I>
-where LinSpace<F, I> : Grid<F, I>,
-      LinSpaceIterator<F, I> : GridIteration<F, I> {
+impl<F, I> Iterator for LinSpaceIterator<F, I>
+where
+    LinSpace<F, I>: Grid<F, I>,
+    LinSpaceIterator<F, I>: GridIteration<F, I>,
+{
     type Item = F;
     #[inline]
     fn next(&mut self) -> Option<F> {
@@ -207,19 +229,24 @@
     }
 }
 
-impl<F, I> StatefulIterator for LinSpaceIterator<F,I>
-where LinSpace<F, I> : Grid<F, I>,
-      LinSpaceIterator<F, I> : GridIteration<F, I> {
+impl<F, I> StatefulIterator for LinSpaceIterator<F, I>
+where
+    LinSpace<F, I>: Grid<F, I>,
+    LinSpaceIterator<F, I>: GridIteration<F, I>,
+{
     #[inline]
     fn current(&self) -> Option<F> {
-        self.current.as_ref().map(|c| self.lingrid.entry_unchecked(c))
+        self.current
+            .as_ref()
+            .map(|c| self.lingrid.entry_unchecked(c))
     }
 }
 
-
-impl<F, I> RestartableIterator for LinSpaceIterator<F,I>
-where LinSpace<F, I> : Grid<F, I>,
-      LinSpaceIterator<F, I> : GridIteration<F, I> {
+impl<F, I> RestartableIterator for LinSpaceIterator<F, I>
+where
+    LinSpace<F, I>: Grid<F, I>,
+    LinSpaceIterator<F, I>: GridIteration<F, I>,
+{
     #[inline]
     fn restart(&mut self) -> Option<F> {
         self.current = None;

mercurial