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

[WIP] Add support for Complex number storage types. #287

Merged
merged 2 commits into from
May 16, 2022
Merged
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
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"
TobTobXX marked this conversation as resolved.
Show resolved Hide resolved
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;
TobTobXX marked this conversation as resolved.
Show resolved Hide resolved

#[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)*));
TobTobXX marked this conversation as resolved.
Show resolved Hide resolved
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