Objects/complexobject.c (part 10)
Source:
cpython 3.14 @ ab2d84fe1023/Objects/complexobject.c
This annotation covers complex number construction and arithmetic. See objects_complexobject9_detail for complex.__repr__, complex.real/imag, and __hash__.
Map
| Lines | Symbol | Role |
|---|---|---|
| 1-80 | complex.__new__ | Parse complex(real, imag) or complex('1+2j') |
| 81-180 | c_sum / c_diff / c_prod | C-level complex arithmetic |
| 181-260 | c_quot / c_pow | Division and power |
| 261-360 | complex.__abs__ | abs(1+2j) — modulus |
| 361-500 | complex.conjugate | Return a - bj |
Reading
complex.__new__
// CPython: Objects/complexobject.c:680 complex_new_impl
static PyObject *
complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i)
{
Py_complex cr, ci;
if (r == NULL) cr.real = cr.imag = 0.0;
else if (PyUnicode_Check(r)) {
/* Parse '1+2j' string */
return complex_from_string(r);
} else {
cr = PyComplex_AsCComplex(r);
}
if (i == NULL) ci.real = ci.imag = 0.0;
else ci = PyComplex_AsCComplex(i);
/* result = (cr.real - ci.imag) + (cr.imag + ci.real)j */
return PyComplex_FromCComplex((Py_complex){
cr.real - ci.imag, cr.imag + ci.real
});
}
complex(1, 2j) is complex(real=1, imag=2j). Because imag may itself be complex, the formula separates real and imaginary components: complex(a+bj, c+dj) = (a-d) + (b+c)j.
c_sum / c_diff
// CPython: Objects/complexobject.c:42 c_sum
static Py_complex
c_sum(Py_complex a, Py_complex b)
{
return (Py_complex){a.real + b.real, a.imag + b.imag};
}
static Py_complex
c_diff(Py_complex a, Py_complex b)
{
return (Py_complex){a.real - b.real, a.imag - b.imag};
}
Complex addition and subtraction are component-wise. Py_complex is a plain C struct {double real; double imag;}.
c_prod
// CPython: Objects/complexobject.c:60 c_prod
static Py_complex
c_prod(Py_complex a, Py_complex b)
{
return (Py_complex){
a.real * b.real - a.imag * b.imag,
a.real * b.imag + a.imag * b.real
};
}
Complex multiplication: (a + bi)(c + di) = (ac - bd) + (ad + bc)i. No NaN-handling in the fast path; c_prod can produce NaN for inf * 0 inputs (this is acceptable per IEEE 754).
c_quot
// CPython: Objects/complexobject.c:80 c_quot
static Py_complex
c_quot(Py_complex a, Py_complex b)
{
double d = b.real * b.real + b.imag * b.imag;
if (d == 0.0) {
errno = EDOM;
return (Py_complex){0.0, 0.0};
}
return (Py_complex){
(a.real * b.real + a.imag * b.imag) / d,
(a.imag * b.real - a.real * b.imag) / d
};
}
Division by zero sets errno = EDOM and returns (0,0). The caller checks errno and raises ZeroDivisionError.
complex.__abs__
// CPython: Objects/complexobject.c:340 complex_abs
static PyObject *
complex_abs(PyComplexObject *v)
{
double result = hypot(v->cval.real, v->cval.imag);
return PyFloat_FromDouble(result);
}
abs(3+4j) returns 5.0. hypot(a, b) computes sqrt(a²+b²) without intermediate overflow: hypot(3e300, 4e300) returns 5e300, not inf.
gopy notes
complex.__new__ is objects.ComplexNew in objects/complex.go. Arithmetic uses complex128 directly in Go. complex.__abs__ calls cmplx.Abs from math/cmplx. conjugate returns complex(real, -imag(c)).