# Complex Numbers in EGPT — Exact Rational Arithmetic Classical floating-point represents complex numbers as pairs of IEEE doubles. EGPT represents them as pairs of **`EGPTReal` values** — rational numbers stored symbolically as prime-factorisation vectors. Every operation is exact: no rounding, no cancellation error, no NaN. The result of `3 + 4i` squared is `25` as a BigInt ratio, not `24.999999...`. This notebook walks through the fundamentals: 1. **Constructing** complex numbers from exact integer components. 2. **Inspecting** the symbolic representation via `toMathString()`. 3. **Computing magnitude squared** — `|z|² = a² + b²` — using `EGPTMath.multiply` and `EGPTMath.add`, both exact. 4. **Verifying** that the result matches the known integer value. Everything below runs through the single injected `math` capability — no URL imports, no floating-point. // Report the active backend — derived from the SDK, never hardcoded. const { math, display } = caps; const backend = math.activeMathBackend; display(`Active math backend (derived): ${backend}`); ## 1. Constructing complex numbers A `ComplexEGPTReal` is a pair `(real: EGPTReal, imag: EGPTReal)`. We build each component from an exact integer via `EGPTReal.fromBigInt(n)` — the canonical integer entry point. There is no approximate coercion from JS `Number`. Here we construct: - `z1 = 3 + 4i` — a classic Pythagorean complex number whose magnitude is exactly 5. - `z2 = 5 + (-2)i` — a second number to illustrate that negative imaginary parts work identically. const { math, display } = caps; const { EGPTReal, ComplexEGPTReal } = math; // Build z1 = 3 + 4i const z1 = new ComplexEGPTReal(EGPTReal.fromBigInt(3n), EGPTReal.fromBigInt(4n)); // Build z2 = 5 + (-2)i const z2 = new ComplexEGPTReal(EGPTReal.fromBigInt(5n), EGPTReal.fromBigInt(-2n)); // toMathString() renders the EGPTReal symbolic representation const z1str = `z1: real=${z1.real.toMathString()}, imag=${z1.imag.toMathString()}`; const z2str = `z2: real=${z2.real.toMathString()}, imag=${z2.imag.toMathString()}`; display(z1str); display(z2str); return { z1str, z2str }; ## 2. The symbolic representation `toMathString()` exposes how the EGPT system stores a number internally. Small integers like `3`, `4`, `5`, `-2` appear in a compact form — but the underlying type is always an exact rational (a numerator/denominator pair of BigInts). There is no lossy float encoding happening here. Both `z1` and `z2` are confirmed to be `ComplexEGPTReal` instances, not raw JS objects. const { math, display } = caps; const { EGPTReal, ComplexEGPTReal } = math; // Reconstruct locally (cells are independent — no cross-cell variable sharing) const z1 = new ComplexEGPTReal(EGPTReal.fromBigInt(3n), EGPTReal.fromBigInt(4n)); const z2 = new ComplexEGPTReal(EGPTReal.fromBigInt(5n), EGPTReal.fromBigInt(-2n)); const isComplex = z1 instanceof ComplexEGPTReal && z2 instanceof ComplexEGPTReal; display(`Both are ComplexEGPTReal instances: ${isComplex}`); return { isComplex }; ## 3. Magnitude squared: |z|² = a² + b² For a complex number `z = a + bi`, the magnitude squared is: ``` |z|² = a·a + b·b ``` We compute this using `EGPTMath.multiply` (exact rational multiplication) and `EGPTMath.add` (exact rational addition). For `z1 = 3 + 4i`: ``` |z1|² = 3·3 + 4·4 = 9 + 16 = 25 ``` This is the Pythagorean triple `(3, 4, 5)` — the magnitude `|z1|` is exactly 5. const { math, display } = caps; const { EGPTReal, EGPTMath, ComplexEGPTReal } = math; const z1 = new ComplexEGPTReal(EGPTReal.fromBigInt(3n), EGPTReal.fromBigInt(4n)); // Exact rational arithmetic — no floating-point at any step const realSquared = EGPTMath.multiply(z1.real, z1.real); // 3 * 3 = 9 const imagSquared = EGPTMath.multiply(z1.imag, z1.imag); // 4 * 4 = 16 const magnitudeSquared = EGPTMath.add(realSquared, imagSquared); // 9 + 16 = 25 const magSqStr = magnitudeSquared.toMathString(); display(`|z1|² = ${magSqStr}`); // Verify against expected value const expected = EGPTReal.fromBigInt(25n); const correct = magnitudeSquared.equals(expected); display(`Equals 25 (exact comparison via .equals()): ${correct}`); return { magSqStr }; ## 4. Why `.equals()`, not `===` or `==` EGPT stores rationals as prime-factorisation vectors. Two `EGPTReal` values may have different internal representations that are mathematically equal. The only correct comparison is **`.equals()`** — a symbolic equality check on the reduced rational. Never use `==`, `===`, or string comparison (`.toMathString() ===`) to compare EGPTReal values. This is the same discipline as comparing fractions: `1/2` and `2/4` are equal but not string-identical. const { math, display } = caps; const { EGPTReal, EGPTMath, ComplexEGPTReal } = math; // Reproduce the original run(sdk) return value exactly const z1 = new ComplexEGPTReal(EGPTReal.fromBigInt(3n), EGPTReal.fromBigInt(4n)); const z2 = new ComplexEGPTReal(EGPTReal.fromBigInt(5n), EGPTReal.fromBigInt(-2n)); const magnitudeSquaredZ1 = EGPTMath.add( EGPTMath.multiply(z1.real, z1.real), EGPTMath.multiply(z1.imag, z1.imag) ); const result = { category: "complex-twiddle", z1: { real: z1.real.toMathString(), imag: z1.imag.toMathString() }, z2: { real: z2.real.toMathString(), imag: z2.imag.toMathString() }, magnitudeSquaredZ1: magnitudeSquaredZ1.toMathString(), isComplex: z1 instanceof ComplexEGPTReal && z2 instanceof ComplexEGPTReal }; display(result);