From 92834dc2e44f34345321462be0d7f34323142653 Mon Sep 17 00:00:00 2001 From: wucke13 Date: Wed, 8 Jun 2022 10:12:26 +0200 Subject: [PATCH] fix #283: add possibility to include num-traits/libm for sin and cos in no_std builds --- .github/workflows/ci-full-test-suite.yml | 2 +- Cargo.toml | 2 ++ src/features.rs | 12 ++++++------ src/lib.rs | 5 +++-- src/si/angle.rs | 8 ++++---- src/si/ratio.rs | 6 +++--- src/system.rs | 4 ++-- src/tests/quantity.rs | 4 ++-- src/tests/system.rs | 14 +++++++------- 9 files changed, 30 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci-full-test-suite.yml b/.github/workflows/ci-full-test-suite.yml index 8d6c70fd..2d70e0fc 100644 --- a/.github/workflows/ci-full-test-suite.yml +++ b/.github/workflows/ci-full-test-suite.yml @@ -48,7 +48,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --verbose --no-default-features --features "autoconvert f32 si use_serde" + args: --verbose --no-default-features --features "autoconvert f32 si use_serde libm" - name: Test si with underlying storage types uses: actions-rs/cargo@v1 diff --git a/Cargo.toml b/Cargo.toml index ee755126..0d625aaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,6 +85,8 @@ use_serde = ["serde"] rational-support = ["num-rational"] bigint-support = ["num-bigint", "num-rational/num-bigint-std"] complex-support = ["num-complex"] +# enable sin/cos for no_std builds, via libm +libm = [ "num-traits/libm" ] [[example]] name = "base" diff --git a/src/features.rs b/src/features.rs index ba4aa4f4..68a08b46 100644 --- a/src/features.rs +++ b/src/features.rs @@ -81,19 +81,19 @@ macro_rules! si { ($($tt:tt)*) => {}; } -/// Expands the given block of code when `uom` is compiled with the `std` feature. +/// Expands the given block of code when `uom` is compiled with either the `std` or the `libm` feature. #[doc(hidden)] #[macro_export] -#[cfg(feature = "std")] -macro_rules! std { +#[cfg(any(feature = "std", feature = "libm"))] +macro_rules! std_or_libm { ($($tt:tt)*) => { $($tt)* }; } -/// Does not expand the given block of code when `uom` is compiled without the `std` feature. +/// Does not expand the given block of code when `uom` is compiled without both the `std` and the `libm` feature. #[doc(hidden)] #[macro_export] -#[cfg(not(feature = "std"))] -macro_rules! std { +#[cfg(not(any(feature = "std", feature = "libm")))] +macro_rules! std_or_libm { ($($tt:tt)*) => {}; } diff --git a/src/lib.rs b/src/lib.rs index 6d8edcdd..9a140dbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,6 +97,7 @@ //! `uom` with `no_std`. Enabled by default. //! * `use_serde` -- Feature to enable support for serialization and deserialization of quantities //! with the [Serde][serde] crate. Disabled by default. +//! * `libm` -- Enable advanced floatingpoint functions (sin, cos, ...) on no_std targets //! //! [Serde][serde] support for the `big*` and `rational*` underlying storage types requires //! manually enabling the `serde` feature for the `num-rational` and `num-bigint` crates. To do @@ -277,9 +278,9 @@ pub mod lib { // Conditionally import num sub-crate types based on feature selection. #[doc(hidden)] pub mod num { - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] pub use num_traits::float::Float; - #[cfg(not(feature = "std"))] + #[cfg(not(any(feature = "std", feature = "libm")))] pub use num_traits::float::FloatCore as Float; pub use num_traits::{pow, FromPrimitive, Num, One, Saturating, Signed, ToPrimitive, Zero}; diff --git a/src/si/angle.rs b/src/si/angle.rs index 171a7c0d..46c7abde 100644 --- a/src/si/angle.rs +++ b/src/si/angle.rs @@ -1,6 +1,6 @@ //! Angle (dimensionless quantity). -#[cfg(feature = "std")] +#[cfg(any(feature = "std", feature = "libm"))] use super::ratio::Ratio; quantity! { @@ -64,7 +64,7 @@ impl Angle, f64> { } /// Implementation of various stdlib trigonometric functions -#[cfg(feature = "std")] +#[cfg(any(feature = "std", feature = "libm"))] impl Angle where U: crate::si::Units + ?Sized, @@ -121,7 +121,7 @@ where } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", feature = "libm"))] impl crate::si::Quantity where D: crate::si::Dimension + ?Sized, @@ -161,7 +161,7 @@ mod tests { } } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] mod trig { storage_types! { types: Float; diff --git a/src/si/ratio.rs b/src/si/ratio.rs index bd789871..f2d05897 100644 --- a/src/si/ratio.rs +++ b/src/si/ratio.rs @@ -1,6 +1,6 @@ //! Ratio (dimensionless quantity). -#[cfg(feature = "std")] +#[cfg(any(feature = "std", feature = "libm"))] use super::angle::{Angle, radian}; quantity! { @@ -33,7 +33,7 @@ quantity! { } /// Implementation of various stdlib functions. -#[cfg(feature = "std")] +#[cfg(any(feature = "std", feature = "libm"))] impl Ratio where U: crate::si::Units + ?Sized, @@ -220,7 +220,7 @@ mod tests { } } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] mod float { storage_types! { types: Float; diff --git a/src/system.rs b/src/system.rs index a9fb3b70..dca9dfa1 100644 --- a/src/system.rs +++ b/src/system.rs @@ -611,7 +611,7 @@ macro_rules! system { self.value.classify() } - std! { + std_or_libm! { autoconvert! { /// Calculates the length of the hypotenuse of a right-angle triangle given the legs. #[must_use = "method returns a new number and does not mutate the original value"] @@ -807,7 +807,7 @@ macro_rules! system { self.value.is_normal() } - std! { + std_or_libm! { /// Takes the cubic root of a number. /// #[cfg_attr(all(feature = "si", feature = "f32"), doc = " ```rust")] diff --git a/src/tests/quantity.rs b/src/tests/quantity.rs index 00ceced5..159d8ce5 100644 --- a/src/tests/quantity.rs +++ b/src/tests/quantity.rs @@ -468,7 +468,7 @@ mod float { Test::assert_eq(&3.3.fract(), &m1.fract::().get::()); } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] quickcheck! { #[allow(trivial_casts)] fn hypot_same(l: V, r: V) -> bool { @@ -477,7 +477,7 @@ mod float { } } - #[cfg(all(feature = "std", feature = "autoconvert"))] + #[cfg(all(any(feature = "std", feature = "libm"), feature = "autoconvert"))] quickcheck! { #[allow(trivial_casts)] fn hypot_mixed(l: V, r: V) -> bool { diff --git a/src/tests/system.rs b/src/tests/system.rs index 1b5399f5..7301a7e9 100644 --- a/src/tests/system.rs +++ b/src/tests/system.rs @@ -286,7 +286,7 @@ mod float { v.classify() == Length::new::(*v).classify() } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] #[allow(trivial_casts)] fn cbrt(v: A) -> bool { let l: Quantity, U, V> = Quantity::, U, V> { @@ -298,7 +298,7 @@ mod float { Test::eq(&v.cbrt(), &l.value) } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] #[allow(trivial_casts)] fn hypot(l: A, r: A) -> bool { Test::eq(&Length::new::(l.hypot(*r)), @@ -315,7 +315,7 @@ mod float { v.is_sign_negative() == Length::new::(*v).is_sign_negative() } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] #[allow(trivial_casts)] fn mul_add(s: A, a: A, b: A) -> bool { let r: Quantity, U, V> = Length::new::(*s).mul_add( @@ -340,13 +340,13 @@ mod float { Test::eq(&v.recip(), &a.value) } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] #[allow(trivial_casts)] fn powi(v: A) -> bool { Test::eq(&v.powi(3), &Length::new::(*v).powi(P3::new()).value) } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] #[allow(trivial_casts)] fn sqrt(v: A) -> TestResult { if *v < V::zero() { @@ -647,7 +647,7 @@ mod complex { v.is_normal() == Length::new::(*v).is_normal() } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] #[allow(trivial_casts)] fn cbrt(v: A) -> bool { let l: Quantity, U, V> = Quantity::, U, V> { @@ -659,7 +659,7 @@ mod complex { Test::eq(&v.cbrt(), &l.value) } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "libm"))] #[allow(trivial_casts)] fn mul_add(s: A, a: A, b: A) -> bool { #[allow(unused_imports)]