FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Implement objcomplex::parse_str() to replace Complex64::from_str() · RustPython/RustPython@ec5d168 · GitHub

Repository navigation

Commit ec5d168

Browse files
authored
Implement objcomplex::parse_str() to replace Complex64::from_str()
1 parent d4a35b9 commit ec5d168

2 files changed

Lines changed: 86 additions & 4 deletions

File tree

‎tests/snippets/builtin_complex.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,48 @@ def __eq__(self, other):
164164
assert complex("-2j") == -2j
165165
assert_raises(TypeError, lambda: complex("5+2j", 1))
166166
assert_raises(ValueError, lambda: complex("abc"))
167+
168+
assert complex("1+10j") == 1+10j
169+
assert complex(10) == 10+0j
170+
assert complex(10.0) == 10+0j
171+
assert complex(10) == 10+0j
172+
assert complex(10+0j) == 10+0j
173+
assert complex(1, 10) == 1+10j
174+
assert complex(1, 10) == 1+10j
175+
assert complex(1, 10.0) == 1+10j
176+
assert complex(1, 10) == 1+10j
177+
assert complex(1, 10) == 1+10j
178+
assert complex(1, 10.0) == 1+10j
179+
assert complex(1.0, 10) == 1+10j
180+
assert complex(1.0, 10) == 1+10j
181+
assert complex(1.0, 10.0) == 1+10j
182+
assert complex(3.14+0j) == 3.14+0j
183+
assert complex(3.14) == 3.14+0j
184+
assert complex(314) == 314.0+0j
185+
assert complex(314) == 314.0+0j
186+
assert complex(3.14+0j, 0j) == 3.14+0j
187+
assert complex(3.14, 0.0) == 3.14+0j
188+
assert complex(314, 0) == 314.0+0j
189+
assert complex(314, 0) == 314.0+0j
190+
assert complex(0j, 3.14j) == -3.14+0j
191+
assert complex(0.0, 3.14j) == -3.14+0j
192+
assert complex(0j, 3.14) == 3.14j
193+
assert complex(0.0, 3.14) == 3.14j
194+
assert complex("1") == 1+0j
195+
assert complex("1j") == 1j
196+
assert complex() == 0
197+
assert complex("-1") == -1
198+
assert complex("+1") == +1
199+
assert complex("(1+2j)") == 1+2j
200+
assert complex("(1.3+2.2j)") == 1.3+2.2j
201+
assert complex("3.14+1J") == 3.14+1j
202+
assert complex(" ( +3.14-6J )") == 3.14-6j
203+
assert complex(" ( +3.14-J )") == 3.14-1j
204+
assert complex(" ( +3.14+j )") == 3.14+1j
205+
assert complex("J") == 1j
206+
assert complex("( j )") == 1j
207+
assert complex("+J") == 1j
208+
assert complex("( -j)") == -1j
209+
assert complex('1e-500') == 0.0 + 0.0j
210+
assert complex('-1e-500j') == 0.0 - 0.0j
211+
assert complex('-1e-500+1e-500j') == -0.0 + 0.0j

‎vm/src/obj/objcomplex.rs‎

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use num_complex::Complex64;
22
use num_traits::Zero;
3-
use std::str::FromStr;
43

54
use super::objfloat;
65
use super::objstr::PyString;
@@ -10,7 +9,7 @@ use crate::pyobject::{
109
PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
1110
};
1211
use crate::vm::VirtualMachine;
13-
use rustpython_common::hash;
12+
use rustpython_common::{float_ops, hash};
1413

1514
/// Create a complex number from a real part and an optional imaginary part.
1615
///
@@ -254,8 +253,9 @@ impl PyComplex {
254253
"complex() can't take second arg if first is a string".to_owned(),
255254
));
256255
}
257-
let value = Complex64::from_str(s.borrow_value())
258-
.map_err(|err| vm.new_value_error(err.to_string()))?;
256+
let value = parse_str(s.borrow_value().trim()).ok_or_else(|| {
257+
vm.new_value_error("complex() arg is a malformed string".to_owned())
258+
})?;
259259
return Self::from(value).into_ref_with_type(vm, cls);
260260
} else {
261261
return Err(vm.new_type_error(format!(
@@ -308,3 +308,40 @@ struct ComplexArgs {
308308
#[pyarg(positional_or_keyword, default = "None")]
309309
imag: Option<PyObjectRef>,
310310
}
311+
312+
fn parse_str(s: &str) -> Option<Complex64> {
313+
// Handle parentheses
314+
let s = match s.strip_prefix('(') {
315+
None => s,
316+
Some(s) => match s.strip_suffix(')') {
317+
None => return None,
318+
Some(s) => s.trim(),
319+
},
320+
};
321+
322+
let value = match s.strip_suffix(|c| c == 'j' || c == 'J') {
323+
None => Complex64::new(float_ops::parse_str(s)?, 0.0),
324+
Some(mut s) => {
325+
let mut real = 0.0;
326+
// Find the central +/- operator. If it exists, parse the real part.
327+
for (i, w) in s.as_bytes().windows(2).enumerate() {
328+
if (w[1] == b'+' || w[1] == b'-') && !(w[0] == b'e' || w[0] == b'E') {
329+
real = float_ops::parse_str(&s[..=i])?;
330+
s = &s[i + 1..];
331+
break;
332+
}
333+
}
334+
335+
let imag = match s {
336+
// "j", "+j"
337+
"" | "+" => 1.0,
338+
// "-j"
339+
"-" => -1.0,
340+
s => float_ops::parse_str(s)?,
341+
};
342+
343+
Complex64::new(real, imag)
344+
}
345+
};
346+
Some(value)
347+
}

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL