Skip to content

Commit

Permalink
Auto merge of serde-rs#170 - DonSheddow:complex-fmt, r=cuviper
Browse files Browse the repository at this point in the history
Add formatting options for Complex

This adds LowerExp and UpperExp traits for Complex, taking precision into account. Fixes serde-rs#148
  • Loading branch information
homu committed Mar 25, 2017
2 parents 2adf018 + 2784b89 commit 904d9b4
Showing 1 changed file with 110 additions and 5 deletions.
115 changes: 110 additions & 5 deletions complex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,16 +616,102 @@ impl<T: Clone + Num> One for Complex<T> {
}
}

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<T> fmt::Display for Complex<T> 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<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)
}
}

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 904d9b4

Please sign in to comment.