From cd5826818fc1a84ebeb0ee6aae86d74d5aea27e7 Mon Sep 17 00:00:00 2001 From: Hubert Hirtz Date: Fri, 17 Sep 2021 07:02:29 +0200 Subject: [PATCH] Remove most trait bounds in functions by using nalgebra::SVector and SMatrix, which use const generics. --- src/algorithms/fiduccia_mattheyses.rs | 9 +- src/algorithms/k_means.rs | 98 ++------ src/algorithms/kernighan_lin.rs | 21 +- src/algorithms/multi_jagged.rs | 33 +-- src/algorithms/recursive_bisection.rs | 70 +++--- src/algorithms/z_curve.rs | 86 ++----- src/geometry.rs | 320 ++++++++++++-------------- src/lib.rs | 229 +++++------------- src/partition.rs | 16 +- 9 files changed, 280 insertions(+), 602 deletions(-) diff --git a/src/algorithms/fiduccia_mattheyses.rs b/src/algorithms/fiduccia_mattheyses.rs index 542746fd..a2abee42 100644 --- a/src/algorithms/fiduccia_mattheyses.rs +++ b/src/algorithms/fiduccia_mattheyses.rs @@ -1,5 +1,4 @@ use itertools::Itertools; -use nalgebra::{allocator::Allocator, DefaultAllocator, DimName}; use sprs::CsMatView; use crate::partition::Partition; @@ -7,18 +6,14 @@ use crate::PointND; use crate::ProcessUniqueId; use std::collections::HashMap; -pub fn fiduccia_mattheyses<'a, D>( +pub fn fiduccia_mattheyses<'a, const D: usize>( initial_partition: &mut Partition<'a, PointND, f64>, adjacency: CsMatView, max_passes: impl Into>, max_flips_per_pass: impl Into>, max_imbalance_per_flip: impl Into>, max_bad_move_in_a_row: usize, -) where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) { let max_passes = max_passes.into(); let max_flips_per_pass = max_flips_per_pass.into(); let max_imbalance_per_flip = max_imbalance_per_flip.into(); diff --git a/src/algorithms/k_means.rs b/src/algorithms/k_means.rs index 76b393dc..35a0367a 100644 --- a/src/algorithms/k_means.rs +++ b/src/algorithms/k_means.rs @@ -16,12 +16,6 @@ use super::z_curve; use itertools::iproduct; use itertools::Itertools; -use nalgebra::allocator::Allocator; -use nalgebra::base::dimension::{DimDiff, DimSub}; -use nalgebra::DefaultAllocator; -use nalgebra::DimName; -use nalgebra::U1; - /// A wrapper type for ProcessUniqueId /// to enforce that it represents temporary ids /// for the k-means algorithm and not a partition id @@ -33,25 +27,15 @@ type ClusterId = ProcessUniqueId; /// this version shows some noticeable oscillations when imposing a restrictive balance constraint. /// It also skips the bounding boxes optimization which would slightly reduce the complexity of the /// algorithm. -pub fn simplified_k_means( +pub fn simplified_k_means( points: &[PointND], weights: &[f64], num_partitions: usize, imbalance_tol: f64, mut n_iter: isize, hilbert: bool, -) -> Vec -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ - let sfc_order = (f64::from(std::u32::MAX)).log(f64::from(2u32.pow(D::dim() as u32))) as u32; +) -> Vec { + let sfc_order = (f64::from(std::u32::MAX)).log(f64::from(2u32.pow(D as u32))) as u32; let permu = if hilbert { unimplemented!("hilbert curve currently not implemented for n-dimension"); // hilbert_curve::hilbert_curve_reorder(points, 15) @@ -222,25 +206,15 @@ impl Default for BalancedKmeansSettings { } } -pub fn balanced_k_means( +pub fn balanced_k_means( points: &[PointND], weights: &[f64], settings: impl Into>, -) -> Vec -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +) -> Vec { let settings = settings.into().unwrap_or_default(); // sort points with space filling curve - let sfc_order = (f64::from(std::u32::MAX)).log(f64::from(2u32.pow(D::dim() as u32))) as u32; + let sfc_order = (f64::from(std::u32::MAX)).log(f64::from(2u32.pow(D as u32))) as u32; let mut permu = if settings.hilbert { unimplemented!("hilbert curve currently not implemented for n-dimension"); // hilbert_curve::hilbert_curve_reorder(points, 15) @@ -309,21 +283,12 @@ where assignments } -pub fn balanced_k_means_with_initial_partition( +pub fn balanced_k_means_with_initial_partition( points: &[PointND], weights: &[f64], settings: impl Into>, initial_partition: &mut [ProcessUniqueId], -) where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +) { let settings = settings.into().unwrap_or_default(); // validate partition soundness @@ -387,11 +352,7 @@ pub fn balanced_k_means_with_initial_partition( } #[derive(Clone, Copy)] -struct Inputs<'a, D> -where - D: DimName, - DefaultAllocator: Allocator, -{ +struct Inputs<'a, const D: usize> { points: &'a [PointND], weights: &'a [f64], } @@ -414,23 +375,14 @@ struct AlgorithmState<'a> { // - moving each cluster after load balance // - checking delta threshold // - relaxing lower and upper bounds -fn balanced_k_means_iter( +fn balanced_k_means_iter( inputs: Inputs, clusters: Clusters>, &[ClusterId]>, permutation: &mut [usize], state: AlgorithmState, settings: &BalancedKmeansSettings, current_iter: usize, -) where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +) { let Inputs { points, weights } = inputs; let Clusters { centers, @@ -538,23 +490,14 @@ fn balanced_k_means_iter( // - checking partitions imbalance // - increasing of diminishing clusters influence based on their imbalance // - relaxing upper and lower bounds -fn assign_and_balance( +fn assign_and_balance( points: &[PointND], weights: &[f64], permutation: &mut [usize], state: AlgorithmState, clusters: Clusters<&[PointND], &[ClusterId]>, settings: &BalancedKmeansSettings, -) where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +) { let AlgorithmState { assignments, influences, @@ -715,7 +658,7 @@ fn relax_bounds(lbs: &mut [f64], ubs: &mut [f64], distances_moved: &[f64], influ /// Most inner loop of the algorithm that aims to optimize /// clusters assignments -fn best_values( +fn best_values( point: &PointND, centers: &[PointND], center_ids: &[ClusterId], @@ -726,12 +669,7 @@ fn best_values( f64, // new lb f64, // new ub Option, // new cluster assignment for the current point (None if the same assignment is kept) -) -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) { let mut best_value = std::f64::MAX; let mut snd_best_value = std::f64::MAX; let mut assignment = None; @@ -766,11 +704,7 @@ fn erosion(distance_moved: f64, average_cluster_diameter: f64) -> f64 { } // computes the maximum distance between two points in the array -fn max_distance(points: &[PointND]) -> f64 -where - D: DimName, - DefaultAllocator: Allocator, -{ +fn max_distance(points: &[PointND]) -> f64 { iproduct!(points, points) .map(|(p1, p2)| (p1 - p2).norm()) .max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)) diff --git a/src/algorithms/kernighan_lin.rs b/src/algorithms/kernighan_lin.rs index 089ea32c..27f794de 100644 --- a/src/algorithms/kernighan_lin.rs +++ b/src/algorithms/kernighan_lin.rs @@ -8,23 +8,16 @@ use crate::partition::Partition; use crate::ProcessUniqueId; use itertools::Itertools; -use nalgebra::allocator::Allocator; -use nalgebra::DefaultAllocator; -use nalgebra::DimName; use sprs::CsMatView; -pub(crate) fn kernighan_lin<'a, D>( +pub(crate) fn kernighan_lin<'a, const D: usize>( initial_partition: &mut Partition<'a, PointND, f64>, adjacency: CsMatView, max_passes: impl Into>, max_flips_per_pass: impl Into>, max_imbalance_per_flip: impl Into>, max_bad_move_in_a_row: usize, -) where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) { // To adapt Kernighan-Lin to a partition of more than 2 parts, // we apply the algorithm to each pair of adjacent parts (two parts // are adjacent if there exists an element in one part that is linked to @@ -35,7 +28,7 @@ pub(crate) fn kernighan_lin<'a, D>( let max_imbalance_per_flip = max_imbalance_per_flip.into(); let (_points, weights, ids) = initial_partition.as_raw_mut(); - kernighan_lin_2_impl( + kernighan_lin_2_impl::( weights, adjacency.view(), ids, @@ -46,7 +39,7 @@ pub(crate) fn kernighan_lin<'a, D>( ); } -fn kernighan_lin_2_impl( +fn kernighan_lin_2_impl( weights: &[f64], adjacency: CsMatView, initial_partition: &mut [ProcessUniqueId], @@ -54,11 +47,7 @@ fn kernighan_lin_2_impl( max_flips_per_pass: Option, _max_imbalance_per_flip: Option, max_bad_move_in_a_row: usize, -) where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) { let unique_ids = initial_partition .iter() .cloned() diff --git a/src/algorithms/multi_jagged.rs b/src/algorithms/multi_jagged.rs index df116d2b..bce63f63 100644 --- a/src/algorithms/multi_jagged.rs +++ b/src/algorithms/multi_jagged.rs @@ -7,10 +7,6 @@ use approx::Ulps; -use nalgebra::allocator::Allocator; -use nalgebra::DefaultAllocator; -use nalgebra::DimName; - use crate::geometry::*; use rayon::prelude::*; use snowflake::ProcessUniqueId; @@ -150,31 +146,21 @@ fn compute_modifiers( .collect() } -pub fn multi_jagged( +pub fn multi_jagged( points: &[PointND], weights: &[f64], num_parts: usize, max_iter: usize, -) -> Vec -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) -> Vec { let partition_scheme = partition_scheme(num_parts, max_iter); multi_jagged_with_scheme(points, weights, partition_scheme) } -fn multi_jagged_with_scheme( +fn multi_jagged_with_scheme( points: &[PointND], weights: &[f64], partition_scheme: PartitionScheme, -) -> Vec -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) -> Vec { let len = points.len(); let mut permutation = (0..len).into_par_iter().collect::>(); let initial_id = ProcessUniqueId::new(); @@ -194,18 +180,14 @@ where initial_partition } -fn multi_jagged_recurse( +fn multi_jagged_recurse( points: &[PointND], weights: &[f64], permutation: &mut [usize], partition: &AtomicPtr, current_coord: usize, partition_scheme: PartitionScheme, -) where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) { if partition_scheme.num_splits != 0 { let num_splits = partition_scheme.num_splits; @@ -219,7 +201,6 @@ fn multi_jagged_recurse( ); let mut sub_permutations = split_at_mut_many(permutation, &split_positions); - let dim = D::dim(); sub_permutations .par_iter_mut() .zip(partition_scheme.next.unwrap()) @@ -229,7 +210,7 @@ fn multi_jagged_recurse( weights, permu, partition, - (current_coord + 1) % dim, + (current_coord + 1) % D, scheme, ) }); diff --git a/src/algorithms/recursive_bisection.rs b/src/algorithms/recursive_bisection.rs index 11bd919d..5cb3aeb7 100644 --- a/src/algorithms/recursive_bisection.rs +++ b/src/algorithms/recursive_bisection.rs @@ -1,11 +1,5 @@ use crate::geometry::*; -use nalgebra::allocator::Allocator; -use nalgebra::base::dimension::{DimDiff, DimSub}; -use nalgebra::DefaultAllocator; -use nalgebra::DimName; -use nalgebra::U1; - use rayon::prelude::*; use snowflake::ProcessUniqueId; @@ -24,12 +18,11 @@ use std::sync::atomic::{self, AtomicPtr}; /// /// the first component of each couple is the id of an object and /// the second component is the id of the partition to which that object was assigned -pub fn rcb(points: &[PointND], weights: &[f64], n_iter: usize) -> Vec -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +pub fn rcb( + points: &[PointND], + weights: &[f64], + n_iter: usize, +) -> Vec { let len = weights.len(); let mut permutation = (0..len).into_iter().collect::>(); let initial_id = ProcessUniqueId::new(); @@ -46,18 +39,14 @@ where initial_partition } -pub fn rcb_recurse( +pub fn rcb_recurse( points: &[PointND], weights: &[f64], permutation: &mut [usize], partition: &AtomicPtr, n_iter: usize, current_coord: usize, -) where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +) { if n_iter == 0 { // No iteration left. The current // ids become a part of the final partition. @@ -98,7 +87,6 @@ pub fn rcb_recurse( // In the next iteration, the split aixs will // be orthogonal to the current one - let dim = D::dim(); rayon::join( || { rcb_recurse( @@ -107,7 +95,7 @@ pub fn rcb_recurse( left_permu, partition, n_iter - 1, - (current_coord + 1) % dim, + (current_coord + 1) % D, ) }, || { @@ -117,7 +105,7 @@ pub fn rcb_recurse( right_permu, partition, n_iter - 1, - (current_coord + 1) % dim, + (current_coord + 1) % D, ) }, ); @@ -125,12 +113,11 @@ pub fn rcb_recurse( } // pub because it is also useful for multijagged and required for benchmarks -pub fn axis_sort(points: &[PointND], permutation: &mut [usize], current_coord: usize) -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +pub fn axis_sort( + points: &[PointND], + permutation: &mut [usize], + current_coord: usize, +) { permutation.par_sort_by(|i1, i2| { if points[*i1][current_coord] < points[*i2][current_coord] { Ordering::Less @@ -202,16 +189,11 @@ fn half_weight_pos_permu(weights: &[f64], permutation: &[usize]) -> usize { /// The global shape of the data is first considered and the separator is computed to /// be parallel to the inertia axis of the global shape, which aims to lead to better shaped /// partitions. -pub fn rib(points: &[PointND], weights: &[f64], n_iter: usize) -> Vec -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +pub fn rib( + points: &[PointND], + weights: &[f64], + n_iter: usize, +) -> Vec { let mbr = Mbr::from_points(points); let points = points @@ -229,13 +211,13 @@ mod tests { fn gen_point_sample() -> Vec { vec![ - Point2D::new(4., 6.), - Point2D::new(9., 5.), - Point2D::new(-1.2, 7.), - Point2D::new(0., 0.), - Point2D::new(3., 9.), - Point2D::new(-4., 3.), - Point2D::new(1., 2.), + Point2D::from([4., 6.]), + Point2D::from([9., 5.]), + Point2D::from([-1.2, 7.]), + Point2D::from([0., 0.]), + Point2D::from([3., 9.]), + Point2D::from([-4., 3.]), + Point2D::from([1., 2.]), ] } diff --git a/src/algorithms/z_curve.rs b/src/algorithms/z_curve.rs index b7d2179e..dcd3d39e 100644 --- a/src/algorithms/z_curve.rs +++ b/src/algorithms/z_curve.rs @@ -19,12 +19,6 @@ use super::multi_jagged::split_at_mut_many; use crate::geometry::{Mbr, PointND}; -use nalgebra::allocator::Allocator; -use nalgebra::base::dimension::{DimDiff, DimSub}; -use nalgebra::base::U1; -use nalgebra::DefaultAllocator; -use nalgebra::DimName; - use rayon::prelude::*; use snowflake::ProcessUniqueId; @@ -37,22 +31,12 @@ use std::sync::atomic::{self, AtomicPtr}; type HashType = u128; const HASH_TYPE_MAX: HashType = std::u128::MAX; -pub fn z_curve_partition( +pub fn z_curve_partition( points: &[PointND], num_partitions: usize, order: u32, -) -> Vec -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ - let max_order = (HASH_TYPE_MAX as f64).log(f64::from(2u32.pow(D::dim() as u32))) as u32; +) -> Vec { + let max_order = (HASH_TYPE_MAX as f64).log(f64::from(2u32.pow(D as u32))) as u32; assert!( order <= max_order, "Cannot use the z-curve partition algorithm with an order > {} because it would currently overflow hashes capacity", @@ -97,17 +81,12 @@ where } // reorders `permu` to sort points by increasing z-curve hash -fn z_curve_partition_recurse( +fn z_curve_partition_recurse( points: &[PointND], order: u32, mbr: &Mbr, permu: &mut [usize], -) where - D: DimName, - DefaultAllocator: Allocator + Allocator, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +) { // we stop recursion if there is only 1 point left to avoid useless calls if order == 0 || permu.len() <= 1 { return; @@ -128,7 +107,7 @@ fn z_curve_partition_recurse( // instead of traversing the whole array, we can just perform a few binary searches // to find the split positions since the array is already sorted - let mut split_positions = (1..2usize.pow(D::dim() as u32)).collect::>(); + let mut split_positions = (1..2usize.pow(D as u32)).collect::>(); for n in split_positions.iter_mut() { *n = permu .binary_search_by(|idx| { @@ -149,18 +128,8 @@ fn z_curve_partition_recurse( // reorders a slice of Point3D in increasing z-curve order #[allow(unused)] -pub(crate) fn z_curve_reorder(points: &[PointND], order: u32) -> Vec -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ - let max_order = (HASH_TYPE_MAX as f64).log(f64::from(2u32.pow(D::dim() as u32))) as u32; +pub(crate) fn z_curve_reorder(points: &[PointND], order: u32) -> Vec { + let max_order = (HASH_TYPE_MAX as f64).log(f64::from(2u32.pow(D as u32))) as u32; assert!( order <= max_order, "Cannot use the z-curve partition algorithm with an order > {} because it would currently overflow hashes capacity", @@ -175,16 +144,11 @@ where // reorders a slice of indices such that the associated array of Point3D is sorted // by increasing z-order #[allow(unused)] -pub(crate) fn z_curve_reorder_permu(points: &[PointND], permu: &mut [usize], order: u32) -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +pub(crate) fn z_curve_reorder_permu( + points: &[PointND], + permu: &mut [usize], + order: u32, +) { let mbr = Mbr::from_points(points); let hashes = permu .par_iter() @@ -194,11 +158,7 @@ where permu.par_sort_by_key(|idx| hashes[*idx]); } -fn compute_hash(point: &PointND, order: u32, mbr: &Mbr) -> HashType -where - D: DimName, - DefaultAllocator: Allocator + Allocator, -{ +fn compute_hash(point: &PointND, order: u32, mbr: &Mbr) -> HashType { let current_hash = mbr .region(point) .expect("Cannot compute the z-hash of a point outside of the current Mbr."); @@ -206,7 +166,7 @@ where if order == 0 { HashType::from(current_hash) } else { - (2_u128.pow(D::dim() as u32)).pow(order) * HashType::from(current_hash) + (2_u128.pow(D as u32)).pow(order) * HashType::from(current_hash) + compute_hash(point, order - 1, &mbr.sub_mbr(current_hash)) } } @@ -219,14 +179,14 @@ mod tests { #[test] fn test_partition() { let points = vec![ - Point2D::new(0., 0.), - Point2D::new(20., 10.), - Point2D::new(0., 10.), - Point2D::new(20., 0.), - Point2D::new(14., 7.), - Point2D::new(4., 7.), - Point2D::new(14., 2.), - Point2D::new(4., 2.), + Point2D::from([0., 0.]), + Point2D::from([20., 10.]), + Point2D::from([0., 10.]), + Point2D::from([20., 0.]), + Point2D::from([14., 7.]), + Point2D::from([4., 7.]), + Point2D::from([14., 2.]), + Point2D::from([4., 2.]), ]; let ids = z_curve_partition(&points, 4, 1); diff --git a/src/geometry.rs b/src/geometry.rs index 883429c2..7f54cb3e 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -3,32 +3,28 @@ use approx::Ulps; use itertools::Itertools; use nalgebra::allocator::Allocator; -use nalgebra::base::dimension::{DimDiff, DimSub}; +use nalgebra::ArrayStorage; +use nalgebra::Const; use nalgebra::DefaultAllocator; -use nalgebra::DimName; -use nalgebra::U1; -use nalgebra::{SymmetricEigen, Vector2, Vector3, VectorN}; +use nalgebra::DimDiff; +use nalgebra::DimSub; +use nalgebra::SMatrix; +use nalgebra::SVector; +use nalgebra::Storage; use rayon::prelude::*; -pub type Point2D = Vector2; -pub type Point3D = Vector3; -pub type PointND = VectorN; +pub type Point2D = SVector; +pub type Point3D = SVector; +pub type PointND = SVector; +pub type Matrix = SMatrix; #[derive(Debug, Clone)] -pub(crate) struct Aabb -where - D: DimName, - DefaultAllocator: Allocator, -{ +pub(crate) struct Aabb { p_min: PointND, p_max: PointND, } -impl Aabb -where - D: DimName, - DefaultAllocator: Allocator, -{ +impl Aabb { pub fn p_min(&self) -> &PointND { &self.p_min } @@ -37,10 +33,7 @@ where &self.p_max } - pub fn from_points(points: &[PointND]) -> Self - where - >::Buffer: Send + Sync, - { + pub fn from_points(points: &[PointND]) -> Self { if points.len() < 2 { panic!("Cannot create an Aabb from less than 2 points."); } @@ -101,9 +94,8 @@ where // if bi is set (i.e. bi == 1) then the matching region has a i-th coordinates from center[i] to p_max[i] // otherwise, the matching region has a i-th coordinates from p_min[i] to center[i] pub fn sub_aabb(&self, region: u32) -> Self { - let dim = D::dim(); assert!( - region < 2u32.pow(dim as u32), + region < 2u32.pow(D as u32), "Wrong region. Region should be composed of dim bits." ); @@ -215,23 +207,14 @@ where } } -use nalgebra::MatrixN; #[derive(Debug, Clone)] -pub(crate) struct Mbr -where - D: DimName, - DefaultAllocator: Allocator + Allocator, -{ +pub(crate) struct Mbr { aabb: Aabb, - aabb_to_mbr: MatrixN, - mbr_to_aabb: MatrixN, + aabb_to_mbr: Matrix, + mbr_to_aabb: Matrix, } -impl Mbr -where - D: DimName, - DefaultAllocator: Allocator + Allocator, -{ +impl Mbr { pub fn aabb(&self) -> &Aabb { &self.aabb } @@ -246,11 +229,13 @@ where /// The resulting `Mbr` is the smallest Aabb that contains every points of the slice. pub fn from_points(points: &[PointND]) -> Self where - D: DimSub, - DefaultAllocator: - Allocator + Allocator + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, + ArrayStorage: Storage, Const>, + Const: DimSub>, + DefaultAllocator: Allocator> + + Allocator, Const> + + Allocator, Const<1>>>, + >>::Buffer: Send + Sync, + , Const>>::Buffer: Send + Sync, { let weights = points.par_iter().map(|_| 1.).collect::>(); let mat = inertia_matrix(&weights, points); @@ -321,13 +306,7 @@ where } } -pub(crate) fn inertia_matrix(weights: &[f64], points: &[PointND]) -> MatrixN -where - D: DimName, - DefaultAllocator: Allocator + Allocator + Allocator, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +pub(crate) fn inertia_matrix(weights: &[f64], points: &[PointND]) -> Matrix { let total_weight = weights.par_iter().sum::(); let centroid: PointND = weights @@ -340,25 +319,26 @@ where .unwrap() / total_weight; - let ret: MatrixN = weights + weights .par_iter() .zip(points) - .fold_with(MatrixN::::from_element(0.), |acc, (w, p)| { + .fold_with(Matrix::from_element(0.), |acc, (w, p)| { acc + ((p - ¢roid) * (p - ¢roid).transpose()).map(|e| e * w) }) .reduce_with(|a, b| a + b) - .unwrap(); - - ret + .unwrap() } -pub(crate) fn inertia_vector(mat: MatrixN) -> VectorN +pub(crate) fn inertia_vector(mat: Matrix) -> PointND where - D: DimName + DimSub, - DefaultAllocator: Allocator + Allocator + Allocator>, + ArrayStorage: Storage, Const>, + Const: DimSub>, + DefaultAllocator: Allocator> + + Allocator, Const> + + Allocator, Const<1>>>, { - let sym_eigen = SymmetricEigen::new(mat); - let mut indices = (0..D::dim()).collect::>(); + let sym_eigen = mat.symmetric_eigen(); + let mut indices = (0..D).collect::>(); // sort indices in decreasing order indices.as_mut_slice().sort_unstable_by(|a, b| { @@ -367,45 +347,32 @@ where .unwrap() }); - sym_eigen.eigenvectors.column(indices[0]).clone_owned() + sym_eigen.eigenvectors.column(indices[0]).into() } -pub fn householder_reflection(element: &VectorN) -> MatrixN -where - D: DimName, - DefaultAllocator: Allocator + Allocator + Allocator, -{ +pub fn householder_reflection(element: &PointND) -> Matrix { let e0 = canonical_vector(0); // if element is parallel to e0, then the reflection is not valid. // return identity (canonical basis) let norm = element.norm(); if Ulps::default().eq(&(element / norm), &e0) { - return MatrixN::::identity(); + return Matrix::identity(); } let sign = if element[0] > 0. { -1. } else { 1. }; let w = element + sign * e0 * element.norm(); - let id = MatrixN::::identity(); + let id = Matrix::identity(); id - 2. * &w * w.transpose() / (w.transpose() * w)[0] } -pub(crate) fn canonical_vector(nth: usize) -> VectorN -where - D: DimName, - DefaultAllocator: Allocator + Allocator + Allocator, -{ - let mut ret = VectorN::::from_element(0.); +pub(crate) fn canonical_vector(nth: usize) -> PointND { + let mut ret = PointND::from_element(0.); ret[nth] = 1.0; ret } -pub(crate) fn center(points: &[PointND]) -> PointND -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +pub(crate) fn center(points: &[PointND]) -> PointND { assert!(!points.is_empty()); let total = points.len() as f64; points.par_iter().sum::>() / total @@ -420,18 +387,18 @@ mod tests { #[test] fn test_aabb_2d() { let points = vec![ - Point2D::new(1., 2.), - Point2D::new(0., 0.), - Point2D::new(3., 1.), - Point2D::new(5., 4.), - Point2D::new(4., 5.), + Point2D::from([1., 2.]), + Point2D::from([0., 0.]), + Point2D::from([3., 1.]), + Point2D::from([5., 4.]), + Point2D::from([4., 5.]), ]; let aabb = Aabb::from_points(&points); let aspect_ratio = aabb.aspect_ratio(); - assert_ulps_eq!(aabb.p_min, Point2D::new(0., 0.)); - assert_ulps_eq!(aabb.p_max, Point2D::new(5., 5.)); + assert_ulps_eq!(aabb.p_min, Point2D::from([0., 0.])); + assert_ulps_eq!(aabb.p_max, Point2D::from([5., 5.])); assert_ulps_eq!(aspect_ratio, 1.); } @@ -445,17 +412,17 @@ mod tests { #[test] #[should_panic] fn test_aabb2d_invalid_input_2() { - let points = vec![Point2D::new(5., -9.2)]; + let points = vec![Point2D::from([5., -9.2])]; let _aabb = Aabb::from_points(&points); } #[test] fn test_mbr_2d() { let points = vec![ - Point2D::new(5., 3.), - Point2D::new(0., 0.), - Point2D::new(1., -1.), - Point2D::new(4., 4.), + Point2D::from([5., 3.]), + Point2D::from([0., 0.]), + Point2D::from([1., -1.]), + Point2D::from([4., 4.]), ]; let mbr = Mbr::from_points(&points); @@ -467,9 +434,9 @@ mod tests { #[test] fn test_inertia_matrix() { let points = vec![ - Point2D::new(3., 0.), - Point2D::new(0., 3.), - Point2D::new(6., -3.), + Point2D::from([3., 0.]), + Point2D::from([0., 3.]), + Point2D::from([6., -3.]), ]; let weights = vec![1.; 3]; @@ -483,17 +450,17 @@ mod tests { #[test] fn test_inertia_vector_2d() { let points = vec![ - Point2D::new(3., 0.), - Point2D::new(0., 3.), - Point2D::new(6., -3.), + Point2D::from([3., 0.]), + Point2D::from([0., 3.]), + Point2D::from([6., -3.]), ]; let weights = vec![1.; 3]; let mat = inertia_matrix(&weights, &points); let vec = inertia_vector(mat); - let vec = Vector3::new(vec.x, vec.y, 0.); - let expected = Vector3::::new(1., -1., 0.); + let vec = Point3D::from([vec.x, vec.y, 0.]); + let expected = Point3D::from([1., -1., 0.]); eprintln!("{}", vec); @@ -503,18 +470,18 @@ mod tests { #[test] fn test_mbr_distance_to_point_2d() { let points = vec![ - Point2D::new(0., 1.), - Point2D::new(1., 0.), - Point2D::new(5., 6.), - Point2D::new(6., 5.), + Point2D::from([0., 1.]), + Point2D::from([1., 0.]), + Point2D::from([5., 6.]), + Point2D::from([6., 5.]), ]; let mbr = Mbr::from_points(&points); let test_points = vec![ - Point2D::new(2., 2.), - Point2D::new(0., 0.), - Point2D::new(5., 7.), + Point2D::from([2., 2.]), + Point2D::from([0., 0.]), + Point2D::from([5., 7.]), ]; let distances: Vec<_> = test_points @@ -530,32 +497,32 @@ mod tests { #[test] fn test_mbr_center() { let points = vec![ - Point2D::new(0., 1.), - Point2D::new(1., 0.), - Point2D::new(5., 6.), - Point2D::new(6., 5.), + Point2D::from([0., 1.]), + Point2D::from([1., 0.]), + Point2D::from([5., 6.]), + Point2D::from([6., 5.]), ]; let mbr = Mbr::from_points(&points); let center = mbr.center(); - assert_ulps_eq!(center, Point2D::new(3., 3.)) + assert_ulps_eq!(center, Point2D::from([3., 3.])) } #[test] fn test_mbr_contains() { let points = vec![ - Point2D::new(0., 1.), - Point2D::new(1., 0.), - Point2D::new(5., 6.), - Point2D::new(6., 5.), + Point2D::from([0., 1.]), + Point2D::from([1., 0.]), + Point2D::from([5., 6.]), + Point2D::from([6., 5.]), ]; let mbr = Mbr::from_points(&points); - assert!(!mbr.contains(&Point2D::new(0., 0.))); + assert!(!mbr.contains(&Point2D::from([0., 0.]))); assert!(mbr.contains(&mbr.center())); - assert!(mbr.contains(&Point2D::new(5., 4.))); + assert!(mbr.contains(&Point2D::from([5., 4.]))); let (min, max) = mbr.minmax(); @@ -566,19 +533,19 @@ mod tests { #[test] fn test_mbr_quadrant() { let points = vec![ - Point2D::new(0., 1.), - Point2D::new(1., 0.), - Point2D::new(5., 6.), - Point2D::new(6., 5.), + Point2D::from([0., 1.]), + Point2D::from([1., 0.]), + Point2D::from([5., 6.]), + Point2D::from([6., 5.]), ]; let mbr = Mbr::from_points(&points); - let none = mbr.region(&Point2D::new(0., 0.)); - let q1 = mbr.region(&Point2D::new(1.2, 1.2)); - let q2 = mbr.region(&Point2D::new(5.8, 4.9)); - let q3 = mbr.region(&Point2D::new(0.2, 1.1)); - let q4 = mbr.region(&Point2D::new(5.1, 5.8)); + let none = mbr.region(&Point2D::from([0., 0.])); + let q1 = mbr.region(&Point2D::from([1.2, 1.2])); + let q2 = mbr.region(&Point2D::from([5.8, 4.9])); + let q3 = mbr.region(&Point2D::from([0.2, 1.1])); + let q4 = mbr.region(&Point2D::from([5.1, 5.8])); println!("q1 = {:?}", q1); println!("q2 = {:?}", q2); @@ -594,8 +561,7 @@ mod tests { #[test] fn test_householder_reflexion() { - use nalgebra::Vector6; - let el = Vector6::::new_random(); + let el = PointND::<6>::new_random(); let mat = householder_reflection(&el); // check that columns are of norm 1 @@ -621,32 +587,32 @@ mod tests { #[test] fn test_aabb_3d() { let points = vec![ - Point3D::new(1., 2., 0.), - Point3D::new(0., 0., 5.), - Point3D::new(3., 1., 1.), - Point3D::new(5., 4., -2.), - Point3D::new(4., 5., 3.), + Point3D::from([1., 2., 0.]), + Point3D::from([0., 0., 5.]), + Point3D::from([3., 1., 1.]), + Point3D::from([5., 4., -2.]), + Point3D::from([4., 5., 3.]), ]; let aabb = Aabb::from_points(&points); let aspect_ratio = aabb.aspect_ratio(); - assert_ulps_eq!(aabb.p_min, Point3D::new(0., 0., -2.)); - assert_ulps_eq!(aabb.p_max, Point3D::new(5., 5., 5.)); + assert_ulps_eq!(aabb.p_min, Point3D::from([0., 0., -2.])); + assert_ulps_eq!(aabb.p_max, Point3D::from([5., 5., 5.])); assert_ulps_eq!(aspect_ratio, 7. / 5.); } #[test] fn test_mbr_3d() { let points = vec![ - Point3D::new(5., 3., 0.), - Point3D::new(0., 0., 0.), - Point3D::new(1., -1., 0.), - Point3D::new(4., 4., 0.), - Point3D::new(5., 3., 2.), - Point3D::new(0., 0., 2.), - Point3D::new(1., -1., 2.), - Point3D::new(4., 4., 2.), + Point3D::from([5., 3., 0.]), + Point3D::from([0., 0., 0.]), + Point3D::from([1., -1., 0.]), + Point3D::from([4., 4., 0.]), + Point3D::from([5., 3., 2.]), + Point3D::from([0., 0., 2.]), + Point3D::from([1., -1., 2.]), + Point3D::from([4., 4., 2.]), ]; let mbr = Mbr::from_points(&points); @@ -659,16 +625,16 @@ mod tests { #[test] fn test_inertia_vector_3d() { let points = vec![ - Point3D::new(3., 0., 0.), - Point3D::new(0., 3., 3.), - Point3D::new(6., -3., -3.), + Point3D::from([3., 0., 0.]), + Point3D::from([0., 3., 3.]), + Point3D::from([6., -3., -3.]), ]; let weights = vec![1.; 3]; let mat = inertia_matrix(&weights, &points); let vec = inertia_vector(mat); - let expected = Vector3::::new(1., -1., -1.); + let expected = Point3D::from([1., -1., -1.]); eprintln!("{}", vec); @@ -678,25 +644,25 @@ mod tests { #[test] fn test_mbr_distance_to_point_3d() { let points = vec![ - Point3D::new(0., 1., 0.), - Point3D::new(1., 0., 0.), - Point3D::new(5., 6., 0.), - Point3D::new(6., 5., 0.), - Point3D::new(0., 1., 4.), - Point3D::new(1., 0., 4.), - Point3D::new(5., 6., 4.), - Point3D::new(6., 5., 4.), + Point3D::from([0., 1., 0.]), + Point3D::from([1., 0., 0.]), + Point3D::from([5., 6., 0.]), + Point3D::from([6., 5., 0.]), + Point3D::from([0., 1., 4.]), + Point3D::from([1., 0., 4.]), + Point3D::from([5., 6., 4.]), + Point3D::from([6., 5., 4.]), ]; let mbr = Mbr::from_points(&points); let test_points = vec![ - Point3D::new(2., 2., 1.), - Point3D::new(0., 0., 1.), - Point3D::new(5., 7., 1.), - Point3D::new(2., 2., 3.), - Point3D::new(0., 0., 3.), - Point3D::new(5., 7., 3.), + Point3D::from([2., 2., 1.]), + Point3D::from([0., 0., 1.]), + Point3D::from([5., 7., 1.]), + Point3D::from([2., 2., 3.]), + Point3D::from([0., 0., 3.]), + Point3D::from([5., 7., 3.]), ]; let distances: Vec<_> = test_points @@ -715,29 +681,29 @@ mod tests { #[test] fn test_mbr_octant() { let points = vec![ - Point3D::new(0., 1., 0.), - Point3D::new(1., 0., 0.), - Point3D::new(5., 6., 0.), - Point3D::new(6., 5., 0.), - Point3D::new(0., 1., 1.), - Point3D::new(1., 0., 1.), - Point3D::new(5., 6., 1.), - Point3D::new(6., 5., 1.), + Point3D::from([0., 1., 0.]), + Point3D::from([1., 0., 0.]), + Point3D::from([5., 6., 0.]), + Point3D::from([6., 5., 0.]), + Point3D::from([0., 1., 1.]), + Point3D::from([1., 0., 1.]), + Point3D::from([5., 6., 1.]), + Point3D::from([6., 5., 1.]), ]; let mbr = Mbr::from_points(&points); eprintln!("mbr = {:#?}", mbr); - let none = mbr.region(&Point3D::new(0., 0., 0.)); + let none = mbr.region(&Point3D::from([0., 0., 0.])); let octants = vec![ - mbr.region(&Point3D::new(1.2, 1.2, 0.3)), - mbr.region(&Point3D::new(5.8, 4.9, 0.3)), - mbr.region(&Point3D::new(0.2, 1.1, 0.3)), - mbr.region(&Point3D::new(5.1, 5.8, 0.3)), - mbr.region(&Point3D::new(1.2, 1.2, 0.7)), - mbr.region(&Point3D::new(5.8, 4.9, 0.7)), - mbr.region(&Point3D::new(0.2, 1.1, 0.7)), - mbr.region(&Point3D::new(5.1, 5.8, 0.7)), + mbr.region(&Point3D::from([1.2, 1.2, 0.3])), + mbr.region(&Point3D::from([5.8, 4.9, 0.3])), + mbr.region(&Point3D::from([0.2, 1.1, 0.3])), + mbr.region(&Point3D::from([5.1, 5.8, 0.3])), + mbr.region(&Point3D::from([1.2, 1.2, 0.7])), + mbr.region(&Point3D::from([5.8, 4.9, 0.7])), + mbr.region(&Point3D::from([0.2, 1.1, 0.7])), + mbr.region(&Point3D::from([5.1, 5.8, 0.7])), ]; assert_eq!(none, None); assert!(octants.iter().all(|o| o.is_some())); diff --git a/src/lib.rs b/src/lib.rs index 94e8d551..ce800051 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,12 +47,6 @@ pub mod dimension { pub use nalgebra::base::dimension::*; } -use nalgebra::allocator::Allocator; -use nalgebra::base::dimension::{DimDiff, DimSub}; -use nalgebra::DefaultAllocator; -use nalgebra::DimName; -use nalgebra::U1; - use ndarray::ArrayView1; use ndarray::ArrayView2; use sprs::CsMatView; @@ -64,33 +58,21 @@ use crate::partition::*; // Trait that allows conversions from/to different kinds of // points views representation as partitioner inputs // e.g. &[f64], &[PointND], slice from ndarray, ... -pub trait PointsView<'a, D> { - fn to_points_nd(self) -> &'a [PointND] - where - D: DimName, - DefaultAllocator: Allocator; +pub trait PointsView<'a, const D: usize> { + fn to_points_nd(self) -> &'a [PointND]; } -impl<'a, D> PointsView<'a, D> for &'a [f64] { - fn to_points_nd(self) -> &'a [PointND] - where - D: DimName, - DefaultAllocator: Allocator, - { - let dim = D::dim(); - if self.len() % dim != 0 { - panic!("error: tried to convert a &[f64] to a &[PointND] with D = {}, but input slice has len {}", dim, self.len()); +impl<'a, const D: usize> PointsView<'a, D> for &'a [f64] { + fn to_points_nd(self) -> &'a [PointND] { + if self.len() % D != 0 { + panic!("error: tried to convert a &[f64] to a &[PointND] with D = {}, but input slice has len {}", D, self.len()); } - unsafe { std::slice::from_raw_parts(self.as_ptr() as *const PointND, self.len() / dim) } + unsafe { std::slice::from_raw_parts(self.as_ptr() as *const PointND, self.len() / D) } } } -impl<'a, D> PointsView<'a, D> for ArrayView1<'a, f64> { - fn to_points_nd(self) -> &'a [PointND] - where - D: DimName, - DefaultAllocator: Allocator, - { +impl<'a, const D: usize> PointsView<'a, D> for ArrayView1<'a, f64> { + fn to_points_nd(self) -> &'a [PointND] { let slice = self.to_slice().expect( "Cannot convert an ArrayView1 with dicontiguous storage repr to a slice. Try cloning the data into a contiguous array first" ); @@ -98,12 +80,8 @@ impl<'a, D> PointsView<'a, D> for ArrayView1<'a, f64> { } } -impl<'a, D> PointsView<'a, D> for ArrayView2<'a, f64> { - fn to_points_nd(self) -> &'a [PointND] - where - D: DimName, - DefaultAllocator: Allocator, - { +impl<'a, const D: usize> PointsView<'a, D> for ArrayView2<'a, f64> { + fn to_points_nd(self) -> &'a [PointND] { let slice = self.to_slice().expect( "Cannot convert an ArrayView2 with dicontiguous storage repr to a slice. Try cloning the data into a contiguous array first" ); @@ -111,11 +89,7 @@ impl<'a, D> PointsView<'a, D> for ArrayView2<'a, f64> { } } -impl<'a, D> PointsView<'a, D> for &'a [PointND] -where - D: DimName, - DefaultAllocator: Allocator, -{ +impl<'a, const D: usize> PointsView<'a, D> for &'a [PointND] { fn to_points_nd(self) -> &'a [PointND] { // nothing to do self @@ -131,11 +105,7 @@ where /// an existing partition to improve it. /// /// See the [implementors](trait.Partitioner.html#implementors) for more information about the currently available algorithms. -pub trait Partitioner -where - D: DimName, - DefaultAllocator: Allocator, -{ +pub trait Partitioner { fn partition<'a>( &self, points: impl PointsView<'a, D>, @@ -149,22 +119,14 @@ where /// points and associated weights to modify and improve an existing partition (typically generated by a [`Partitioner`](trait.Partitioner.html)). /// /// See the [implementors](trait.PartitionImprover.html#implementors) for more information about the currently available algorithms. -pub trait PartitionImprover -where - D: DimName, - DefaultAllocator: Allocator, -{ +pub trait PartitionImprover { fn improve_partition<'a>( &self, partition: Partition<'a, PointND, f64>, ) -> Partition<'a, PointND, f64>; } -pub trait TopologicPartitioner -where - D: DimName, - DefaultAllocator: Allocator, -{ +pub trait TopologicPartitioner { fn partition<'a>( &self, points: impl PointsView<'a, D>, @@ -173,11 +135,7 @@ where ) -> Partition<'a, PointND, f64>; } -pub trait TopologicPartitionImprover -where - D: DimName, - DefaultAllocator: Allocator, -{ +pub trait TopologicPartitionImprover { fn improve_partition<'a>( &self, partition: Partition<'a, PointND, f64>, @@ -224,26 +182,21 @@ where /// } /// } /// ``` -pub struct Rcb { +pub struct Rcb { pub num_iter: usize, - _marker: PhantomData, + _marker: PhantomData<[u8; D]>, } -impl Rcb { +impl Rcb { pub fn new(num_iter: usize) -> Self { Self { num_iter, - _marker: PhantomData::, + _marker: PhantomData, } } } -impl Partitioner for Rcb -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +impl Partitioner for Rcb { fn partition<'a>( &self, points: impl PointsView<'a, D>, @@ -295,32 +248,22 @@ where /// // there are two different partition /// assert_ne!(ids[1], ids[2]); /// ``` -pub struct Rib { +pub struct Rib { /// The number of iterations of the algorithm. This will yield a partition of `2^num_iter` parts. pub num_iter: usize, - _marker: PhantomData, + _marker: PhantomData<[u8; D]>, } -impl Rib { +impl Rib { pub fn new(num_iter: usize) -> Self { Self { num_iter, - _marker: PhantomData::, + _marker: PhantomData, } } } -impl Partitioner for Rib -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +impl Partitioner for Rib { fn partition<'a>( &self, points: impl PointsView<'a, D>, @@ -385,28 +328,23 @@ where /// } /// } /// ``` -pub struct MultiJagged { +pub struct MultiJagged { pub num_partitions: usize, pub max_iter: usize, - _marker: PhantomData, + _marker: PhantomData<[u8; D]>, } -impl MultiJagged { +impl MultiJagged { pub fn new(num_partitions: usize, max_iter: usize) -> Self { Self { num_partitions, max_iter, - _marker: PhantomData::, + _marker: PhantomData, } } } -impl Partitioner for MultiJagged -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +impl Partitioner for MultiJagged { fn partition<'a>( &self, points: impl PointsView<'a, D>, @@ -462,33 +400,23 @@ where /// assert_eq!(ids[4], ids[5]); /// assert_eq!(ids[6], ids[7]); /// ``` -pub struct ZCurve { +pub struct ZCurve { pub num_partitions: usize, pub order: u32, - _marker: PhantomData, + _marker: PhantomData<[u8; D]>, } -impl ZCurve { +impl ZCurve { pub fn new(num_partitions: usize, order: u32) -> Self { Self { num_partitions, order, - _marker: PhantomData::, + _marker: PhantomData, } } } -impl Partitioner for ZCurve -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +impl Partitioner for ZCurve { fn partition<'a>( &self, points: impl PointsView<'a, D>, @@ -542,31 +470,27 @@ where /// assert_eq!(ids[4], ids[5]); /// assert_eq!(ids[6], ids[7]); /// ``` -pub struct HilbertCurve { +pub struct HilbertCurve { pub num_partitions: usize, pub order: u32, - _marker: PhantomData, } -impl HilbertCurve { +impl HilbertCurve { pub fn new(num_partitions: usize, order: u32) -> Self { Self { num_partitions, order, - _marker: PhantomData::, } } } -use nalgebra::base::U2; - // hilbert curve is only implemented in 2d for now -impl Partitioner for HilbertCurve { +impl Partitioner<2> for HilbertCurve { fn partition<'a>( &self, - points: impl PointsView<'a, U2>, + points: impl PointsView<'a, 2>, _weights: &'a [f64], - ) -> Partition<'a, PointND, f64> { + ) -> Partition<'a, PointND<2>, f64> { let points = points.to_points_nd(); let ids = crate::algorithms::hilbert_curve::hilbert_curve_partition( points, @@ -640,7 +564,7 @@ impl Partitioner for HilbertCurve { /// assert_eq!(ids[6], ids[8]); /// ``` #[derive(Debug, Clone, Copy)] -pub struct KMeans { +pub struct KMeans { pub num_partitions: usize, pub imbalance_tol: f64, pub delta_threshold: f64, @@ -649,7 +573,7 @@ pub struct KMeans { pub erode: bool, pub hilbert: bool, pub mbr_early_break: bool, - _marker: PhantomData, + _marker: PhantomData<[u8; D]>, } // KMeans builder pattern @@ -661,20 +585,12 @@ pub struct KMeans { // .max_balance_iter(12) // .build(); // ``` -#[derive(Debug, Clone, Copy)] -pub struct KMeansBuilder { +#[derive(Debug, Default, Clone, Copy)] +pub struct KMeansBuilder { inner: KMeans, } -impl Default for KMeansBuilder { - fn default() -> Self { - Self { - inner: KMeans::default(), - } - } -} - -impl KMeansBuilder { +impl KMeansBuilder { pub fn build(self) -> KMeans { self.inner } @@ -720,7 +636,7 @@ impl KMeansBuilder { } } -impl KMeans { +impl KMeans { #[allow(clippy::too_many_arguments)] pub fn new( num_partitions: usize, @@ -741,12 +657,12 @@ impl KMeans { erode, hilbert, mbr_early_break, - _marker: PhantomData::, + _marker: PhantomData, } } } -impl Default for KMeans { +impl Default for KMeans { fn default() -> Self { Self { num_partitions: 7, @@ -757,22 +673,12 @@ impl Default for KMeans { erode: false, // for now, `erode` yields` enabled yields wrong results hilbert: true, mbr_early_break: false, // for now, `mbr_early_break` enabled yields wrong results - _marker: PhantomData::, + _marker: PhantomData, } } } -impl PartitionImprover for KMeans -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +impl PartitionImprover for KMeans { fn improve_partition<'a>( &self, partition: Partition<'a, PointND, f64>, @@ -897,12 +803,7 @@ impl KernighanLin { } } -impl TopologicPartitionImprover for KernighanLin -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +impl TopologicPartitionImprover for KernighanLin { fn improve_partition<'a>( &self, mut partition: Partition<'a, PointND, f64>, @@ -1026,12 +927,7 @@ impl FiducciaMattheyses { } } -impl TopologicPartitionImprover for FiducciaMattheyses -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +impl TopologicPartitionImprover for FiducciaMattheyses { fn improve_partition<'a>( &self, mut partition: Partition<'a, PointND, f64>, @@ -1121,12 +1017,7 @@ impl GraphGrowth { } } -impl TopologicPartitioner for GraphGrowth -where - D: DimName, - DefaultAllocator: Allocator, - >::Buffer: Send + Sync, -{ +impl TopologicPartitioner for GraphGrowth { fn partition<'a>( &self, points: impl PointsView<'a, D>, @@ -1157,10 +1048,8 @@ impl Composition { } } -impl Partitioner for Composition +impl Partitioner for Composition where - D: DimName, - DefaultAllocator: Allocator, T: Partitioner, U: PartitionImprover, { @@ -1175,10 +1064,8 @@ where } } -impl PartitionImprover for Composition +impl PartitionImprover for Composition where - D: DimName, - DefaultAllocator: Allocator, T: PartitionImprover, U: PartitionImprover, { @@ -1191,10 +1078,8 @@ where } } -impl TopologicPartitioner for Composition +impl TopologicPartitioner for Composition where - D: DimName, - DefaultAllocator: Allocator, T: Partitioner, U: TopologicPartitionImprover, { diff --git a/src/partition.rs b/src/partition.rs index 04971cd8..fa2fb0f2 100644 --- a/src/partition.rs +++ b/src/partition.rs @@ -1,11 +1,6 @@ //! Utilities to manipulate partitions. use itertools::Itertools; -use nalgebra::allocator::Allocator; -use nalgebra::base::dimension::{DimDiff, DimSub}; -use nalgebra::DefaultAllocator; -use nalgebra::DimName; -use nalgebra::U1; use sprs::CsMatView; @@ -394,16 +389,7 @@ impl<'a, P, W> Part<'a, P, W> { } } -impl<'a, W, D> Part<'a, PointND, W> -where - D: DimName + DimSub, - DefaultAllocator: Allocator - + Allocator - + Allocator - + Allocator>, - >::Buffer: Send + Sync, - >::Buffer: Send + Sync, -{ +impl<'a, W, const D: usize> Part<'a, PointND, W> { /// Computes the aspect ratio of a part. It is defined as the aspect ratio of a minimal bounding rectangle /// of the set of points contained in the part. ///