Skip to content

complex+saloon: implement complex transcendentals; wire %cplx into Saloon#59

Merged
sigilante merged 5 commits into
sigilante/unum-transcendentalsfrom
sigilante/complex-transcendentals
Jun 9, 2026
Merged

complex+saloon: implement complex transcendentals; wire %cplx into Saloon#59
sigilante merged 5 commits into
sigilante/unum-transcendentalsfrom
sigilante/complex-transcendentals

Conversation

@sigilante

Copy link
Copy Markdown
Collaborator

Stacked on #58 (unum transcendentals). Completes the %cplx Tier-B story so Saloon's transcendentals work on complex rays.

/lib/complex — complex elementary functions

cexp, clog, csqrt, csin, ccos, ctan, cpow in all four width doors (cs/cd/ch/cq).

Self-contained (no /+ math): per the architecture discussion, each door carries its own real exp/sin/cos/log/atan as naive Taylor/AGM series over the stdlib component float door — consistent with /lib/unum//lib/fixed//lib/twoc, and avoids coupling the complex kind-primitive to the special-functions lib (or pulling math into Lagoon's build). Closed forms documented in the header; #18's Chebyshev rewrite would upgrade the real series in lockstep.

Saloon — %cplx dispatch

+trans-scalar/+fun-scalar gain a %cplx branch (complex bloqs 5/6/7/8 = ch/cs/cd/cq). exp/sin/cos/tan/log/sqrt/pow map to the complex ops; real-only/ordered functions (factorial/log-10/log-2/cbrt/pow-n) are undefined on complex and crash.

Tests (validated vs numpy, all green on ~hex)

  • tests/lib/complex-fns — full set at @cs; exp/log/sqrt at @cd; exp at @ch/@cq. (@cd matches numpy complex128 to ~15 digits, @cq to ~34.)
  • tests/lib/saloon-cplx — ray-level %cplx dispatch through Saloon Tier B (with sake %n for deterministic rounding), plus factorial/cbrt crash-on-complex guards.

Note: bare +sa's default rnd isn't %n (the same "set rnd via +sake" expectation the eig tests follow); the %cplx tests use sake %n since complex rounding is rnd-sensitive (unlike posits).

🤖 Generated with Claude Code

sigilante and others added 4 commits June 9, 2026 11:18
…loon

/lib/complex gains complex elementary functions (cexp, clog, csqrt, csin, ccos,
ctan, cpow) in all four width doors (cs/cd/ch/cq).  Kept self-contained -- like
/lib/unum, /lib/fixed, /lib/twoc -- by giving each door its OWN real exp/sin/
cos/log/atan as naive Taylor/AGM series over the stdlib component float door,
rather than depending on /lib/math (which would couple the kind-primitive to
the special-functions lib and pull it into Lagoon's build).

Saloon's Tier-B dispatch (+trans-scalar / +fun-scalar) gains a %cplx branch
(complex bloqs 5/6/7/8 = ch/cs/cd/cq), so exp/sin/cos/tan/log/sqrt/pow now work
on %cplx rays.  Real-only / ordered functions (factorial, log-10, log-2, cbrt,
pow-n) are undefined on complex and crash.

Tests (validated vs numpy, all green on ~hex):
- tests/lib/complex-fns: the full set at @cs, exp/log/sqrt at @cd, exp at
  @ch/@cq (cd matches complex128 to ~15 digits, cq to ~34).
- tests/lib/saloon-cplx: ray-level %cplx dispatch through Saloon Tier B, plus
  factorial/cbrt crash-on-complex guards.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Edge-case testing surfaced a bug: the self-contained real +rlog lacked the
x<=0 domain guard the unum +log has, so clog(0+0i) ran the atanh series on
y=-1 and returned garbage (~-5.4) instead of the -inf singularity.  Add a
log(0) -> -inf guard to +rlog in all four doors (|z| is always >= 0, so 0 is
the only singular input).

Add /tests/lib/complex-edge: origin, real/imaginary axes, the csqrt/clog branch
cut (-1, +-i), the csqrt sign branch (sqrt(-i) = 0.707 - 0.707i), the clog(0)
singularity, off-axis (1+1i, 3+4i), and two large-argument cases locked as
documented limitations (the naive series is ~0.2% off far from the origin).
All validated against numpy complex64.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
complex-edge now covers the same edges across all four widths -- @cd/@ch/@cq
get origin, the csqrt/clog branch cut (-1, -i), the clog(0)=-inf singularity,
and the imaginary axis -- plus:

- cpow edges: 2^0=1, 2^2=4, i^2=-1, (-1)^0.5=i, and the 0^2 corner (documented:
  yields NaN, since cpow routes through clog(0)=-inf -> exp(-inf), which the
  naive series can't represent -- locked as a known limitation, not correctness).
- rounding: cexp(1+2i) under %n/%u/%d/%z gives four distinct bit patterns,
  confirming the rounding mode propagates bit-exactly through the complex ops.

39 cases total, all validated against numpy complex64/128.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds tests/lib/unum-edge (28 cases), the %unum analogue of complex-edge:
- exact identities (exp0=1, cos0=1, sqt4=2, fact5=120, log1=0, acos1=0, ...)
- sign (exp(-1)=1/e, atan(-1)=-pi/4)
- NaR propagation (exp/sin/sqt/factorial of NaR -> NaR)
- domain -> NaR (sqrt(-1))
- a posit8 cross-width spot (identity + NaR propagation)
- large-argument breakdown / saturation, locked as DOCUMENTED limitations:
  exp(10)~21991 vs 22026; exp(50)/exp(100) saturate near maxpos; sin(10) blows
  up out of [-1,1] (no range reduction); log (atanh) holds up (log(100)~4.605).

No bug found (the unum domain guards from the transcendental PR already hold);
posits round-to-nearest-even so there is no rounding-mode axis to sweep.  The
large-arg cases are the #18 hazard made explicit, not asserted as correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
unum: posit transcendental edge-case sweep
@sigilante sigilante merged commit a6cbf6b into sigilante/unum-transcendentals Jun 9, 2026
@sigilante sigilante deleted the sigilante/complex-transcendentals branch June 9, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant