pub const COLS: [i32; 8] = [0, 1, 0, -1, 1, 1, -1, -1];
pub const ROWS: [i32; 8] = [1, 0, -1, 0, 1, -1, 1, -1];
pub const NONE: u32 = u32::MAX;
pub const NO_SIM: f32 = f32::NAN;
#[derive(Default)]
pub struct Nodes {
pub level: Vec<u8>, pub cell: Vec<(i32, i32)>, pub frac: Vec<f32>, pub cond: Vec<f32>, pub trav: Vec<f32>, pub weight: Vec<f32>, pub count: Vec<f32>, pub pa: Vec<f32>, pub rim: Vec<bool>, pub sims: Vec<f32>, }
impl Nodes {
pub fn len(&self) -> usize {
self.cond.len()
}
pub fn clear(&mut self) {
self.level.clear();
self.cell.clear();
self.frac.clear();
self.cond.clear();
self.trav.clear();
self.weight.clear();
self.count.clear();
self.pa.clear();
self.rim.clear();
self.sims.clear();
}
pub fn push_copy(&mut self, u: usize, cell: (i32, i32), n_scen: usize) {
self.level.push(self.level[u]);
self.cell.push(cell);
self.frac.push(self.frac[u]);
self.cond.push(self.cond[u]);
self.trav.push(self.trav[u]);
self.weight.push(self.weight[u]);
self.count.push(self.count[u]);
self.pa.push(self.pa[u]);
self.rim.push(self.rim[u]);
self.sims.extend_from_within(u * n_scen..(u + 1) * n_scen);
}
pub fn bytes(&self) -> usize {
self.level.capacity()
+ self.cell.capacity() * 8
+ self.rim.capacity()
+ 4 * (self.frac.capacity()
+ self.cond.capacity()
+ self.trav.capacity()
+ self.weight.capacity()
+ self.count.capacity()
+ self.pa.capacity()
+ self.sims.capacity())
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Edge {
pub to: u32,
pub adj_cost: u32, pub geo_cost: u32, pub adj: f32, pub dist: f32, }
impl Edge {
#[inline]
pub fn new(to: u32, w: f32, dist: f32) -> Self {
let adj = w * dist;
Self {
to,
adj_cost: (adj * 100.0).round() as u32,
geo_cost: (dist * 100.0).round() as u32,
adj,
dist,
}
}
}
#[derive(Default)]
pub struct Csr {
pub offsets: Vec<u32>,
pub edges: Vec<Edge>,
}
impl Csr {
pub fn clear(&mut self) {
self.offsets.clear();
self.offsets.push(0);
self.edges.clear();
}
#[inline]
pub fn close(&mut self) {
self.offsets.push(self.edges.len() as u32);
}
pub fn bytes(&self) -> usize {
self.offsets.capacity() * 4 + self.edges.capacity() * std::mem::size_of::<Edge>()
}
}
pub fn get_edge_neighbours(
i: i32,
j: i32,
level: i32,
offsets: (usize, usize),
) -> ([(i32, i32); 4], usize) {
let (tile_row0_u, tile_col0_u) = offsets;
let tile_row0 = tile_row0_u as i32;
let tile_col0 = tile_col0_u as i32;
#[inline]
fn to_higher_local(idx: i32, level: i32, tile0: i32) -> i32 {
let curr_origin = tile0.div_euclid(level);
let higher_origin = tile0.div_euclid(level * 2);
(curr_origin + idx).div_euclid(2) - higher_origin
}
let target_higher = (
to_higher_local(i, level, tile_row0),
to_higher_local(j, level, tile_col0),
);
const OFFSETS: [(i32, i32); 8] = [
(-1, 0),
(1, 0),
(0, -1),
(0, 1),
(-1, -1),
(-1, 1),
(1, -1),
(1, 1),
];
let mut higher_cells = [(0, 0); 4];
let mut count = 1;
higher_cells[0] = target_higher;
for (di, dj) in OFFSETS {
let ni = i + di;
let nj = j + dj;
let higher = (
to_higher_local(ni, level, tile_row0),
to_higher_local(nj, level, tile_col0),
);
if higher == target_higher {
continue;
}
let mut found = false;
for k in 0..count {
if higher_cells[k] == higher {
found = true;
break;
}
}
if !found && count < higher_cells.len() {
higher_cells[count] = higher;
count += 1;
}
}
(higher_cells, count)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn includes_parent_cell() {
let (cells, count) = get_edge_neighbours(1, 1, 1, (0, 0));
let cells = &cells[..count];
assert_eq!(count, 4);
assert!(cells.contains(&(0, 0)));
assert!(cells.contains(&(1, 0)));
assert!(cells.contains(&(0, 1)));
assert!(cells.contains(&(1, 1)));
}
}