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

feat: [wip] ordered-float feature options #492

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ num-bigint = { version = "0.4", optional = true, default-features = false, featu
num-complex = { version = "0.4", optional = true, default-features = false, features = ["std"] }
serde = { version = "1.0", optional = true, default-features = false }
typenum = "1.13"
ordered-float = { version = "4.5.0", optional = true, default-features = false, features = ["std"] }

[dev-dependencies]
approx = "0.5"
Expand Down Expand Up @@ -67,6 +68,10 @@ rational64 = ["rational-support"]
bigrational = ["bigint-support"]
complex32 = ["complex-support"]
complex64 = ["complex-support"]
orderedf32 = ["ordered-float-support"]
orderedf64 = ["ordered-float-support"]
notnanf32 = ["ordered-float-support"]
notnanf64 = ["ordered-float-support"]
f32 = []
f64 = []
si = []
Expand All @@ -81,6 +86,7 @@ use_serde = ["serde"]
rational-support = ["num-rational"]
bigint-support = ["num-bigint", "num-rational/num-bigint-std"]
complex-support = ["num-complex"]
ordered-float-support = ["ordered-float"]

[[example]]
name = "base"
Expand Down
21 changes: 21 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
test-min:
@echo "Test all crates"
cargo test --all --verbose --features "use_serde"

test-si:
@echo "Test si"
cargo test --verbose --no-default-features --features "f32 si"

test-non-storage:
@echo "Test all non-storage type features"
cargo test --verbose --no-default-features --features "autoconvert f32 si use_serde"

test-si-storage:
@echo "Test si with underlying storage types"
cargo test --verbose --no-run --no-default-features --features "autoconvert usize isize bigint bigrational complex32 orderedf32 notnanf32 si std use_serde"

test-all-non-si:
@echo "Test all non-si features"
cargo test --verbose --no-run --no-default-features --features "autoconvert usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 bigint biguint rational rational32 rational64 bigrational complex32 complex64 orderedf32 orderedf64 notnanf32 notnanf64 f32 f64 std use_serde"

test-ci: test-min test-si test-non-storage test-si-storage test-all-non-si
96 changes: 95 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@
feature = "bigint", feature = "biguint",
feature = "rational", feature = "rational32", feature = "rational64", feature = "bigrational",
feature = "complex32", feature = "complex64",
feature = "orderedf32", feature = "orderedf64",
feature = "notnanf32", feature = "notnanf64",
feature = "f32", feature = "f64", )))]
compile_error!("A least one underlying storage type must be enabled. See the features section of \
uom documentation for available underlying storage type options.");
Expand All @@ -215,6 +217,10 @@ pub extern crate num_rational;
#[cfg(feature = "complex-support")]
pub extern crate num_complex;

#[doc(hidden)]
#[cfg(feature = "ordered-float-support")]
pub extern crate ordered_float;

#[doc(hidden)]
#[cfg(feature = "serde")]
pub extern crate serde;
Expand All @@ -224,7 +230,7 @@ pub extern crate typenum;

#[cfg(all(
test,
any(feature = "f32", feature = "f64", feature = "complex32", feature = "complex64")
any(feature = "f32", feature = "f64", feature = "complex32", feature = "complex64", feature = "orderedf32", feature = "orderedf64", feature="notnanf32", feature="notnanf64")
))]
#[macro_use]
extern crate approx;
Expand Down Expand Up @@ -293,6 +299,15 @@ pub mod num {
pub mod complex {
pub use num_complex::*;
}

#[cfg(feature = "ordered-float-support")]
pub mod ordered_float {
pub use ordered_float::*;
pub type Orderedf32 = OrderedFloat<f32>;
pub type Orderedf64 = OrderedFloat<f64>;
pub type NotNanf32 = NotNan<f32>;
pub type NotNanf64 = NotNan<f64>;
}
}

/// Primitive traits and types representing basic properties of types.
Expand Down Expand Up @@ -697,6 +712,85 @@ storage_types! {
}
}


storage_types! {
types: OrderedFloat;

impl crate::Conversion<Self> for V {
type T = VV;

#[inline(always)]
fn constant(op: crate::ConstantOp) -> Self::T {
match op {
crate::ConstantOp::Add => -<Self::T as crate::num::Zero>::zero(),
crate::ConstantOp::Sub => <Self::T as crate::num::Zero>::zero(),
}
}

#[inline(always)]
fn conversion(&self) -> Self::T {
self.0
}
}

impl crate::ConversionFactor<V> for VV {
#[inline(always)]
fn powi(self, e: i32) -> Self {
<Self as crate::num::Float>::powi(self, e)
}

#[inline(always)]
fn value(self) -> V {
ordered_float::OrderedFloat::<VV>(self)
}
}

impl crate::ConstZero for V {
const ZERO: Self = ordered_float::OrderedFloat::<VV>(0.0);
}
}

storage_types! {
types: NotNan;

impl crate::Conversion<Self> for V {
type T = VV;

#[inline(always)]
fn constant(op: crate::ConstantOp) -> Self::T {
match op {
crate::ConstantOp::Add => -<Self::T as crate::num::Zero>::zero(),
crate::ConstantOp::Sub => <Self::T as crate::num::Zero>::zero(),
}
}

#[inline(always)]
fn conversion(&self) -> Self::T {
self.into_inner()
}
}

impl crate::ConversionFactor<V> for VV {
#[inline(always)]
fn powi(self, e: i32) -> Self {
<Self as crate::num::Float>::powi(self, e)
}

#[inline(always)]
fn value(self) -> V {
ordered_float::NotNan::new(self).unwrap()
}
}

// TODO: is this an acceptable violation of our forbid unsafe?
// It seems worth it to me since it literally can not fail.
//impl crate::ConstZero for V {
// SAFETY: NotNan can never panic from a const 0.0 call.
// const ZERO: Self = unsafe { ordered_float::NotNat::new_unchecked(0.0) };
//}

}

/// Utilities for formatting and printing quantities.
pub mod fmt {
/// An enum to specify the display style to use.
Expand Down
51 changes: 51 additions & 0 deletions src/storage_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,37 @@ macro_rules! storage_types {
pub type VV = f64;
$($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident Orderedf32 ($($tt:tt)*)) => {
storage_type_orderedf32!(($(#[$attr])*) @$M (
/// Inner storage type.
#[allow(dead_code)]
pub type VV = f32;
$($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident Orderedf64 ($($tt:tt)*)) => {
storage_type_orderedf64!(($(#[$attr])*) @$M (
/// Inner storage type.
#[allow(dead_code)]
pub type VV = f64;
$($tt)*));
};


(@type ($(#[$attr:meta])*) @$M:ident NotNanf32 ($($tt:tt)*)) => {
storage_type_notnanf32!(($(#[$attr])*) @$M (
/// Inner storage type.
#[allow(dead_code)]
pub type VV = f32;
$($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident NotNanf64 ($($tt:tt)*)) => {
storage_type_notnanf64!(($(#[$attr])*) @$M (
/// Inner storage type.
#[allow(dead_code)]
pub type VV = f64;
$($tt)*));
};

(@type ($(#[$attr:meta])*) @$M:ident f32 ($($tt:tt)*)) => {
storage_type_f32!(($(#[$attr])*) @$M ($($tt)*));
};
Expand Down Expand Up @@ -142,6 +173,10 @@ macro_rules! storage_types {
storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Complex32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Complex64 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Orderedf32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Orderedf64 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M NotNanf32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M NotNanf64 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
};
Expand Down Expand Up @@ -181,6 +216,10 @@ macro_rules! storage_types {
storage_types!(@type ($(#[$attr])*) @$M Rational32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Rational64 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Orderedf32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Orderedf64 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M NotNanf32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M NotNanf64 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
};
Expand All @@ -197,6 +236,14 @@ macro_rules! storage_types {
storage_types!(@type ($(#[$attr])*) @$M Complex32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Complex64 ($($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident OrderedFloat ($($tt:tt)*)) => {
storage_types!(@type ($(#[$attr])*) @$M Orderedf32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Orderedf64 ($($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident NotNan ($($tt:tt)*)) => {
storage_types!(@type ($(#[$attr])*) @$M NotNanf32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M NotNanf64 ($($tt)*));
};
(@mod ($(#[$attr:meta])*) $M:ident, $V:ty; ($($tt:tt)*)) => {
$(#[$attr])*
mod $M {
Expand Down Expand Up @@ -268,6 +315,10 @@ storage_type_types! {
storage_type_bigrational!("bigrational", bigrational, $crate::num::BigRational);
storage_type_complex32!("complex32", complex32, $crate::num::complex::Complex32);
storage_type_complex64!("complex64", complex64, $crate::num::complex::Complex64);
storage_type_orderedf32!("orderedf32", orderedf32, $crate::num::ordered_float::Orderedf32);
storage_type_orderedf64!("orderedf64", orderedf64, $crate::num::ordered_float::Orderedf64);
storage_type_notnanf32!("notnanf32", notnanf32, $crate::num::ordered_float::NotNanf32);
storage_type_notnanf64!("notnanf64", notnanf64, $crate::num::ordered_float::NotNanf64);
storage_type_f32!("f32", f32, f32);
storage_type_f64!("f64", f64, f64);
}
Loading