Skip to content

Design: %cplx complex arrays + /lib/complex (BLAS-interleaved)#45

Open
sigilante wants to merge 3 commits into
mainfrom
sigilante/cplx-design
Open

Design: %cplx complex arrays + /lib/complex (BLAS-interleaved)#45
sigilante wants to merge 3 commits into
mainfrom
sigilante/cplx-design

Conversation

@sigilante
Copy link
Copy Markdown
Collaborator

Design proposal (lagoon/CPLX-DESIGN.md) — not an implementation. Adds a
complex-number Lagoon kind %cplx and a pure-Hoon /lib/complex, with an atom
layout bit-identical to SoftBLAS / BLAS complex arrays so the eventual jet
is a zero-conversion cast. The motivating consumer is eigenvalues /
eigenvectors in Saloon
— the eigenvalues of a real matrix are generally
complex, so Saloon's eig is blocked until Lagoon can carry complex arrays.

Grounded in the actual code

Researched the vendored SoftBLAS (vere/ext/softblas) and the Lagoon jet C
(lagoon/vere/noun/jets/i/lagoon.c):

  • complex{16,32,64,128}_t = struct {real; imag} (real-first), interleaved
    [re0 im0 re1 im1 …].
  • Level-1 complex only (c/i/z/v axpy/copy/dotc/scal/swap/rot);
    *dotc is the conjugate dot, there's no *dotu, and there is no
    complex GEMM
    .
  • The jet marshals the data atom by 2^(bloq-3) bytes/element and casts
    straight to floatN_t*
    by bloq.

Core decision

bloq = log₂ of the total complex element width (one element = one
complexN_t): bloq6 = complex32 (2×@rs, 64b), bloq7 = complex64
(2×@rd, 128b). Real in the low 2^(bloq-1) bits, imag in the high — so an
array of slots is a BLAS interleaved complex array and the jet is a pure cast.
meta.tail unused (all derives from bloq).

Layout + arithmetic validated on ~hex before writing: (1+2i)·(3+4i) = -5+10i, (1+2i)+(3+4i) = 4+6i with real-low/imag-high @rs components.

What the doc covers

  • /lib/complex arm set (add/sub/mul/div-via-Smith/neg/conj/abs-via-hypot/
    equ/neq); ℂ has no total order → gth/lth crash, only equ/neq.
  • Lagoon's six dispatch sites (mirrors %int2/%unum/%fixp), comparisons
    returning complex one/zero, a proposed %conj op.
  • Reductions: dot (unconjugated, cross-kind-consistent) vs new dotc
    (Hermitian, maps to SoftBLAS *dotc); mmul pure-Hoon now, jet later via
    4-real-GEMM / 3M-Karatsuba over sgemm/dgemm (no complex GEMM exists);
    no exact accumulator (rounds per op, like %i754).
  • Open decisions (§7) and a three-phase plan ending in Saloon eig
    (Hessenberg + shifted QR).

Open questions for review (§7)

ordering (crash vs modulus) · dot conjugation · add %conj to ops ·
which widths first · change semantics.

No code in desk/ changes here — %cplx stays commented out until Phase 1, so
nothing builds against it yet.

🤖 Generated with Claude Code

sigilante and others added 3 commits June 1, 2026 15:53
Design proposal (lagoon/CPLX-DESIGN.md) for a complex-number Lagoon kind and a
pure-Hoon /lib/complex, with an atom layout bit-identical to SoftBLAS complex
arrays so the eventual jet is a zero-conversion cast.  Motivating consumer:
eigenvalues/eigenvectors in Saloon (complex eigenvalues require complex arrays).

Grounded in the vendored SoftBLAS (complex{16,32,64,128}_t = {real;imag},
interleaved, Level-1 + dotc only, no complex GEMM) and the Lagoon jet's
bloq->floatN_t cast marshalling.

Core decision: bloq = log2 of the total complex element width (one element =
one complexN_t; bloq6=complex32, bloq7=complex64), real in the low half / imag
in the high half, so an array of slots IS a BLAS interleaved complex array.
Layout + arithmetic validated on ~hex ((1+2i)(3+4i)=-5+10i).

Covers: /lib/complex arm set (no total order -> gth/lth crash), Lagoon's six
dispatch sites, dot (unconjugated) vs dotc (Hermitian, maps to SoftBLAS *dotc),
mmul via real-GEMM decomposition for the future jet, open decisions, and a
three-phase plan ending in Saloon eig.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fold in resolved review decisions: dedicated complex aura family
@ch/@cs/@cd/@cq (parallel to @r); gth/lth crash (no total order); add %conj
to the ops union; ship @cs (bloq6) + @cd (bloq7) first.  dot-conjugation and
%cplx->real change semantics remain under discussion (§7).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolve the last review decisions:
- dot is bilinear (numpy @/BLAS *dotu, consistent with mmul); add a separate
  Hermitian dotc (numpy vdot/BLAS *dotc) for norms and Saloon eig.
- change out of complex (cplx->real) refuses as lossy; conversions into complex
  and between complex widths are defined.  Modulus stays via abs.
- We own the vendored SoftBLAS, so the jet plan adds the missing complex
  primitives there (*dotu, cgemm/zgemm via 4-real-GEMM / Karatsuba over the
  real kernels) instead of decomposing Lagoon-side; Level-1 already exists.

All design decisions settled; doc ready to implement against.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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