num-complex
Advanced tools
+1
-1
@@ -10,3 +10,3 @@ [package] | ||
| repository = "https://github.com/rust-num/num" | ||
| version = "0.1.36" | ||
| version = "0.1.37" | ||
@@ -13,0 +13,0 @@ [dependencies] |
+135
-5
@@ -36,4 +36,29 @@ // Copyright 2013 The Rust Project Developers. See the COPYRIGHT | ||
| /// A complex number in Cartesian form. | ||
| /// | ||
| /// ## Representation and Foreign Function Interface Compatibility | ||
| /// | ||
| /// `Complex<T>` is memory layout compatible with an array `[T; 2]`. | ||
| /// | ||
| /// Note that `Complex<F>` where F is a floating point type is **only** memory | ||
| /// layout compatible with C's complex types, **not** necessarily calling | ||
| /// convention compatible. This means that for FFI you can only pass | ||
| /// `Complex<F>` behind a pointer, not as a value. | ||
| /// | ||
| /// ## Examples | ||
| /// | ||
| /// Example of extern function declaration. | ||
| /// | ||
| /// ``` | ||
| /// use num_complex::Complex; | ||
| /// use std::os::raw::c_int; | ||
| /// | ||
| /// extern "C" { | ||
| /// fn zaxpy_(n: *const c_int, alpha: *const Complex<f64>, | ||
| /// x: *const Complex<f64>, incx: *const c_int, | ||
| /// y: *mut Complex<f64>, incy: *const c_int); | ||
| /// } | ||
| /// ``` | ||
| #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)] | ||
| #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] | ||
| #[repr(C)] | ||
| pub struct Complex<T> { | ||
@@ -620,2 +645,44 @@ /// Real portion of the complex number | ||
| macro_rules! write_complex { | ||
| ($f:ident, $t:expr, $prefix:expr, $re:expr, $im:expr, $T:ident) => {{ | ||
| let abs_re = if $re < Zero::zero() { $T::zero() - $re.clone() } else { $re.clone() }; | ||
| let abs_im = if $im < Zero::zero() { $T::zero() - $im.clone() } else { $im.clone() }; | ||
| let real: String; | ||
| let imag: String; | ||
| if let Some(prec) = $f.precision() { | ||
| real = format!(concat!("{:.1$", $t, "}"), abs_re, prec); | ||
| imag = format!(concat!("{:.1$", $t, "}"), abs_im, prec); | ||
| } | ||
| else { | ||
| real = format!(concat!("{:", $t, "}"), abs_re); | ||
| imag = format!(concat!("{:", $t, "}"), abs_im); | ||
| } | ||
| let prefix = if $f.alternate() { $prefix } else { "" }; | ||
| let sign = if $re < Zero::zero() { | ||
| "-" | ||
| } else if $f.sign_plus() { | ||
| "+" | ||
| } else { | ||
| "" | ||
| }; | ||
| let complex = if $im < Zero::zero() { | ||
| format!("{}{pre}{re}-{pre}{im}i", sign, re=real, im=imag, pre=prefix) | ||
| } | ||
| else { | ||
| format!("{}{pre}{re}+{pre}{im}i", sign, re=real, im=imag, pre=prefix) | ||
| }; | ||
| if let Some(width) = $f.width() { | ||
| write!($f, "{0: >1$}", complex, width) | ||
| } | ||
| else { | ||
| write!($f, "{}", complex) | ||
| } | ||
| }} | ||
| } | ||
| /* string conversions */ | ||
@@ -626,10 +693,54 @@ impl<T> fmt::Display for Complex<T> where | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| if self.im < Zero::zero() { | ||
| write!(f, "{}-{}i", self.re, T::zero() - self.im.clone()) | ||
| } else { | ||
| write!(f, "{}+{}i", self.re, self.im) | ||
| } | ||
| write_complex!(f, "", "", self.re, self.im, T) | ||
| } | ||
| } | ||
| impl<T> fmt::LowerExp for Complex<T> where | ||
| T: fmt::LowerExp + Num + PartialOrd + Clone | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write_complex!(f, "e", "", self.re, self.im, T) | ||
| } | ||
| } | ||
| impl<T> fmt::UpperExp for Complex<T> where | ||
| T: fmt::UpperExp + Num + PartialOrd + Clone | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write_complex!(f, "E", "", self.re, self.im, T) | ||
| } | ||
| } | ||
| impl<T> fmt::LowerHex for Complex<T> where | ||
| T: fmt::LowerHex + Num + PartialOrd + Clone | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write_complex!(f, "x", "0x", self.re, self.im, T) | ||
| } | ||
| } | ||
| impl<T> fmt::UpperHex for Complex<T> where | ||
| T: fmt::UpperHex + Num + PartialOrd + Clone | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write_complex!(f, "X", "0x", self.re, self.im, T) | ||
| } | ||
| } | ||
| impl<T> fmt::Octal for Complex<T> where | ||
| T: fmt::Octal + Num + PartialOrd + Clone | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write_complex!(f, "o", "0o", self.re, self.im, T) | ||
| } | ||
| } | ||
| impl<T> fmt::Binary for Complex<T> where | ||
| T: fmt::Binary + Num + PartialOrd + Clone | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write_complex!(f, "b", "0b", self.re, self.im, T) | ||
| } | ||
| } | ||
| #[cfg(feature = "serde")] | ||
@@ -1217,2 +1328,21 @@ impl<T> serde::Serialize for Complex<T> | ||
| #[test] | ||
| fn test_string_formatting() { | ||
| let a = Complex::new(1.23456, 123.456); | ||
| assert_eq!(format!("{}", a), "1.23456+123.456i"); | ||
| assert_eq!(format!("{:.2}", a), "1.23+123.46i"); | ||
| assert_eq!(format!("{:.2e}", a), "1.23e0+1.23e2i"); | ||
| assert_eq!(format!("{:+20.2E}", a), " +1.23E0+1.23E2i"); | ||
| let b = Complex::new(0x80, 0xff); | ||
| assert_eq!(format!("{:X}", b), "80+FFi"); | ||
| assert_eq!(format!("{:#x}", b), "0x80+0xffi"); | ||
| assert_eq!(format!("{:+#b}", b), "+0b10000000+0b11111111i"); | ||
| assert_eq!(format!("{:+#16o}", b), " +0o200+0o377i"); | ||
| let c = Complex::new(-10, -10000); | ||
| assert_eq!(format!("{}", c), "-10-10000i"); | ||
| assert_eq!(format!("{:16}", c), " -10-10000i"); | ||
| } | ||
| #[test] | ||
| fn test_hash() { | ||
@@ -1219,0 +1349,0 @@ let a = Complex::new(0i32, 0i32); |