use std::{ sync::{Arc, RwLock}, thread, }; #[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] pub struct Point2d { pub x: f64, pub y: f64, } #[derive(Debug, Default, Clone, Copy)] pub struct PVal { point_index: usize, val: f64, } impl PartialEq for PVal { fn eq(&self, other: &Self) -> bool { self.val == other.val } } impl Eq for PVal {} impl PartialOrd for PVal { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for PVal { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.val .partial_cmp(&other.val) .unwrap_or(std::cmp::Ordering::Equal) } } impl PVal { pub fn new(point: usize, val: f64) -> Self { Self { point_index: point, val, } } pub fn point_index(&self) -> usize { self.point_index } pub fn val(&self) -> f64 { self.val } } #[derive(Debug, Default, Clone)] pub struct Spindex2d { pub xpoints: Arc>>, pub ypoints: Arc>>, pub xs: Arc>>, pub ys: Arc>>, } impl Spindex2d { pub fn new(points: &[Point2d]) -> Self { let mut xpoints = Vec::with_capacity(points.len()); let mut xs = Vec::with_capacity(points.len()); let mut ypoints = Vec::with_capacity(points.len()); let mut ys = Vec::with_capacity(points.len()); thread::scope(|s| { s.spawn(|| { for (i, point) in points.iter().enumerate() { let x = PVal::new(i, point.x); xs.push(x); xpoints.push(i); } }); s.spawn(|| { for (i, point) in points.iter().enumerate() { let y = PVal::new(i, point.y); ys.push(y); ypoints.push(i); } }); }); let index = Self { xpoints: Arc::new(RwLock::new(xpoints)), ypoints: Arc::new(RwLock::new(ypoints)), xs: Arc::new(RwLock::new(xs)), ys: Arc::new(RwLock::new(ys)), }; index.sort(); index } /// This method assumes that the points have the same cardinality and order as the points used /// when constructing this index. May panic if the updated points argument is longer than the /// original points. pub fn update(&self, points: &[Point2d]) { thread::scope(|s| { s.spawn(|| { let mut xs = self.xs.write().unwrap(); let xpoints = self.xpoints.read().unwrap(); for (i, point) in points.iter().enumerate() { let xi = xpoints[i]; let x = PVal::new(i, point.x); xs[xi] = x; } }); s.spawn(|| { let mut ys = self.ys.write().unwrap(); let ypoints = self.ypoints.read().unwrap(); for (i, point) in points.iter().enumerate() { let yi = ypoints[i]; let y = PVal::new(i, point.y); ys[yi] = y; } }); }); self.sort(); } fn sort(&self) { let xs = self.xs.clone(); let points = self.xpoints.clone(); let xhandle = thread::spawn(move || { let mut xs = xs.write().unwrap(); xs.sort_unstable(); let mut points = points.write().unwrap(); for (i, x) in xs.iter().enumerate() { let p = x.point_index; points[p] = i; } }); let ys = self.ys.clone(); let points = self.ypoints.clone(); let yhandle = thread::spawn(move || { let mut ys = ys.write().unwrap(); ys.sort_unstable(); let mut points = points.write().unwrap(); for (i, y) in ys.iter().enumerate() { let p = y.point_index; points[p] = i; } }); xhandle.join().unwrap(); yhandle.join().unwrap(); } }