--- 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;