Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d2a2120

Browse filesBrowse files
committed
Add rustpython_literal::complex
1 parent 3ff40d2 commit d2a2120
Copy full SHA for d2a2120

File tree

5 files changed

+79
-75
lines changed
Filter options

5 files changed

+79
-75
lines changed

‎compiler/codegen/src/unparse.rs

Copy file name to clipboardExpand all lines: compiler/codegen/src/unparse.rs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ impl<'a, 'b, 'c> Unparser<'a, 'b, 'c> {
366366
}
367367
}
368368
&ruff::Number::Complex { real, imag } => self
369-
.p(&rustpython_literal::float::complex_to_string(real, imag)
369+
.p(&rustpython_literal::complex::to_string(real, imag)
370370
.replace("inf", inf_str))?,
371371
}
372372
}

‎compiler/literal/src/complex.rs

Copy file name to clipboard
+73Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::float;
2+
3+
/// Convert a complex number to a string.
4+
pub fn to_string(re: f64, im: f64) -> String {
5+
// integer => drop ., fractional => float_ops
6+
let mut im_part = if im.fract() == 0.0 {
7+
im.to_string()
8+
} else {
9+
float::to_string(im)
10+
};
11+
im_part.push('j');
12+
13+
// positive empty => return im_part, integer => drop ., fractional => float_ops
14+
let re_part = if re == 0.0 {
15+
if re.is_sign_positive() {
16+
return im_part;
17+
} else {
18+
re.to_string()
19+
}
20+
} else if re.fract() == 0.0 {
21+
re.to_string()
22+
} else {
23+
float::to_string(re)
24+
};
25+
let mut result =
26+
String::with_capacity(re_part.len() + im_part.len() + 2 + im.is_sign_positive() as usize);
27+
result.push('(');
28+
result.push_str(&re_part);
29+
if im.is_sign_positive() || im.is_nan() {
30+
result.push('+');
31+
}
32+
result.push_str(&im_part);
33+
result.push(')');
34+
result
35+
}
36+
37+
/// Parse a complex number from a string.
38+
///
39+
/// Returns `Some((re, im))` on success.
40+
pub fn parse_str(s: &str) -> Option<(f64, f64)> {
41+
let s = s.trim();
42+
// Handle parentheses
43+
let s = match s.strip_prefix('(') {
44+
None => s,
45+
Some(s) => s.strip_suffix(')')?.trim(),
46+
};
47+
48+
let value = match s.strip_suffix(|c| c == 'j' || c == 'J') {
49+
None => (float::parse_str(s)?, 0.0),
50+
Some(mut s) => {
51+
let mut real = 0.0;
52+
// Find the central +/- operator. If it exists, parse the real part.
53+
for (i, w) in s.as_bytes().windows(2).enumerate() {
54+
if (w[1] == b'+' || w[1] == b'-') && !(w[0] == b'e' || w[0] == b'E') {
55+
real = float::parse_str(&s[..=i])?;
56+
s = &s[i + 1..];
57+
break;
58+
}
59+
}
60+
61+
let imag = match s {
62+
// "j", "+j"
63+
"" | "+" => 1.0,
64+
// "-j"
65+
"-" => -1.0,
66+
s => float::parse_str(s)?,
67+
};
68+
69+
(real, imag)
70+
}
71+
};
72+
Some(value)
73+
}

‎compiler/literal/src/float.rs

Copy file name to clipboardExpand all lines: compiler/literal/src/float.rs
-33Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -178,39 +178,6 @@ pub fn to_string(value: f64) -> String {
178178
}
179179
}
180180

181-
pub fn complex_to_string(re: f64, im: f64) -> String {
182-
// integer => drop ., fractional => float_ops
183-
let mut im_part = if im.fract() == 0.0 {
184-
im.to_string()
185-
} else {
186-
to_string(im)
187-
};
188-
im_part.push('j');
189-
190-
// positive empty => return im_part, integer => drop ., fractional => float_ops
191-
let re_part = if re == 0.0 {
192-
if re.is_sign_positive() {
193-
return im_part;
194-
} else {
195-
re.to_string()
196-
}
197-
} else if re.fract() == 0.0 {
198-
re.to_string()
199-
} else {
200-
to_string(re)
201-
};
202-
let mut result =
203-
String::with_capacity(re_part.len() + im_part.len() + 2 + im.is_sign_positive() as usize);
204-
result.push('(');
205-
result.push_str(&re_part);
206-
if im.is_sign_positive() || im.is_nan() {
207-
result.push('+');
208-
}
209-
result.push_str(&im_part);
210-
result.push(')');
211-
result
212-
}
213-
214181
pub fn from_hex(s: &str) -> Option<f64> {
215182
if let Ok(f) = hexf_parse::parse_hexf64(s, false) {
216183
return Some(f);

‎compiler/literal/src/lib.rs

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod char;
2+
pub mod complex;
23
pub mod escape;
34
pub mod float;
45
pub mod format;

‎vm/src/builtins/complex.rs

Copy file name to clipboardExpand all lines: vm/src/builtins/complex.rs
+4-41Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,13 @@ impl Constructor for PyComplex {
179179
"complex() can't take second arg if first is a string".to_owned(),
180180
));
181181
}
182-
let value = s
182+
let (re, im) = s
183183
.to_str()
184-
.and_then(|s| parse_str(s.trim()))
184+
.and_then(rustpython_literal::complex::parse_str)
185185
.ok_or_else(|| {
186186
vm.new_value_error("complex() arg is a malformed string".to_owned())
187187
})?;
188-
return Self::from(value)
188+
return Self::from(Complex64 { re, im })
189189
.into_ref_with_type(vm, cls)
190190
.map(Into::into);
191191
} else {
@@ -494,7 +494,7 @@ impl Representable for PyComplex {
494494
// TODO: when you fix this, move it to rustpython_common::complex::repr and update
495495
// ast/src/unparse.rs + impl Display for Constant in ast/src/constant.rs
496496
let Complex64 { re, im } = zelf.value;
497-
Ok(rustpython_literal::float::complex_to_string(re, im))
497+
Ok(rustpython_literal::complex::to_string(re, im))
498498
}
499499
}
500500

@@ -519,40 +519,3 @@ pub struct ComplexArgs {
519519
#[pyarg(any, optional)]
520520
imag: OptionalArg<PyObjectRef>,
521521
}
522-
523-
fn parse_str(s: &str) -> Option<Complex64> {
524-
// Handle parentheses
525-
let s = match s.strip_prefix('(') {
526-
None => s,
527-
Some(s) => match s.strip_suffix(')') {
528-
None => return None,
529-
Some(s) => s.trim(),
530-
},
531-
};
532-
533-
let value = match s.strip_suffix(|c| c == 'j' || c == 'J') {
534-
None => Complex64::new(crate::literal::float::parse_str(s)?, 0.0),
535-
Some(mut s) => {
536-
let mut real = 0.0;
537-
// Find the central +/- operator. If it exists, parse the real part.
538-
for (i, w) in s.as_bytes().windows(2).enumerate() {
539-
if (w[1] == b'+' || w[1] == b'-') && !(w[0] == b'e' || w[0] == b'E') {
540-
real = crate::literal::float::parse_str(&s[..=i])?;
541-
s = &s[i + 1..];
542-
break;
543-
}
544-
}
545-
546-
let imag = match s {
547-
// "j", "+j"
548-
"" | "+" => 1.0,
549-
// "-j"
550-
"-" => -1.0,
551-
s => crate::literal::float::parse_str(s)?,
552-
};
553-
554-
Complex64::new(real, imag)
555-
}
556-
};
557-
Some(value)
558-
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.