195 lines
5 KiB
Rust
195 lines
5 KiB
Rust
use std::{
|
|
sync::{Arc, RwLock},
|
|
thread,
|
|
};
|
|
|
|
struct Point2d {
|
|
x: f64,
|
|
y: f64,
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
struct PointRef2d {
|
|
x: usize,
|
|
y: usize,
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, Copy)]
|
|
struct PVal {
|
|
point: 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<std::cmp::Ordering> {
|
|
self.val.partial_cmp(&other.val)
|
|
}
|
|
}
|
|
|
|
impl Ord for PVal {
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
self.partial_cmp(other).unwrap()
|
|
}
|
|
}
|
|
|
|
struct Spindex2d {
|
|
points: Arc<Vec<RwLock<PointRef2d>>>,
|
|
xs: Arc<RwLock<Vec<RwLock<PVal>>>>,
|
|
ys: Arc<RwLock<Vec<RwLock<PVal>>>>,
|
|
}
|
|
|
|
impl Spindex2d {
|
|
pub fn new(points: &[Point2d]) -> Self {
|
|
let mut ps = Vec::with_capacity(points.len());
|
|
let mut xs = Vec::with_capacity(points.len());
|
|
let mut ys = Vec::with_capacity(points.len());
|
|
for (i, point) in points.iter().enumerate() {
|
|
let x = PVal {
|
|
point: i,
|
|
val: point.x,
|
|
};
|
|
xs.push(x.into());
|
|
let y = PVal {
|
|
point: i,
|
|
val: point.y,
|
|
};
|
|
ys.push(y.into());
|
|
let p = PointRef2d { x: i, y: i };
|
|
ps.push(p.into());
|
|
}
|
|
|
|
let index = Self {
|
|
points: ps.into(),
|
|
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]) {
|
|
todo!()
|
|
}
|
|
|
|
fn sort(&self) {
|
|
let xs = self.xs.clone();
|
|
let xhandle = thread::spawn(move || {
|
|
let mut xs = xs.write().unwrap();
|
|
xs.sort_unstable_by(|a, b| {
|
|
let a = a.read().unwrap();
|
|
let b = b.read().unwrap();
|
|
a.cmp(&b)
|
|
});
|
|
});
|
|
|
|
let ys = self.ys.clone();
|
|
let yhandle = thread::spawn(move || {
|
|
let mut ys = ys.write().unwrap();
|
|
ys.sort_unstable_by(|a, b| {
|
|
let a = a.read().unwrap();
|
|
let b = b.read().unwrap();
|
|
a.cmp(&b)
|
|
});
|
|
});
|
|
|
|
xhandle.join().unwrap();
|
|
yhandle.join().unwrap();
|
|
|
|
let xs = self.xs.clone();
|
|
let points = self.points.clone();
|
|
let xhandle = thread::spawn(move || {
|
|
let xs = xs.read().unwrap();
|
|
for (i, x) in xs.iter().enumerate() {
|
|
let x = x.read().unwrap();
|
|
let p = x.point;
|
|
points[p].write().unwrap().x = i;
|
|
}
|
|
});
|
|
|
|
let ys = self.ys.clone();
|
|
let points = self.points.clone();
|
|
let yhandle = thread::spawn(move || {
|
|
let ys = ys.read().unwrap();
|
|
|
|
for (i, y) in ys.iter().enumerate() {
|
|
let y = y.read().unwrap();
|
|
let p = y.point;
|
|
points[p].write().unwrap().y = i;
|
|
}
|
|
});
|
|
|
|
xhandle.join().unwrap();
|
|
yhandle.join().unwrap();
|
|
}
|
|
}
|
|
|
|
use rand::{Rng, SeedableRng};
|
|
use rand_hc::Hc128Rng;
|
|
|
|
fn create_random_points(num_points: usize, seed: &[u8; 32]) -> Vec<[f64; 2]> {
|
|
let mut rng = Hc128Rng::from_seed(*seed);
|
|
(0..num_points).map(|_| rng.random()).collect()
|
|
}
|
|
|
|
use criterion::Criterion;
|
|
use criterion::{criterion_group, criterion_main};
|
|
|
|
const SEED_1: &[u8; 32] = b"Gv0aHMtHkBGsUXNspGU9fLRuCWkZWHZx";
|
|
// const SEED_2: &[u8; 32] = b"km7DO4GeaFZfTcDXVpnO7ZJlgUY7hZiS";
|
|
|
|
const DEFAULT_NUM_POINTS: usize = 1_000_000;
|
|
|
|
fn new_index(c: &mut Criterion) {
|
|
c.bench_function("new index", move |b| {
|
|
let points: Vec<_> = create_random_points(DEFAULT_NUM_POINTS, SEED_1)
|
|
.into_iter()
|
|
.map(|[x, y]| Point2d { x, y })
|
|
.collect();
|
|
|
|
b.iter(|| {
|
|
Spindex2d::new(&points);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn update_positions(c: &mut Criterion) {
|
|
c.bench_function("update positions", move |b| {
|
|
let points: Vec<_> = create_random_points(DEFAULT_NUM_POINTS, SEED_1)
|
|
.into_iter()
|
|
.map(|[x, y]| Point2d { x, y })
|
|
.collect();
|
|
|
|
let mut rng = Hc128Rng::from_seed(*SEED_1);
|
|
|
|
let jitters: Vec<_> = points
|
|
.iter()
|
|
.map(|p| {
|
|
let x = p.x + rng.random_range(-5.0..=5.0);
|
|
let y = p.y + rng.random_range(-5.0..=5.0);
|
|
Point2d { x, y }
|
|
})
|
|
.collect();
|
|
|
|
let index = Spindex2d::new(&points);
|
|
let mut round = 0;
|
|
b.iter(|| todo!());
|
|
});
|
|
}
|
|
|
|
//fn reuse_index(_c: &mut Criterion) {}
|
|
|
|
criterion_group!(benches, new_index);
|
|
criterion_main!(benches);
|