Skip to content

Commit 11e9d81

Browse files
authored
Merge pull request RustPython#3838 from fanninpm/complex-pynumber
2 parents 0c58d7b + de9a4d5 commit 11e9d81

File tree

2 files changed

+70
-5
lines changed

2 files changed

+70
-5
lines changed

Lib/test/test_itertools.py

-2
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,6 @@ def test_compress(self):
533533
next(testIntermediate)
534534
self.assertEqual(list(op(testIntermediate)), list(result2))
535535

536-
# TODO: RUSTPYTHON
537-
@unittest.expectedFailure
538536
def test_count(self):
539537
self.assertEqual(lzip('abc',count()), [('a', 0), ('b', 1), ('c', 2)])
540538
self.assertEqual(lzip('abc',count(3)), [('a', 3), ('b', 4), ('c', 5)])

vm/src/builtins/complex.rs

+70-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use super::{float, PyStr, PyType, PyTypeRef};
22
use crate::{
33
class::PyClassImpl,
4-
convert::ToPyObject,
4+
convert::{ToPyObject, ToPyResult},
55
function::{
66
OptionalArg, OptionalOption,
77
PyArithmeticValue::{self, *},
88
PyComparisonValue,
99
},
1010
identifier,
11-
types::{Comparable, Constructor, Hashable, PyComparisonOp},
11+
protocol::{PyNumber, PyNumberMethods},
12+
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp},
1213
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
1314
};
1415
use num_complex::Complex64;
@@ -203,7 +204,7 @@ impl PyComplex {
203204
}
204205
}
205206

206-
#[pyimpl(flags(BASETYPE), with(Comparable, Hashable, Constructor))]
207+
#[pyimpl(flags(BASETYPE), with(Comparable, Hashable, Constructor, AsNumber))]
207208
impl PyComplex {
208209
#[pymethod(magic)]
209210
fn complex(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<PyComplex> {
@@ -419,6 +420,72 @@ impl Hashable for PyComplex {
419420
}
420421
}
421422

423+
impl AsNumber for PyComplex {
424+
const AS_NUMBER: PyNumberMethods = PyNumberMethods {
425+
add: Some(|number, other, vm| Self::number_complex_op(number, other, |a, b| a + b, vm)),
426+
subtract: Some(|number, other, vm| {
427+
Self::number_complex_op(number, other, |a, b| a - b, vm)
428+
}),
429+
multiply: Some(|number, other, vm| {
430+
Self::number_complex_op(number, other, |a, b| a * b, vm)
431+
}),
432+
power: Some(|number, other, vm| Self::number_general_op(number, other, inner_pow, vm)),
433+
negative: Some(|number, vm| {
434+
let value = Self::number_downcast(number).value;
435+
(-value).to_pyresult(vm)
436+
}),
437+
positive: Some(|number, vm| Self::number_complex(number, vm).to_pyresult(vm)),
438+
absolute: Some(|number, vm| {
439+
let value = Self::number_downcast(number).value;
440+
value.norm().to_pyresult(vm)
441+
}),
442+
boolean: Some(|number, _vm| Ok(Self::number_downcast(number).value.is_zero())),
443+
true_divide: Some(|number, other, vm| {
444+
Self::number_general_op(number, other, inner_div, vm)
445+
}),
446+
..PyNumberMethods::NOT_IMPLEMENTED
447+
};
448+
}
449+
450+
impl PyComplex {
451+
fn number_general_op<F, R>(
452+
number: &PyNumber,
453+
other: &PyObject,
454+
op: F,
455+
vm: &VirtualMachine,
456+
) -> PyResult
457+
where
458+
F: FnOnce(Complex64, Complex64, &VirtualMachine) -> R,
459+
R: ToPyResult,
460+
{
461+
if let (Some(a), Some(b)) = (number.obj.payload::<Self>(), other.payload::<Self>()) {
462+
op(a.value, b.value, vm).to_pyresult(vm)
463+
} else {
464+
Ok(vm.ctx.not_implemented())
465+
}
466+
}
467+
468+
fn number_complex_op<F>(
469+
number: &PyNumber,
470+
other: &PyObject,
471+
op: F,
472+
vm: &VirtualMachine,
473+
) -> PyResult
474+
where
475+
F: FnOnce(Complex64, Complex64) -> Complex64,
476+
{
477+
Self::number_general_op(number, other, |a, b, _vm| op(a, b), vm)
478+
}
479+
480+
fn number_complex(number: &PyNumber, vm: &VirtualMachine) -> PyRef<PyComplex> {
481+
if let Some(zelf) = number.obj.downcast_ref_if_exact::<Self>(vm) {
482+
zelf.to_owned()
483+
} else {
484+
vm.ctx.new_complex(Self::number_downcast(number).value)
485+
}
486+
}
487+
}
488+
422489
#[derive(FromArgs)]
423490
pub struct ComplexArgs {
424491
#[pyarg(any, optional)]

0 commit comments

Comments
 (0)