util.bend checks
raw source on the hub · import 0xcd07e24a626a62e74603d48f436cd679/util.bend as Util
Shared helpers. Parallelize independent list splits; keep these total.
Population maps use mid-split + a b = f(lo) f(hi) (bend guide Parallelism).
Fuel is |xs| so the Nat shrinks; halves stay observationally ordered.
1 import
import Base
Definitions
def list_len source · line 7 · raw
@-A:Data -> @xs:List<&2, A> -> Nat
def list_take_pad source · line 12 · raw
@-A:Data -> @+fill:A -> @xs:List<&2, A> -> @+n:Nat -> List<&2, A>
|take(xs ++ replicate(n, fill), n)| = n. Identity when |xs| = n (take never reads the pad). Used to lock Run / select to the law size.
def word_all_false source · line 17 · raw
@n:Nat -> @w:Word(n) -> Bool
IEEE +0.0 is the all-false Word(32). Definitional on the 0.0 literal, so p=0 operator laws skip F32.is_gt / F32.is_eq (opaque Base laws).
def f32_is_zero source · line 28 · raw
@x:F32 -> Bool
def nat_min.fin source · line 33 · raw
@+a:Nat -> @+b:Nat -> @c:Bool -> Nat
def nat_min source · line 40 · raw
@+a:Nat -> @+b:Nat -> Nat
def nat_max.fin source · line 43 · raw
@+a:Nat -> @+b:Nat -> @c:Bool -> Nat
def nat_max source · line 50 · raw
@+a:Nat -> @+b:Nat -> Nat
def nat_pow source · line 53 · raw
@+b:Nat -> @e:Nat -> Nat
def binomial source · line 61 · raw
@+n:Nat -> @+k:Nat -> Nat
C(n, k). Das–Dennis count = C(p + M - 1, M - 1).
def in_nats source · line 70 · raw
@+x:Nat -> @xs:List<&2, Nat> -> Bool
def keep_if source · line 73 · raw
@-A:Data -> @+h:A -> @rest:List<&2, A> -> @keep:Bool -> List<&2, A>
def minus.put source · line 80 · raw
@h:Nat -> @rest:List<&2, Nat> -> @drop:Bool -> List<&2, Nat>
def minus source · line 87 · raw
@+xs:List<&2, Nat> -> @+ys:List<&2, Nat> -> List<&2, Nat>
def get_nat source · line 94 · raw
@xs:List<&2, Nat> -> @i:Nat -> Nat
def inc_at source · line 97 · raw
@+xs:List<&2, Nat> -> @+i:Nat -> List<&2, Nat>
def zeros_nat source · line 100 · raw
@n:Nat -> List<&2, Nat>
def nats_add source · line 103 · raw
@a:List<&2, Nat> -> @b:List<&2, Nat> -> List<&2, Nat>
def vec_min source · line 114 · raw
@a:List<&2, F32> -> @b:List<&2, F32> -> List<&2, F32>
def vec_max source · line 125 · raw
@a:List<&2, F32> -> @b:List<&2, F32> -> List<&2, F32>
def vec_sub source · line 136 · raw
@a:List<&2, F32> -> @b:List<&2, F32> -> List<&2, F32>
def vec_scale source · line 147 · raw
@+s:F32 -> @v:List<&2, F32> -> List<&2, F32>
def vec_dot source · line 154 · raw
@a:List<&2, F32> -> @b:List<&2, F32> -> F32
def vec_sqnorm source · line 165 · raw
@+v:List<&2, F32> -> F32
def ones_f32 source · line 168 · raw
@n:Nat -> List<&2, F32>
def zeros_f32 source · line 171 · raw
@n:Nat -> List<&2, F32>
def get_f32 source · line 174 · raw
@xs:List<&2, F32> -> @i:Nat -> F32
def set_f32 source · line 177 · raw
@xs:List<&2, F32> -> @i:Nat -> @x:F32 -> List<&2, F32>
def f32_or_one source · line 180 · raw
@+span:F32 -> @tiny:Bool -> F32
def denom source · line 188 · raw
@+lo:F32 -> @+hi:F32 -> F32
C# Normalize: denom < 1e-12 → 1.0 (intercept span uses the same floor).
def vec_norm_div source · line 192 · raw
@f:List<&2, F32> -> @ideal:List<&2, F32> -> @nadir:List<&2, F32> -> List<&2, F32>
def csv_step source · line 203 · raw
@x:F32 -> @acc:String -> String
def show_f32s source · line 210 · raw
@xs:List<&2, F32> -> String
def f32s_eq source · line 213 · raw
@a:List<&2, F32> -> @b:List<&2, F32> -> Bool
def has_f32s source · line 224 · raw
@+needle:List<&2, F32> -> @xs:List<&2, List<&2, F32>> -> Bool
def g12_scale source · line 235 · raw
F32
C# Unsga3Algorithm.DecisionKey: double.ToString("G12") — 12 significant digits, which on the unit box is 12 decimal places. Round each coord to 12 dp before duplicate-key compare. Bend F32 ULP is coarser than 1e-12, so this matches C# G12 at the precision this tree has.
def g12_round_abs source · line 238 · raw
@+x:F32 -> F32
def g12_one.signed source · line 242 · raw
@+x:F32 -> @neg:Bool -> F32
def g12_one source · line 249 · raw
@+x:F32 -> F32
def g12_vec.go source · line 313 · raw
@xs:List<&2, F32> -> @acc:List<&2, F32> -> List<&2, F32>
Sequential cons walk (guide: the list is the shape a flat loop walks). n_var is 12–30 on the oracles; mid-split take/drop of that spine is more expensive than a tail walk. Same rounding as the old map_halves.
def g12_vec source · line 320 · raw
@xs:List<&2, F32> -> List<&2, F32>
Templates
template map_halves.go source · line 255 · raw
@-A:Data -> @-B:Data -> @-C:Data -> @-f:(@+c:C -> @+x:A -> B) -> @+ctx:C -> @+fuel:Nat -> @xs:List<&2, A> -> List<&2, B>
Balanced fork-join map. Singleton / empty stay sequential. Fuel 0 is a
total fallback (public callers pass |xs|). ~f is a closed top-level.
Mid take/drop is inlined: a computed pair cannot be matched.
template map_halves source · line 279 · raw
@-A:Data -> @-B:Data -> @-C:Data -> @-f:(@+c:C -> @+x:A -> B) -> @+ctx:C -> @+xs:List<&2, A> -> List<&2, B>
template filter_halves.go source · line 284 · raw
@-A:Data -> @-C:Data -> @-p:(@+c:C -> @+x:A -> Bool) -> @+ctx:C -> @+fuel:Nat -> @xs:List<&2, A> -> List<&2, A>
Independent keep/drop. Mid-split; take ++ drop matches the old
tail-first cons_if walk (original relative order).
template filter_halves source · line 307 · raw
@-A:Data -> @-C:Data -> @-p:(@+c:C -> @+x:A -> Bool) -> @+ctx:C -> @+xs:List<&2, A> -> List<&2, A>