From 0ec034b21fb6adc93db50bf8e9a95a540f99d446 Mon Sep 17 00:00:00 2001 From: Sigilante Date: Fri, 29 May 2026 21:05:08 -0500 Subject: [PATCH] Fix any/all reductions for the numeric boolean convention 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 --- lagoon/desk/lib/lagoon.hoon | 12 ++++++++++-- lagoon/desk/tests/lib/lagoon-array-utils.hoon | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lagoon/desk/lib/lagoon.hoon b/lagoon/desk/lib/lagoon.hoon index e87432c..ee760ef 100644 --- a/lagoon/desk/lib/lagoon.hoon +++ b/lagoon/desk/lib/lagoon.hoon @@ -994,15 +994,23 @@ =/ rtol (fill meta.a data:(scale meta.a +.tol)) (lte (abs (sub a b)) (add atol (mul rtol (abs b)))) :: + :: Booleans use the numeric convention true=1, false=0 (see fun-scalar). + :: An element is truthy iff its encoded value is nonzero (also +0.0=0x0). + :: any: some element truthy <=> the max element is nonzero. + :: all: every element truthy <=> the min element is nonzero. + :: min/max reduce to an all-1s-shape scalar ray, so index with a + :: rank-matched zero index rather than assuming a fixed dimensionality. ++ any |= [a=ray] ^- ?(%.y %.n) - (^lth (get-item (cumsum a) ~[0]) (roll shape.meta.a ^mul)) + =/ dex (reap (lent shape.meta.a) 0) + !(=((get-item (max a) dex) 0)) :: ++ all |= [a=ray] ^- ?(%.y %.n) - =((get-item (cumsum a) ~[0]) 0) + =/ dex (reap (lent shape.meta.a) 0) + !(=((get-item (min a) dex) 0)) :: +$ ops $? %add %sub diff --git a/lagoon/desk/tests/lib/lagoon-array-utils.hoon b/lagoon/desk/tests/lib/lagoon-array-utils.hoon index 28141f0..8497e57 100644 --- a/lagoon/desk/tests/lib/lagoon-array-utils.hoon +++ b/lagoon/desk/tests/lib/lagoon-array-utils.hoon @@ -208,6 +208,21 @@ !>((get-item:la (max:la a) ~[0 0])) !>((snag (argmax:la a) (ravel:la a))) == +:: +:: any/all over boolean rays (numeric convention: true=1.0, false=0.0). +:: any = some element truthy; all = every element truthy. +++ test-any-all ^- tang + =/ all-true (en-ray:la [meta=[shape=~[1 3] bloq=5 kind=%i754 tail=~] baum=~[~[.1.0 .1.0 .1.0]]]) + =/ has-false (en-ray:la [meta=[shape=~[1 3] bloq=5 kind=%i754 tail=~] baum=~[~[.1.0 .0.0 .1.0]]]) + =/ all-false (en-ray:la [meta=[shape=~[1 3] bloq=5 kind=%i754 tail=~] baum=~[~[.0.0 .0.0 .0.0]]]) + ;: weld + %+ expect-eq !>(%.y) !>((all:la all-true)) + %+ expect-eq !>(%.y) !>((any:la all-true)) + %+ expect-eq !>(%.n) !>((all:la has-false)) + %+ expect-eq !>(%.y) !>((any:la has-false)) + %+ expect-eq !>(%.n) !>((all:la all-false)) + %+ expect-eq !>(%.n) !>((any:la all-false)) + == -- :: to-tank