Plate 76
cmath vs math.hypot Magnitudes: Localhost Lab
Hands-on cmath vs math.hypot magnitude ops lab: real ops/s for abs, polar, and phase, measured on Linux localhost today in this hands-on lab for SREs.
Aditya Challa3 min read
Intro — what this post promises
2-D magnitude and phase with math.hypot / math.atan2 vs abs(complex) / cmath.polar / cmath.phase. This lab reports ops/s on Linux localhost for 200000 synthetic (re, im) pairs.
Related links:
- sqlite3 vs shelve localhost lab
- gc collect cost localhost lab
- copy copy vs dict copy localhost lab
- html parser vs regex localhost lab
- dataclass asdict vs vars localhost lab
- tracemalloc snapshot localhost lab
- path read text vs open localhost lab
- intenum vs int localhost lab
Lab honesty (1 Oct 2026 IST): Python 3.13.5. Affiliates: 0. Stdlib only — useful when you treat latency error components, IQ samples, or vector residuals as complex numbers.
Verdict up front: abs(complex) ~34917055 ops/s; math.hypot ~16959583; cmath.polar r ~11928627; manual sqrt(a*a+b*b) ~23608807. Phase: cmath.phase ~23945233 vs atan2 ~19534098.
Arms
| Arm | Pattern |
|---|---|
math.hypot(a,b) | float pair magnitude |
abs(z) on complex | complex abs |
cmath.polar(z)[0] | polar radius |
math.sqrt(a*a+b*b) | manual (overflow-prone) |
cmath.phase / atan2 | angle |
Seven rounds, p50. Sample check: hypot 65.11528238439882 matches abs (match=True).
Lab topology
Script: lab-evidence/134-cmath-vs-math-hypot/results/run_lab.py.
Lead table (p50 ops/s)
| Arm | ops/s |
|---|---|
| abs(complex) | 34917055 |
| manual sqrt | 23608807 |
| cmath.phase | 23945233 |
| math.atan2 | 19534098 |
| math.hypot | 16959583 |
| cmath.polar r | 11928627 |
abs(complex) led magnitude. cmath.polar paid for computing both r and φ even when only r was used.
Reading it for SRE work
- Already holding
complexvalues →abs(z)(fastest magnitude here). - Separate float channels without complex objects →
math.hypot(overflow-safer than manual sqrt). - Need angle too → prefer one
cmath.polarover abs+phase separately if both used (measure your path). - Never use manual
sqrt(a*a+b*b)near float extremes — hypot exists for a reason.
Why hypot still matters
Even though hypot was slower than abs(complex) on this run (~16959583 vs ~34917055), hypot avoids intermediate overflow when |a| or |b| is huge. Telemetry pipelines with wild units should stay on hypot unless values are already complex.
cmath.polar at ~11928627 ops/s is the wrong tool if you only need magnitude — you pay for phase work you discard.
Phase peers
cmath.phase (~23945233) edged atan2 (~19534098) slightly here. Pick the API that matches your types; do not convert float pairs to complex solely for phase unless the rest of the pipeline is complex-native.
Type-driven choice
If your pipeline already boxes samples as complex, stay there and call abs (~34917055 ops/s here). If sensors give two floats, call math.hypot and skip allocating complex objects just to take a magnitude. Conversion cost is outside this bench but shows up in real collectors — measure end-to-end before rewriting.
For dashboards that need both magnitude and angle once per sample, cmath.polar can still win on clarity even at ~11928627 ops/s, because one call documents intent better than abs+phase glue.
Pitfalls
- Using
cmath.polaronly forrin a hot loop. - Manual squared sum overflowing.
- Comparing arms with different pre-boxed types without stating allocation.
- Assuming numpy hypot matches these CPython numbers.
Reproduce
Evidence: summary.json, summary.txt.
Limits
One Linux box. Pure Python loops over lists. Not NumPy ufuncs.
Takeaway
For magnitudes on complex values, abs(z) ~34917055 ops/s led; for float pairs prefer math.hypot (~16959583) over manual sqrt. Use cmath.polar only when you need both radius and phase.
Lab evidence
What I found running this
Lab 1 Oct 2026 IST. Python 3.13.5. n=200000: abs(complex) 34917055 ops/s; math.hypot 16959583; cmath.polar r 11928627. Affiliates: 0. Evidence: lab-evidence/134-cmath-vs-math-hypot/results/summary.json. Results reproduced on Linux localhost today.
Related links
Plate 17
platform vs os.uname Inventory: Localhost Lab
Hands-on platform.platform vs os.uname host inventory lab: real ops/s plus cache notes, measured on Linux localhost today in this hands-on lab for SREs.
1 Oct 2026
Plate 09
dataclasses.asdict vs vars: Localhost Lab
1 Oct 2026
Plate 75
uuid.uuid4 vs uuid.uuid1: Localhost Lab
Hands-on uuid.uuid4 vs uuid.uuid1 ID generation lab: real ops/s plus version/node checks, measured on Linux localhost today in this hands-on lab for SREs.
1 Oct 2026