Skip to content

Commit

Permalink
Update ordered-float to 4
Browse files Browse the repository at this point in the history
This requires using `FloatCore` instead of `Float` for the `Float` trait
whenever possible.
  • Loading branch information
msk committed Nov 30, 2023
1 parent 6df61b8 commit ecafc35
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
rust: [stable, 1.64]
rust: [stable, 1.70.0]
steps:
- name: Install Rust
uses: hecrj/setup-rust-action@v1
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and
this project adheres to [Semantic
Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- Instead of `Float` trait, `FloatCore` trait is used as a bound for `T` in
`BallTree` and `VantagePointTree`.
- Requires Rust 1.70 or newer.

## [0.9.0] - 2023-08-07

### Added
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "petal-neighbors"
version = "0.9.0"
version = "0.10.0-rc.1"
edition = "2021"
rust-version = "1.64"
rust-version = "1.70"
description = "Nearest neighbor search algorithms including a ball tree and a vantage point tree."
readme = "README.md"
documentation = "https://docs.rs/petal-neighbors"
Expand All @@ -20,7 +20,7 @@ codecov = { repository = "petabi/petal-neighbors", service = "github" }
[dependencies]
ndarray = "0.15"
num-traits = "0.2"
ordered-float = "3"
ordered-float = "4"
thiserror = "1"

[dev-dependencies]
Expand Down
43 changes: 20 additions & 23 deletions src/ball_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::distance::{self, Euclidean, Metric};
use crate::ArrayError;
use ndarray::{Array1, ArrayBase, ArrayView1, CowArray, Data, Ix1, Ix2};
use num_traits::{Float, FromPrimitive, Zero};
use ordered_float::OrderedFloat;
use ordered_float::{FloatCore, OrderedFloat};
use std::cmp;
use std::collections::BinaryHeap;
use std::num::NonZeroUsize;
Expand All @@ -12,7 +12,7 @@ use std::ops::{AddAssign, DivAssign, Range};
/// which is partitioned into a nested set of hyperspheres, or "balls".
pub struct BallTree<'a, A, M>
where
A: Float,
A: FloatCore,
M: Metric<A>,
{
pub points: CowArray<'a, A, Ix2>,
Expand All @@ -23,7 +23,7 @@ where

impl<'a, A, M> BallTree<'a, A, M>
where
A: Float + Zero + AddAssign + DivAssign + FromPrimitive,
A: FloatCore + Zero + AddAssign + DivAssign + FromPrimitive,
M: Metric<A>,
{
/// Builds a ball tree using the given distance metric.
Expand Down Expand Up @@ -74,6 +74,7 @@ where
/// assert_eq!(index, 2); // points[2] is the nearest.
/// assert!((2_f64.sqrt() - distance).abs() < 1e-8);
/// ```
#[allow(clippy::missing_panics_doc)] // never panics
pub fn query_nearest<S>(&self, point: &ArrayBase<S, Ix1>) -> (usize, A)
where
S: Data<Elem = A>,
Expand All @@ -100,9 +101,7 @@ where
where
S: Data<Elem = A>,
{
let k = if let Some(k) = NonZeroUsize::new(k) {
k
} else {
let Some(k) = NonZeroUsize::new(k) else {
return (Vec::new(), Vec::new());
};
let mut neighbors = BinaryHeap::with_capacity(k.get());
Expand Down Expand Up @@ -355,7 +354,7 @@ where

impl<'a, A> BallTree<'a, A, Euclidean>
where
A: Float + Zero + AddAssign + DivAssign + FromPrimitive,
A: FloatCore + Float + Zero + AddAssign + DivAssign + FromPrimitive,
{
/// Builds a ball tree with a euclidean distance metric.
///
Expand All @@ -375,17 +374,14 @@ where

/// An error returned when an array is not suitable to build a `BallTree`.
#[derive(Clone, Debug)]
struct Neighbor<A>
where
A: Float,
{
struct Neighbor<A> {
pub idx: usize,
pub distance: OrderedFloat<A>,
}

impl<A> Neighbor<A>
where
A: Float,
A: FloatCore,
{
#[must_use]
pub fn new(idx: usize, distance: A) -> Self {
Expand All @@ -398,7 +394,7 @@ where

impl<A> Ord for Neighbor<A>
where
A: Float,
A: FloatCore,
{
#[must_use]
fn cmp(&self, other: &Self) -> cmp::Ordering {
Expand All @@ -408,25 +404,25 @@ where

impl<A> PartialOrd for Neighbor<A>
where
A: Float,
A: FloatCore,
{
#[must_use]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.distance.partial_cmp(&other.distance)
Some(self.cmp(other))
}
}

impl<A> PartialEq for Neighbor<A>
where
A: Float,
A: FloatCore,
{
#[must_use]
fn eq(&self, other: &Self) -> bool {
self.distance == other.distance
}
}

impl<A> Eq for Neighbor<A> where A: Float {}
impl<A> Eq for Neighbor<A> where A: FloatCore {}

/// A node containing a range of points in a ball tree.
#[derive(Clone, Debug)]
Expand All @@ -439,7 +435,7 @@ pub struct Node<A> {

impl<A> Node<A>
where
A: Float + Zero + AddAssign + DivAssign + FromPrimitive,
A: FloatCore + Zero + AddAssign + DivAssign + FromPrimitive,
{
/// Computes the centroid of the node.
///
Expand Down Expand Up @@ -489,7 +485,7 @@ where

impl<A> Default for Node<A>
where
A: Float + Zero,
A: FloatCore + Zero,
{
#[allow(clippy::reversed_empty_ranges)] // An empty range is valid because `centroid` is empty.
fn default() -> Self {
Expand All @@ -515,7 +511,7 @@ fn build_subtree<A, M>(
range: Range<usize>,
metric: &M,
) where
A: Float + AddAssign + DivAssign + FromPrimitive,
A: FloatCore + AddAssign + DivAssign + FromPrimitive,
M: Metric<A>,
{
let n_nodes = nodes.len();
Expand Down Expand Up @@ -550,7 +546,7 @@ fn build_subtree<A, M>(
/// Panics if `col` is empty.
fn halve_node_indices<A>(idx: &mut [usize], col: &ArrayView1<A>)
where
A: Float,
A: FloatCore,
{
let (mut first, mut last) = (0, idx.len() - 1);
let mid = idx.len() / 2;
Expand Down Expand Up @@ -582,7 +578,7 @@ where
/// greater than or equal to the number of rows in `matrix`.
fn max_spread_column<A, S>(matrix: &ArrayBase<S, Ix2>, idx: &[usize]) -> usize
where
A: Float,
A: FloatCore,
S: Data<Elem = A>,
{
let mut spread_iter = matrix
Expand Down Expand Up @@ -623,6 +619,7 @@ mod test {
use ndarray::{arr1, array, aview1, aview2, Array, Axis};
use ndarray_rand::rand_distr::Uniform;
use ndarray_rand::RandomExt;
use ordered_float::FloatCore;

#[test]
#[should_panic]
Expand Down Expand Up @@ -875,7 +872,7 @@ mod test {
metric: &M,
) -> Vec<Neighbor<A>>
where
A: Float,
A: FloatCore,
S: Data<Elem = A>,
M: Metric<A>,
{
Expand Down
12 changes: 4 additions & 8 deletions src/vantage_point_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ use crate::distance::{self, Metric};
use crate::ArrayError;
use ndarray::{ArrayBase, ArrayView1, CowArray, Data, Ix1, Ix2};
use num_traits::{Float, Zero};
use ordered_float::OrderedFloat;
use ordered_float::{FloatCore, OrderedFloat};
use std::ops::AddAssign;

/// A data structure for nearest neighbor search in a multi-dimensional space,
/// which is partitioned into two parts for each vantage point: those points
/// closer to the vantage point than a threshold, and those farther.
pub struct VantagePointTree<'a, A, M>
where
A: Float,
M: Metric<A>,
{
pub struct VantagePointTree<'a, A, M> {
points: CowArray<'a, A, Ix2>,
nodes: Vec<Node<A>>,
root: usize,
Expand All @@ -21,7 +17,7 @@ where

impl<'a, A> VantagePointTree<'a, A, distance::Euclidean>
where
A: Float + Zero + AddAssign + 'a,
A: Float + FloatCore + Zero + AddAssign + 'a,
{
/// Builds a vantage point tree with a euclidean distance metric.
///
Expand All @@ -40,7 +36,7 @@ where

impl<'a, A, M> VantagePointTree<'a, A, M>
where
A: Float + Zero + AddAssign + 'a,
A: FloatCore + Zero + AddAssign + 'a,
M: Metric<A>,
{
/// Builds a vantage point tree using the given distance metric.
Expand Down

0 comments on commit ecafc35

Please sign in to comment.