Skip to main content

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

LinesSymbolRole
1-80complex.__new__Parse complex(real, imag) or complex('1+2j')
81-180c_sum / c_diff / c_prodC-level complex arithmetic
181-260c_quot / c_powDivision and power
261-360complex.__abs__abs(1+2j) — modulus
361-500complex.conjugateReturn 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)).