Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ lto = "thin"

[patch.crates-io]
parking_lot_core = { git = "https://github.com/youknowone/parking_lot", branch = "rustpython" }
num-complex = { git = "https://github.com/moreal/num-complex", rev = "e179d6f7d4045ad9381249afb849fcb48831616c" }
# REDOX START, Uncomment when you want to compile/check with redoxer
# REDOX END

Expand Down Expand Up @@ -192,7 +193,7 @@ malachite-bigint = "0.9.1"
malachite-q = "0.9.1"
malachite-base = "0.9.1"
memchr = "2.8.0"
num-complex = "0.4.6"
num-complex = { git = "https://github.com/moreal/num-complex", rev = "e179d6f7d4045ad9381249afb849fcb48831616c" }
num-integer = "0.1.46"
num-traits = "0.2"
num_enum = { version = "0.7", default-features = false }
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ def check_div(self, x, y):
q = z.__truediv__(y)
self.assertClose(q, x)

@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: floats nan and inf are not identical
def test_truediv(self):
simple_real = [float(i) for i in range(-5, 6)]
simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
Expand Down Expand Up @@ -290,7 +289,6 @@ def test_sub(self):
self.assertRaises(TypeError, operator.sub, 1j, None)
self.assertRaises(TypeError, operator.sub, None, 1j)

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_mul(self):
self.assertEqual(1j * int(20), complex(0, 20))
self.assertEqual(1j * int(-1), complex(0, -1))
Expand Down
79 changes: 73 additions & 6 deletions crates/vm/src/builtins/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,43 @@
Ok(r)
}

fn inner_div(v1: Complex64, v2: Complex64, vm: &VirtualMachine) -> PyResult<Complex64> {
if v2.is_zero() {
return Err(vm.new_zero_division_error("complex division by zero"));
/// Equivalent of CPython's `_Py_rc_quot`: real / complex division using
/// Smith's method with C99 Annex G.5.2 NaN recovery.
fn rc_div(a: f64, b: Complex64) -> Complex64 {
let abs_breal = b.re.abs();

Check warning on line 148 in crates/vm/src/builtins/complex.rs

View workflow job for this annotation

GitHub Actions / Lint Rust & Python code

Misspelled word (breal) Suggestions: (break*)
let abs_bimag = b.im.abs();

let (mut x, mut y);

if abs_breal >= abs_bimag {

Check warning on line 153 in crates/vm/src/builtins/complex.rs

View workflow job for this annotation

GitHub Actions / Lint Rust & Python code

Misspelled word (breal) Suggestions: (break*)
if abs_breal == 0.0 {

Check warning on line 154 in crates/vm/src/builtins/complex.rs

View workflow job for this annotation

GitHub Actions / Lint Rust & Python code

Misspelled word (breal) Suggestions: (break*)
// zero division — caller should have checked
return Complex64::new(0.0, 0.0);
}
let ratio = b.im / b.re;
let denom = b.re + b.im * ratio;
x = a / denom;
y = (-a * ratio) / denom;
} else if abs_bimag >= abs_breal {

Check warning on line 162 in crates/vm/src/builtins/complex.rs

View workflow job for this annotation

GitHub Actions / Lint Rust & Python code

Misspelled word (breal) Suggestions: (break*)
let ratio = b.re / b.im;
let denom = b.re * ratio + b.im;
x = (a * ratio) / denom;
y = (-a) / denom;
} else {
// At least one of b.re or b.im is a NaN
x = f64::NAN;
y = f64::NAN;
}

if x.is_nan() && y.is_nan() && a.is_finite() && (abs_breal.is_infinite() || abs_bimag.is_infinite())

Check warning on line 173 in crates/vm/src/builtins/complex.rs

View workflow job for this annotation

GitHub Actions / Lint Rust & Python code

Misspelled word (breal) Suggestions: (break*)
{
let bx = if b.re.is_infinite() { 1.0_f64.copysign(b.re) } else { 0.0_f64.copysign(b.re) };
let by = if b.im.is_infinite() { 1.0_f64.copysign(b.im) } else { 0.0_f64.copysign(b.im) };
x = 0.0 * (a * bx);
y = 0.0 * (-a * by);
}

Ok(v1.fdiv(v2))
Complex64::new(x, y)
}

fn inner_pow(v1: Complex64, v2: Complex64, vm: &VirtualMachine) -> PyResult<Complex64> {
Expand Down Expand Up @@ -468,7 +499,16 @@
vm,
)
}),
multiply: Some(|a, b, vm| PyComplex::number_op(a, b, |a, b, _vm| a * b, vm)),
multiply: Some(|a, b, vm| {
PyComplex::complex_real_binop(
a,
b,
|a, b| a.fmul(b),

Check warning on line 506 in crates/vm/src/builtins/complex.rs

View workflow job for this annotation

GitHub Actions / Lint Rust & Python code

Unknown word (fmul)
|a_complex, b_real| Complex64::new(a_complex.re * b_real, a_complex.im * b_real),
|a_real, b_complex| Complex64::new(a_real * b_complex.re, a_real * b_complex.im),
vm,
)
}),
power: Some(|a, b, c, vm| {
if vm.is_none(c) {
PyComplex::number_op(a, b, inner_pow, vm)
Expand All @@ -493,7 +533,34 @@
result.to_pyresult(vm)
}),
boolean: Some(|number, _vm| Ok(!PyComplex::number_downcast(number).value.is_zero())),
true_divide: Some(|a, b, vm| PyComplex::number_op(a, b, inner_div, vm)),
true_divide: Some(|a, b, vm| {
PyComplex::complex_real_binop(
a,
b,
|a, b| -> PyResult<Complex64> {
if b.is_zero() {
Err(vm.new_zero_division_error("complex division by zero"))
} else {
Ok(a.fdiv(b))
}
},
|a_complex, b_real| -> PyResult<Complex64> {
if b_real == 0.0 {
Err(vm.new_zero_division_error("complex division by zero"))
} else {
Ok(Complex64::new(a_complex.re / b_real, a_complex.im / b_real))
}
},
|a_real, b_complex| -> PyResult<Complex64> {
if b_complex.is_zero() {
Err(vm.new_zero_division_error("complex division by zero"))
} else {
Ok(rc_div(a_real, b_complex))
}
},
vm,
)
}),
..PyNumberMethods::NOT_IMPLEMENTED
};
&AS_NUMBER
Expand Down
Loading