Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-enable num-traits under an optional feature #7

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
- run: cargo build --verbose
- run: cargo doc --verbose
- run: cargo test --verbose
- run: cargo test --verbose --features float-trait
- run: cargo build --verbose --manifest-path kodama-capi/Cargo.toml
- run: cargo build --verbose --manifest-path kodama-bin/Cargo.toml
- if: matrix.rust == 'nightly'
Expand Down
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ members = ["kodama-bin", "kodama-capi"]
[lib]
name = "kodama"

[dependencies.num-traits]
# For writing generic floating point code.
version = "0.2.12"
optional = true

[dev-dependencies]
# For reading benchmark data.
byteorder = "1.4.3"
Expand All @@ -30,6 +35,10 @@ lazy_static = "1.4.0"
# For property based testing.
quickcheck = { version = "1.0.3", default-features = false }

[features]
default = []
float-trait = ["num-traits"]

[profile.release]
debug = true

Expand Down
2 changes: 1 addition & 1 deletion src/chain.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::mem;

use crate::Float;
use crate::condensed::CondensedMatrix;
use crate::dendrogram::Dendrogram;
use crate::float::Float;
use crate::method;
use crate::{LinkageState, MethodChain};

Expand Down
2 changes: 1 addition & 1 deletion src/dendrogram.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::mem;
use std::ops;

use crate::float::Float;
use crate::Float;

/// A step-wise dendrogram that represents a hierarchical clustering as a
/// binary tree.
Expand Down
77 changes: 52 additions & 25 deletions src/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,54 @@ mod private {
pub trait Sealed {}
impl Sealed for f32 {}
impl Sealed for f64 {}

/// The `SealedCast` trait stops crates other than kodama from implementing
/// any traits that use it.
pub trait SealedCast {}
impl SealedCast for f32 {}
impl SealedCast for f64 {}
impl SealedCast for usize {}
}

/// A trait for numbers that can be converted to a float primitive.
///
/// This is a simplified copy of the homonymous trait from the `num-traits`,
/// copied here to offer just the features required by `kodama`.
pub trait ToPrimitive:
self::private::SealedCast
{
fn to_f32(&self) -> Option<f32>;
fn to_f64(&self) -> Option<f64>;
}

impl ToPrimitive for f32 {
fn to_f32(&self) -> Option<f32> {
Some(*self)
}

fn to_f64(&self) -> Option<f64> {
Some(*self as f64)
}
}

impl ToPrimitive for f64 {
fn to_f32(&self) -> Option<f32> {
Some(*self as f32)
}

fn to_f64(&self) -> Option<f64> {
Some(*self)
}
}

impl ToPrimitive for usize {
fn to_f32(&self) -> Option<f32> {
Some(*self as f32)
}

fn to_f64(&self) -> Option<f64> {
Some(*self as f64)
}
}

/// A trait for writing generic code over floating point numbers.
Expand All @@ -26,13 +74,8 @@ pub trait Float:
+ Div<Self, Output = Self>
+ Mul<Self, Output = Self>
{
/// Converts a `usize` to a float.
fn from_usize(v: usize) -> Self;
/// Converts any floating type to this one.
fn from_float<F: Float>(v: F) -> Self;
/// Converts this floating type to a `f64`.
fn to_f64(self) -> f64;

fn from<T: ToPrimitive>(v: T) -> Option<Self>;
/// Returns the representation of "infinity" for this float type.
fn infinity() -> Self;
/// Returns the maximum value for this float type.
Expand All @@ -44,16 +87,8 @@ pub trait Float:
}

impl Float for f32 {
fn from_usize(v: usize) -> f32 {
v as f32
}

fn from_float<F: Float>(v: F) -> f32 {
v.to_f64() as f32
}

fn to_f64(self) -> f64 {
self as f64
fn from<T: ToPrimitive>(v: T) -> Option<f32> {
v.to_f32()
}

fn infinity() -> f32 {
Expand All @@ -74,18 +109,10 @@ impl Float for f32 {
}

impl Float for f64 {
fn from_usize(v: usize) -> f64 {
v as f64
}

fn from_float<F: Float>(v: F) -> f64 {
fn from<T: ToPrimitive>(v: T) -> Option<f64> {
v.to_f64()
}

fn to_f64(self) -> f64 {
self
}

fn infinity() -> f64 {
f64::INFINITY
}
Expand Down
2 changes: 1 addition & 1 deletion src/generic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::Float;
use crate::condensed::CondensedMatrix;
use crate::dendrogram::Dendrogram;
use crate::float::Float;
use crate::method;
use crate::{LinkageState, Method};

Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,15 @@ use std::str::FromStr;

pub use crate::chain::{nnchain, nnchain_with};
pub use crate::dendrogram::{Dendrogram, Step};
pub use crate::float::Float;
pub use crate::generic::{generic, generic_with};
pub use crate::primitive::{primitive, primitive_with};
pub use crate::spanning::{mst, mst_with};

#[cfg(not(feature = "float-trait"))]
pub use crate::float::Float;
#[cfg(feature = "float-trait")]
pub use num_traits::Float;

use crate::active::Active;
use crate::queue::LinkageHeap;
use crate::union::LinkageUnionFind;
Expand All @@ -250,6 +254,7 @@ mod active;
mod chain;
mod condensed;
mod dendrogram;
#[cfg(not(feature = "float-trait"))]
mod float;
mod generic;
mod method;
Expand Down
22 changes: 11 additions & 11 deletions src/method.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::float::Float;
use crate::Float;

#[inline]
pub fn single<T: Float>(a: T, b: &mut T) {
Expand All @@ -16,14 +16,14 @@ pub fn complete<T: Float>(a: T, b: &mut T) {

#[inline]
pub fn average<T: Float>(a: T, b: &mut T, size_a: usize, size_b: usize) {
let size_a = T::from_usize(size_a);
let size_b = T::from_usize(size_b);
let size_a = T::from(size_a).unwrap();
let size_b = T::from(size_b).unwrap();
*b = (size_a * a + size_b * *b) / (size_a + size_b);
}

#[inline]
pub fn weighted<T: Float>(a: T, b: &mut T) {
*b = T::from_float(0.5) * (a + *b);
*b = T::from(0.5).unwrap() * (a + *b);
}

#[inline]
Expand All @@ -35,9 +35,9 @@ pub fn ward<T: Float>(
size_b: usize,
size_x: usize,
) {
let size_a = T::from_usize(size_a);
let size_b = T::from_usize(size_b);
let size_x = T::from_usize(size_x);
let size_a = T::from(size_a).unwrap();
let size_b = T::from(size_b).unwrap();
let size_x = T::from(size_x).unwrap();

let numerator = ((size_x + size_a) * a) + ((size_x + size_b) * *b)
- (size_x * merged_dist);
Expand All @@ -53,8 +53,8 @@ pub fn centroid<T: Float>(
size_a: usize,
size_b: usize,
) {
let size_a = T::from_usize(size_a);
let size_b = T::from_usize(size_b);
let size_a = T::from(size_a).unwrap();
let size_b = T::from(size_b).unwrap();
let size_ab = size_a + size_b;

*b = (((size_a * a) + (size_b * *b)) / size_ab)
Expand All @@ -63,8 +63,8 @@ pub fn centroid<T: Float>(

#[inline]
pub fn median<T: Float>(a: T, b: &mut T, merged_dist: T) {
let half = T::from_float(0.5);
let quarter = T::from_float(0.25);
let half = T::from(0.5).unwrap();
let quarter = T::from(0.25).unwrap();

*b = (half * (a + *b)) - (merged_dist * quarter);
}
2 changes: 1 addition & 1 deletion src/primitive.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::Float;
use crate::active::Active;
use crate::condensed::CondensedMatrix;
use crate::dendrogram::Dendrogram;
use crate::float::Float;
use crate::method;
use crate::{LinkageState, Method};

Expand Down
5 changes: 2 additions & 3 deletions src/queue.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::float::Float;
use crate::Float;

// BREADCRUMBS: Look into moving `nearest` into this heap structure. It seems
// like it might be doing too much at once, but things might actually become
Expand Down Expand Up @@ -166,8 +166,7 @@ impl<T: Float> LinkageHeap<T> {

#[cfg(test)]
mod tests {
use crate::float::Float;

use crate::Float;
use super::LinkageHeap;

fn is_sorted_asc<T: Float>(xs: &[T]) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion src/spanning.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::Float;
use crate::condensed::CondensedMatrix;
use crate::dendrogram::Dendrogram;
use crate::float::Float;
use crate::method;
use crate::{LinkageState, Method};

Expand Down