Skip to content

Commit

Permalink
Merge pull request #287 from TobTobXX/master
Browse files Browse the repository at this point in the history
Add support for Complex number storage types.
  • Loading branch information
iliekturtles authored May 16, 2022
2 parents 66d3e85 + d6d39e1 commit b7906fd
Show file tree
Hide file tree
Showing 11 changed files with 635 additions and 293 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci-full-test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --no-run --no-default-features --features "autoconvert usize isize bigint bigrational si std use_serde"
args: --verbose --no-run --no-default-features --features "autoconvert usize isize bigint bigrational complex32 si std use_serde"

- name: Test all non-si features
uses: actions-rs/cargo@v1
with:
command: test
args: --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 f32 f64 std use_serde"
args: --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 f32 f64 std use_serde"
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ members = [
num-traits = { version = "0.2", default-features = false }
num-rational = { version = "0.4", optional = true, default-features = false }
num-bigint = { version = "0.4", optional = true, default-features = false, features = ["std"] }
num-complex = { version = "0.4", optional = true, default-features = false, features = ["std"] }
serde = { version = "1.0", optional = true, default-features = false }
typenum = "1.13"

Expand Down Expand Up @@ -66,6 +67,8 @@ rational = ["rational-support"]
rational32 = ["rational-support"]
rational64 = ["rational-support"]
bigrational = ["bigint-support"]
complex32 = ["complex-support"]
complex64 = ["complex-support"]
f32 = []
f64 = []
si = []
Expand All @@ -81,6 +84,7 @@ use_serde = ["serde"]
# Internal features to include appropriate num-* crates.
rational-support = ["num-rational"]
bigint-support = ["num-bigint", "num-rational/num-bigint-std"]
complex-support = ["num-complex"]

[[example]]
name = "base"
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ uom = {
"isize", "i8", "i16", "i32", "i64", "i128", # Signed integer storage types.
"bigint", "biguint", # Arbitrary width integer storage types.
"rational", "rational32", "rational64", "bigrational", # Integer ratio storage types.
"complex32", "complex64", # Complex floating point storage types.
"f32", "f64", # Floating point storage types.
"si", "std", # Built-in SI system and std library support.
"use_serde", # Serde support.
Expand All @@ -99,10 +100,10 @@ uom = {
The feature exists to account for compiler limitations where zero-cost code is not generated for
non-floating point underlying storage types.
* `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`, `i128`, `bigint`,
`biguint`, `rational`, `rational32`, `rational64`, `bigrational`, `f32`, `f64` -- Features to
enable underlying storage types. At least one of these features must be enabled. `f32` and `f64`
are enabled by default. See the [Design](#design) section for implications of choosing different
underlying storage types.
`biguint`, `rational`, `rational32`, `rational64`, `bigrational`, `complex32`, `complex64`,
`f32`, `f64` -- Features to enable underlying storage types. At least one of these features must
be enabled. `f32` and `f64` are enabled by default. See the [Design](#design) section for
implications of choosing different underlying storage types.
* `si` -- Feature to include the pre-built [International System of Units][si] (SI). Enabled by
default.
* `std` -- Feature to compile with standard library support. Disabling this feature compiles `uom`
Expand Down Expand Up @@ -134,7 +135,7 @@ storage type (e.g. `f32`).
Alternative base units can be used by executing the macro defined for the system of quantities
(`ISQ!` for the SI). `uom` supports `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`,
`i16`, `i32`, `i64`, `i128`, `bigint`, `biguint`, `rational`, `rational32`, `rational64`,
`bigrational`, `f32`, and `f64` as the underlying storage type.
`bigrational`, `complex32`, `complex64`, `f32`, and `f64` as the underlying storage type.

A consequence of normalizing values to the base unit is that some values may not be able to be
represented or can't be precisely represented for floating point and rational underlying storage
Expand Down
64 changes: 57 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
//! "isize", "i8", "i16", "i32", "i64", "i128", # Signed integer storage types.
//! "bigint", "biguint", # Arbitrary width integer storage types.
//! "rational", "rational32", "rational64", "bigrational", # Integer ratio storage types.
//! "complex32", "complex64", # Complex floating point storage types.
//! "f32", "f64", # Floating point storage types.
//! "si", "std", # Built-in SI system and std library support.
//! "use_serde", # Serde support.
Expand All @@ -86,11 +87,10 @@
//! directly interact. The feature exists to account for compiler limitations where zero-cost
//! code is not generated for non-floating point underlying storage types.
//! * `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`, `i128`,
//! `bigint`, `biguint`, `rational`, `rational32`, `rational64`, `bigrational`, `f32`, `f64` --
//! Features to enable underlying storage types. At least one of these features must be enabled.
//! `f32` and `f64` are enabled by default. See the [Design](#design) section for implications
//! of choosing different
//! underlying storage types.
//! `bigint`, `biguint`, `rational`, `rational32`, `rational64`, `bigrational`, `complex32`,
//! `complex64`, `f32`, `f64` -- Features to enable underlying storage types. At least one of
//! these features must be enabled. `f32` and `f64` are enabled by default. See the
//! [Design](#design) section for implications of choosing different underlying storage types.
//! * `si` -- Feature to include the pre-built [International System of Units][si] (SI). Enabled by
//! default.
//! * `std` -- Feature to compile with standard library support. Disabling this feature compiles
Expand Down Expand Up @@ -122,7 +122,8 @@
//! quantity. Alternative base units can be used by executing the macro defined for the system of
//! quantities (`ISQ!` for the SI). `uom` supports `usize`, `u8`, `u16`, `u32`, `u64`, `u128`,
//! `isize`, `i8`, `i16`, `i32`, `i64`, `i128`, `bigint`, `biguint`, `rational`, `rational32`,
//! `rational64`, `bigrational`, `f32`, and `f64` as the underlying storage type.
//! `rational64`, `bigrational`, `complex32`, `complex64`, `f32`, and `f64` as the underlying
//! storage type.
//!
//! A consequence of normalizing values to the base unit is that some values may not be able to be
//! represented or can't be precisely represented for floating point and rational underlying
Expand Down Expand Up @@ -199,6 +200,7 @@
feature = "i128",
feature = "bigint", feature = "biguint",
feature = "rational", feature = "rational32", feature = "rational64", feature = "bigrational",
feature = "complex32", feature = "complex64",
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 @@ -214,14 +216,21 @@ pub extern crate num_bigint;
#[cfg(any(feature = "rational-support", feature = "bigint-support"))]
pub extern crate num_rational;

#[doc(hidden)]
#[cfg(feature = "complex-support")]
pub extern crate num_complex;

#[doc(hidden)]
#[cfg(feature = "serde")]
pub extern crate serde;

#[doc(hidden)]
pub extern crate typenum;

#[cfg(all(test, any(feature = "f32", feature = "f64")))]
#[cfg(all(
test,
any(feature = "f32", feature = "f64", feature = "complex32", feature = "complex64")
))]
#[macro_use]
extern crate approx;
#[cfg(test)]
Expand Down Expand Up @@ -284,6 +293,11 @@ pub mod num {
pub mod rational {
pub use num_rational::*;
}

#[cfg(feature = "complex-support")]
pub mod complex {
pub use num_complex::*;
}
}

/// Primitive traits and types representing basic properties of types.
Expand Down Expand Up @@ -645,6 +659,42 @@ storage_types! {
}
}

storage_types! {
types: Complex;
impl crate::Conversion<V> 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 {
// Conversion factor is the norm of the number. Scaling with length again yields the
// same number.
self.norm()
}
}

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

#[inline(always)]
fn value(self) -> V {
// Conversion by scaling (multiplication with only real number). Scaling a normalized
// number yields the original number again.
V::new(self, 0.0)
}
}
}

/// Utilities for formatting and printing quantities.
pub mod fmt {
/// An enum to specify the display style to use.
Expand Down
27 changes: 25 additions & 2 deletions src/storage_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
/// * `$T`: Types to generate a module for. Accepts all underlying storage types along with a number
/// of different categories:
/// * `All`: `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`,
/// `i128`, `BigInt`, `BigUint`, `Rational`, `Rational32`, `Rational64`, `BigRational`, `f32`,
/// and `f64`.
/// `i128`, `BigInt`, `BigUint`, `Rational`, `Rational32`, `Rational64`, `BigRational`,
/// `Complex32`, `Complex64`, `f32`, and `f64`.
/// * `PrimInt`: `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`,
/// and `i128`.
/// * `Ratio`: `Rational`, `Rational32`, `Rational64`, and `BigRational`.
/// * `Float`: `f32` and `f64`.
/// * `Signed`: `isize`, `i8`, `i16`, `i32`, `i64`, `i128`, `BigInt`, `Rational`, `Rational32`,
/// `Rational64`, `BigRational`, `f32`, and `f64`.
/// * `Unsigned`: `usize`, `u8`, `u16`, `u32`, `u64`, `u128`, and `BigUint`.
/// * `Complex`: `Complex32` and `Complex64`.
/// * `$tt`: Code to place into each storage type module.
///
#[cfg_attr(all(feature = "f32", feature = "f64"), doc = " ```rust")]
Expand Down Expand Up @@ -100,6 +101,20 @@ macro_rules! storage_types {
(@type ($(#[$attr:meta])*) @$M:ident BigRational ($($tt:tt)*)) => {
storage_type_bigrational!(($(#[$attr])*) @$M ($($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident Complex32 ($($tt:tt)*)) => {
storage_type_complex32!(($(#[$attr])*) @$M (
/// Inner storage type.
#[allow(dead_code)]
pub type VV = f32;
$($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident Complex64 ($($tt:tt)*)) => {
storage_type_complex64!(($(#[$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 All @@ -125,6 +140,8 @@ 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 Complex32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Complex64 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
};
Expand Down Expand Up @@ -176,6 +193,10 @@ macro_rules! storage_types {
storage_types!(@type ($(#[$attr])*) @$M u128 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M BigUint ($($tt)*));
};
(@type ($(#[$attr:meta])*) @$M:ident Complex ($($tt:tt)*)) => {
storage_types!(@type ($(#[$attr])*) @$M Complex32 ($($tt)*));
storage_types!(@type ($(#[$attr])*) @$M Complex64 ($($tt)*));
};
(@mod ($(#[$attr:meta])*) $M:ident, $V:ty; ($($tt:tt)*)) => {
$(#[$attr])*
mod $M {
Expand Down Expand Up @@ -245,6 +266,8 @@ storage_type_types! {
storage_type_rational32!("rational32", rational32, $crate::num::rational::Rational32);
storage_type_rational64!("rational64", rational64, $crate::num::rational::Rational64);
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_f32!("f32", f32, f32);
storage_type_f64!("f64", f64, f64);
}
Loading

0 comments on commit b7906fd

Please sign in to comment.