lib.bend source
lib.bend on the hub · documented module
# ColorSample — Color layer 3: sample RGB within a ColorRange using Prng.## Hub deps (own CAS ids; not folded into this package's published blob):# Color 0xc6ecb72f45a1b2f83318765698582f7f# Prng 0xfd7037736e4fa1794a671d0278638da7## Maybe gate is U32-only: Color.range_valid uses F32.is_le on alpha, which is# opaque to definitional equality. Callers who need alpha ordering should still# call Color.range_valid first. No Hsl range type in Color layer 1 → RGB only.# Base + hub imports only; no termination escapes.import Baseimport 0xc6ecb72f45a1b2f83318765698582f7f/lib.bend as Colorimport 0xfd7037736e4fa1794a671d0278638da7/lib.bend as Prng# Inclusive U32 width. Precondition: lo <= hi (enforced by the Maybe gate).def ColorSample.span(+lo: U32, +hi: U32) -> U32: U32.add(U32.sub(hi, lo), 1)def ColorSample.channel.go(+lo: U32, r: U32 & Prng.Prng) -> U32 & Prng.Prng: (v, p2) = r (U32.add(lo, v), p2)# Uniform draw in lo..=hi via next_bounded(span).def ColorSample.channel(p: Prng.Prng, +lo: U32, +hi: U32) -> U32 & Prng.Prng: ColorSample.channel.go(lo, Prng.Prng.next_bounded(p, ColorSample.span(lo, hi)))def ColorSample.alpha.go(+lo: F32, +hi: F32, r: F32 & Prng.Prng) -> F32 & Prng.Prng: (t, p2) = r (F32.add(lo, F32.mul(F32.sub(hi, lo), t)), p2)# Lerp alpha with next_f32 in [0, 1). Always advances the PRNG.def ColorSample.alpha(p: Prng.Prng, +lo: F32, +hi: F32) -> F32 & Prng.Prng: ColorSample.alpha.go(lo, hi, Prng.Prng.next_f32(p))# Thread PRNG through r → g → b → a. Helpers are ordered bottom-up; each match# scrutinizes a parameter (Bend forbids matching computed pairs inline).def ColorSample.after_a.go( +r: U32, +g: U32, +b: U32, ra: F32 & Prng.Prng) -> Color.Rgb & Prng.Prng: (a, p4) = ra (Color.Rgb{r, g, b, a}, p4)def ColorSample.after_b.go( +aa: F32, +ba: F32, +r: U32, +g: U32, rb: U32 & Prng.Prng) -> Color.Rgb & Prng.Prng: (b, p3) = rb ColorSample.after_a.go(r, g, b, ColorSample.alpha(p3, aa, ba))def ColorSample.after_g.go( +ab: U32, +aa: F32, +bb: U32, +ba: F32, +r: U32, rg: U32 & Prng.Prng) -> Color.Rgb & Prng.Prng: (g, p2) = rg ColorSample.after_b.go(aa, ba, r, g, ColorSample.channel(p2, ab, bb))def ColorSample.after_r.go( +ag: U32, +ab: U32, +aa: F32, +bg: U32, +bb: U32, +ba: F32, +r: U32, p1: Prng.Prng) -> Color.Rgb & Prng.Prng: ColorSample.after_g.go(ab, aa, bb, ba, r, ColorSample.channel(p1, ag, bg))def ColorSample.rgb.go( +ar: U32, +ag: U32, +ab: U32, +aa: F32, +br: U32, +bg: U32, +bb: U32, +ba: F32, rr: U32 & Prng.Prng) -> Color.Rgb & Prng.Prng: (r, p1) = rr ColorSample.after_r.go(ag, ab, aa, bg, bb, ba, r, p1)def ColorSample.rgb.from_ends( +ar: U32, +ag: U32, +ab: U32, +aa: F32, +br: U32, +bg: U32, +bb: U32, +ba: F32, p: Prng.Prng) -> Color.Rgb & Prng.Prng: ColorSample.rgb.go(ar, ag, ab, aa, br, bg, bb, ba, ColorSample.channel(p, ar, br))# Gate on U32 min<=max for r/g/b; sample when ok. Pair payload ⇒ Maybe<&1, …>.def ColorSample.rgb.with_ends( +ar: U32, +ag: U32, +ab: U32, +aa: F32, +br: U32, +bg: U32, +bb: U32, +ba: F32, p: Prng.Prng) -> Maybe<&1, Color.Rgb & Prng.Prng>: Bool.pick(Maybe<&1, Color.Rgb & Prng.Prng>, Bool.and(U32.is_le(ar, br), Bool.and(U32.is_le(ag, bg), U32.is_le(ab, bb))), Some{ColorSample.rgb.from_ends(ar, ag, ab, aa, br, bg, bb, ba, p)}, None{})def ColorSample.rgb(range: Color.ColorRange, p: Prng.Prng) -> Maybe<&1, Color.Rgb & Prng.Prng>: match range: case Color.ColorRange{min, max}: match min max: case Color.Rgb{ar, ag, ab, aa} Color.Rgb{br, bg, bb, ba}: ColorSample.rgb.with_ends(ar, ag, ab, aa, br, bg, bb, ba, p)# Same U32 predicate as the Maybe gate (for laws / callers).def ColorSample.range_ok_u32(r: Color.ColorRange) -> Bool: match r: case Color.ColorRange{min, max}: match min max: case Color.Rgb{ar, ag, ab, aa} Color.Rgb{br, bg, bb, ba}: Bool.and(U32.is_le(ar, br), Bool.and(U32.is_le(ag, bg), U32.is_le(ab, bb)))# Projection helper for laws. None{} yields black (laws only call on Some).def ColorSample.unwrap_rgb(m: Maybe<&1, Color.Rgb & Prng.Prng>) -> Color.Rgb: match m: case None{}: Color.Rgb{0, 0, 0, 0.0} case Some{pair}: Pair.fst(Color.Rgb, Prng.Prng, pair)