adds basic parser for complex numbers in Cartesian form
This commit is contained in:
parent
31fa9f626a
commit
3c490cdee4
|
@ -22,10 +22,12 @@ extern crate rustc_serialize;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use std::hash;
|
use std::hash;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use traits::{Zero, One, Num, Float};
|
use traits::{Zero, One, Num, Float};
|
||||||
|
|
||||||
|
@ -740,6 +742,77 @@ impl<T> fmt::Binary for Complex<T> where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> FromStr for Complex<T> where
|
||||||
|
T: FromStr + Num + PartialOrd + Clone
|
||||||
|
{
|
||||||
|
type Err = ParseComplexError;
|
||||||
|
|
||||||
|
/// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T`
|
||||||
|
fn from_str(s: &str) -> Result<Complex<T>, ParseComplexError>
|
||||||
|
{
|
||||||
|
// first try to split on " + "
|
||||||
|
let mut split_p = s.splitn(2, " + ");
|
||||||
|
|
||||||
|
let mut a = match split_p.next() {
|
||||||
|
None => return Err(ParseComplexError { kind: ComplexErrorKind::ParseError }),
|
||||||
|
Some(s) => s.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut b = match split_p.next() {
|
||||||
|
// no second item could mean we need to split on " - " instead
|
||||||
|
None => {
|
||||||
|
let mut split_m = s.splitn(2, " - ");
|
||||||
|
|
||||||
|
a = match split_m.next() {
|
||||||
|
None => return Err(ParseComplexError { kind: ComplexErrorKind::ParseError }),
|
||||||
|
Some(s) => s.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let c = match split_m.next() {
|
||||||
|
None => {
|
||||||
|
// if `a` is imaginary, let `b` be real (and vice versa)
|
||||||
|
match a.rfind('i') {
|
||||||
|
None => "0i".to_string(),
|
||||||
|
Some(u) => "0".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(s) => {
|
||||||
|
"-".to_string() + s
|
||||||
|
}
|
||||||
|
};
|
||||||
|
c
|
||||||
|
},
|
||||||
|
Some(s) => s.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let re = match a.rfind('i') {
|
||||||
|
None => {
|
||||||
|
try!(T::from_str(&a)
|
||||||
|
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError }))
|
||||||
|
},
|
||||||
|
Some(u) => {
|
||||||
|
try!(T::from_str(&b)
|
||||||
|
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError }))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let im = match a.rfind('i') {
|
||||||
|
None => {
|
||||||
|
b.pop();
|
||||||
|
try!(T::from_str(&b)
|
||||||
|
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError }))
|
||||||
|
},
|
||||||
|
Some(u) => {
|
||||||
|
a.pop();
|
||||||
|
try!(T::from_str(&a)
|
||||||
|
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError }))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Complex::new(re, im))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl<T> serde::Serialize for Complex<T>
|
impl<T> serde::Serialize for Complex<T>
|
||||||
where T: serde::Serialize
|
where T: serde::Serialize
|
||||||
|
@ -763,6 +836,36 @@ impl<T> serde::Deserialize for Complex<T> where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
pub struct ParseComplexError {
|
||||||
|
kind: ComplexErrorKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
enum ComplexErrorKind {
|
||||||
|
ParseError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ParseComplexError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
self.kind.description()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ParseComplexError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.description().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComplexErrorKind {
|
||||||
|
fn description(&self) -> &'static str {
|
||||||
|
match *self {
|
||||||
|
ComplexErrorKind::ParseError => "failed to parse complex number",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn hash<T: hash::Hash>(x: &T) -> u64 {
|
fn hash<T: hash::Hash>(x: &T) -> u64 {
|
||||||
use std::hash::{BuildHasher, Hasher};
|
use std::hash::{BuildHasher, Hasher};
|
||||||
|
|
Loading…
Reference in New Issue