Skip to content

Fix any/all reductions for the numeric boolean convention#28

Merged
sigilante merged 1 commit into
mainfrom
sigilante/fix-any-all
May 30, 2026
Merged

Fix any/all reductions for the numeric boolean convention#28
sigilante merged 1 commit into
mainfrom
sigilante/fix-any-all

Conversation

@sigilante
Copy link
Copy Markdown
Collaborator

Summary

A gnome investigation established that comparison ops across the library consistently encode booleans as numeric true=1, false=0:

  • float arms store 1.0/0.0 (lagoon.hoon:1048–1095),
  • uint arms use !(^op b c) which — since Hoon's %.y=0 — yields true→1, false→0 (lagoon.hoon:1029–1032),
  • the C jets use ? REAL_ONE : REAL_ZERO, and the saloon docs / tinygrad consumer agree.

So there is no convention clash (correcting an earlier hypothesis). The only broken code was any/all (lagoon.hoon:994, 999), written for the opposite true=0 assumption: any tested cumsum < count and all tested cumsum == 0 — both inverted for every boolean ray. (The gnome's first-pass =(sum,count) idea is also unusable: it would compare a float bit-pattern sum to an integer count.)

Fix

Reformulate in terms of min/max, which reduce correctly across kinds (they compare encoded values directly and seed at the first element):

  • any = the max element is nonzero (some element truthy)
  • all = the min element is nonzero (every element truthy)

The != 0 test is encoding-agnostic — both integer 0 and float +0.0 are 0x0. The scalar result is indexed with a rank-matched zero index ((reap (lent shape) 0)) instead of a hardcoded ~[0], so it works for arrays of any dimensionality (the old ~[0] only worked for vectors).

Impact

These arms were unreachable from any test (the is-close helper that calls all is defined but never invoked), and saloon's all-close/any-close delegate here — so they were broken too, and are now fixed. Added a direct any/all test over all-true / mixed / all-false rays.

lagoon-old.hoon has the same bug but is a dead legacy file (slated for removal) and is left untouched.

🤖 Generated with Claude Code

Comparison ops across the library consistently encode booleans as
numeric true=1, false=0 (float arms, uint arms via `!`, the C jets, and
the saloon docs all agree). But `any` and `all` were written for the
opposite (true=0) assumption: `any` tested cumsum < count and `all`
tested cumsum == 0, so both were inverted for every boolean ray.

Reformulate in terms of min/max, which reduce correctly across kinds:
any = the max element is nonzero (some element truthy); all = the min
element is nonzero (every element truthy). Both compare against 0, which
is encoding-agnostic (false and +0.0 are both 0x0). Index the scalar
result with a rank-matched zero index instead of a hardcoded ~[0], so it
works for arrays of any dimensionality.

These arms were previously unreachable from any test (the is-close
helper that calls `all` is defined but never invoked), and saloon's
all-close/any-close delegate here, so they were broken too. Add a direct
any/all test over all-true / mixed / all-false boolean rays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sigilante sigilante force-pushed the sigilante/fix-any-all branch from 83dabad to 0ec034b Compare May 30, 2026 15:05
@sigilante sigilante merged commit bd95628 into main May 30, 2026
@sigilante sigilante deleted the sigilante/fix-any-all branch May 30, 2026 15:07
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