diff --git a/complex/src/lib.rs b/complex/src/lib.rs index 62f74cc..1ef6e03 100644 --- a/complex/src/lib.rs +++ b/complex/src/lib.rs @@ -616,16 +616,102 @@ impl One for Complex { } } +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 */ impl fmt::Display for Complex where T: fmt::Display + Num + PartialOrd + Clone { 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 fmt::LowerExp for Complex 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 fmt::UpperExp for Complex 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 fmt::LowerHex for Complex 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 fmt::UpperHex for Complex 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 fmt::Octal for Complex 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 fmt::Binary for Complex 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) } } @@ -1210,6 +1296,25 @@ mod test { test(_05_05i, "0.5+0.5i".to_string()); } + #[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() { let a = Complex::new(0i32, 0i32);