use std::cmp::Ordering;
use std::ops::Range;
#[cfg(feature = "rayon")]
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
use crate::indices::MutableIndices;
use crate::r#type::IndexableNum;
use crate::rtree::sort::util::{apply_permutation, k_block_sort_by};
use crate::rtree::sort::{Sort, SortParams};
#[derive(Debug, Clone, Copy)]
pub struct STRSort;
impl<N: IndexableNum> Sort<N> for STRSort {
fn sort(params: &mut SortParams<N>, boxes: &mut [N], indices: &mut MutableIndices) {
let two = N::from(2).unwrap();
let num_leaf_nodes = (params.num_items as f64 / params.node_size as f64).ceil();
let num_items_per_slice = {
let num_vertical_slices = num_leaf_nodes.sqrt().ceil() as usize;
num_vertical_slices * params.node_size
};
let mut center_with_indices: Vec<(N, u32)> = Vec::with_capacity(params.num_items);
for i in 0..params.num_items {
let min_x = boxes[i * 4];
let max_x = boxes[(i * 4) + 2];
let center_x = (min_x + max_x) / two;
center_with_indices.push((center_x, 0));
}
sort(
&mut center_with_indices,
boxes,
indices,
0..params.num_items,
num_items_per_slice,
);
center_with_indices.clear();
for i in 0..params.num_items {
let min_y = boxes[(i * 4) + 1];
let max_y = boxes[(i * 4) + 3];
let center_y = (min_y + max_y) / two;
center_with_indices.push((center_y, 0));
}
#[cfg(feature = "rayon")]
{
let center_slices = center_with_indices
.chunks_mut(num_items_per_slice)
.collect::<Vec<_>>();
let boxes_slices = boxes
.chunks_mut(num_items_per_slice * 4)
.collect::<Vec<_>>();
let indices_slices = indices.chunks_mut(num_items_per_slice);
center_slices
.into_par_iter()
.zip(boxes_slices)
.zip(indices_slices)
.for_each(|((center_chunk, boxes_chunk), mut indices_chunk)| {
let chunk_len = center_chunk.len();
sort(
center_chunk,
boxes_chunk,
&mut indices_chunk,
0..chunk_len,
params.node_size,
);
})
}
#[cfg(not(feature = "rayon"))]
{
for partition_start in (0..params.num_items).step_by(num_items_per_slice) {
let partition_end = (partition_start + num_items_per_slice).min(params.num_items);
sort(
&mut center_with_indices,
boxes,
indices,
partition_start..partition_end,
params.node_size,
);
}
}
}
}
fn sort<N: IndexableNum>(
center_with_indices: &mut [(N, u32)],
boxes: &mut [N],
indices: &mut MutableIndices,
range: Range<usize>,
node_size: usize,
) {
let center_with_indices = &mut center_with_indices[range.clone()];
for (idx, val) in center_with_indices.iter_mut().enumerate() {
val.1 = idx as u32;
}
let boxes = &mut boxes[range.start * 4..range.end * 4];
let mut indices = match indices {
MutableIndices::U16(arr) => MutableIndices::U16(&mut arr[range]),
MutableIndices::U32(arr) => MutableIndices::U32(&mut arr[range]),
};
k_block_sort_by(center_with_indices, node_size, |&a, &b| {
a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal)
});
apply_permutation(center_with_indices, boxes, &mut indices);
}