Cleaned out some allocations

This commit is contained in:
Alan Liddell 2017-07-16 09:51:55 -04:00
parent 97e6d45d03
commit 38ee1304bb
1 changed files with 97 additions and 131 deletions

View File

@ -755,123 +755,89 @@ impl<T> FromStr for Complex<T> where
_ => 'j' _ => 'j'
}; };
let mut a = String::with_capacity(s.len());
let mut b = String::with_capacity(s.len()); let mut b = String::with_capacity(s.len());
let mut first = true; let mut first = true;
let mut char_indices = s.char_indices(); let mut char_indices = s.char_indices();
let mut pc = ' '; let mut pc = ' ';
let mut split_index = s.len();
loop { loop {
match char_indices.next() { match char_indices.next() {
Some(t) => { Some(t) => {
let i = t.0; let i = t.0;
let cc = t.1; let cc = t.1;
if cc == '+' {
// handle exponents if cc == '+' && pc != 'e' && pc != 'E' {
if pc != 'e' && pc != 'E' { // ignore '+' if part of an exponent
if first {
split_index = i;
first = false; first = false;
// don't carry '+' over into b
pc = ' ';
continue;
} }
} else if cc == '-' { // don't carry '+' over into b
// handle exponents and negative numbers pc = ' ';
if i > 0 && pc != 'e' && pc != 'E' { continue;
} else if cc == '-' && pc != 'e' && pc != 'E' && i > 0 {
// ignore '-' if part of an exponent or begins the string
if first {
split_index = i;
first = false; first = false;
// DO carry '-' over into b
} }
// DO carry '-' over into b
} }
if !first && cc == ' ' && pc == '-' { if pc == '-' && cc == ' ' && !first {
// ignore whitespace between minus sign and next number // ignore whitespace between minus sign and next number
continue; continue;
} }
if first { if !first {
a.push(cc);
} else {
b.push(cc); b.push(cc);
} }
pc = cc; pc = cc;
}, },
None => break, None => break,
} }
} }
a = a.trim_right().to_string(); // split off real and imaginary parts, trim whitespace
b = b.trim_left().to_string(); let (a, _) = s.split_at(split_index);
let a = a.trim_right();
let mut b = b.trim_left();
// input was either pure real or pure imaginary
if b.is_empty() { if b.is_empty() {
b = match a.rfind(imag) { b = match a.ends_with(imag) {
None => "0i".to_string(), false => "0i",
_ => "0".to_string() true => "0"
}; };
} }
let re = match a.rfind(imag) { let re;
None => { let im;
try!(T::from_str(&a) if a.ends_with(imag) {
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError })) im = a; re = b;
}, } else if b.ends_with(imag) {
_ => { re = a; im = b;
try!(T::from_str(&b) } else {
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError })) return Err(ParseComplexError { kind: ComplexErrorKind::ParseError });
} }
};
let im = match a.rfind(imag) { // parse re
None => { let re = try!(T::from_str(re)
// a is real .map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError }));
match b.pop() {
// b was empty
None => return Err(ParseComplexError { kind: ComplexErrorKind::ParseError }),
Some(c) => {
if c == imag {
// b is imaginary
if b.is_empty() {
// b was just 'imag'
b = "1".to_string();
} else if b == "-" {
// b was just '-imag'
b = "-1".to_string();
}
} else {
// given a sum or difference of two reals
return Err(ParseComplexError { kind: ComplexErrorKind::ParseError });
}
}
}
try!(T::from_str(&b) // pop imaginary unit off
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError })) let mut im = &im[..im.len()-1];
}, // handle im == "i" or im == "-i"
_ => { if im.is_empty() {
// a contains imag im = "1";
match a.pop() { } else if im == "-" {
None => return Err(ParseComplexError { kind: ComplexErrorKind::ParseError }), im = "-1";
Some(c) => { }
if c == imag {
// a is imaginary
if a.is_empty() {
// a was just 'imag'
a = "1".to_string();
} else if a == "-" {
// a was just '-imag'
a = "-1".to_string();
}
} else {
// given a sum or difference of two reals
return Err(ParseComplexError { kind: ComplexErrorKind::ParseError });
}
}
}
try!(T::from_str(&a) // parse im
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError })) let im = try!(T::from_str(im)
} .map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError }));
};
Ok(Complex::new(re, im)) Ok(Complex::new(re, im))
} }
@ -1570,61 +1536,61 @@ mod test {
#[test] #[test]
fn test_from_str() { fn test_from_str() {
fn test(z: Complex64, s: String) { fn test(z: Complex64, s: &str) {
assert_eq!(FromStr::from_str(&s), Ok(z)); assert_eq!(FromStr::from_str(s), Ok(z));
} }
test(_0_0i, "0 + 0i".to_string()); test(_0_0i, "0 + 0i");
test(_0_0i, "0+0j".to_string()); test(_0_0i, "0+0j");
test(_0_0i, "0 - 0j".to_string()); test(_0_0i, "0 - 0j");
test(_0_0i, "0-0i".to_string()); test(_0_0i, "0-0i");
test(_0_0i, "0i + 0".to_string()); test(_0_0i, "0i + 0");
test(_0_0i, "0".to_string()); test(_0_0i, "0");
test(_0_0i, "-0".to_string()); test(_0_0i, "-0");
test(_0_0i, "0i".to_string()); test(_0_0i, "0i");
test(_0_0i, "0j".to_string()); test(_0_0i, "0j");
test(_0_0i, "-0i".to_string()); test(_0_0i, "-0i");
test(_1_0i, "1 + 0i".to_string()); test(_1_0i, "1 + 0i");
test(_1_0i, "1+0j".to_string()); test(_1_0i, "1+0j");
test(_1_0i, "1 - 0j".to_string()); test(_1_0i, "1 - 0j");
test(_1_0i, "1-0i".to_string()); test(_1_0i, "1-0i");
test(_1_0i, "-0j+1".to_string()); test(_1_0i, "-0j+1");
test(_1_0i, "1".to_string()); test(_1_0i, "1");
test(_1_1i, "1 + i".to_string()); test(_1_1i, "1 + i");
test(_1_1i, "1+j".to_string()); test(_1_1i, "1+j");
test(_1_1i, "1 + 1j".to_string()); test(_1_1i, "1 + 1j");
test(_1_1i, "1+1i".to_string()); test(_1_1i, "1+1i");
test(_1_1i, "i + 1".to_string()); test(_1_1i, "i + 1");
test(_1_1i, "1i+1".to_string()); test(_1_1i, "1i+1");
test(_1_1i, "j+1".to_string()); test(_1_1i, "j+1");
test(_0_1i, "0 + i".to_string()); test(_0_1i, "0 + i");
test(_0_1i, "0+j".to_string()); test(_0_1i, "0+j");
test(_0_1i, "-0 + j".to_string()); test(_0_1i, "-0 + j");
test(_0_1i, "-0+i".to_string()); test(_0_1i, "-0+i");
test(_0_1i, "0 + 1i".to_string()); test(_0_1i, "0 + 1i");
test(_0_1i, "0+1j".to_string()); test(_0_1i, "0+1j");
test(_0_1i, "-0 + 1j".to_string()); test(_0_1i, "-0 + 1j");
test(_0_1i, "-0+1i".to_string()); test(_0_1i, "-0+1i");
test(_0_1i, "j + 0".to_string()); test(_0_1i, "j + 0");
test(_0_1i, "i".to_string()); test(_0_1i, "i");
test(_0_1i, "j".to_string()); test(_0_1i, "j");
test(_0_1i, "1j".to_string()); test(_0_1i, "1j");
test(_neg1_1i, "-1 + i".to_string()); test(_neg1_1i, "-1 + i");
test(_neg1_1i, "-1+j".to_string()); test(_neg1_1i, "-1+j");
test(_neg1_1i, "-1 + 1j".to_string()); test(_neg1_1i, "-1 + 1j");
test(_neg1_1i, "-1+1i".to_string()); test(_neg1_1i, "-1+1i");
test(_neg1_1i, "1i-1".to_string()); test(_neg1_1i, "1i-1");
test(_neg1_1i, "j + -1".to_string()); test(_neg1_1i, "j + -1");
test(_05_05i, "0.5 + 0.5i".to_string()); test(_05_05i, "0.5 + 0.5i");
test(_05_05i, "0.5+0.5j".to_string()); test(_05_05i, "0.5+0.5j");
test(_05_05i, "5e-1+0.5j".to_string()); test(_05_05i, "5e-1+0.5j");
test(_05_05i, "5E-1 + 0.5j".to_string()); test(_05_05i, "5E-1 + 0.5j");
test(_05_05i, "5E-1i + 0.5".to_string()); test(_05_05i, "5E-1i + 0.5");
test(_05_05i, "0.05e+1j + 50E-2".to_string()); test(_05_05i, "0.05e+1j + 50E-2");
} }
#[test] #[test]