src/containers/internal/vec.bend source
src/containers/internal/vec.bend on the hub · documented module
import Base# Persistent fixed-size vector: a perfect binary tree of depth d holding# 2^d slots, slot j addressed by comparing j with 2^(d-1) at each level.# get/set cost O(d) = O(log size); the tree is immutable Data, so updates# share all untouched subtrees. Shared by structures that need indexed# storage. Do not instantiate with U32 payloads through this# erased-generic code (see docs/VALIDATION.md, runtime defects).type Vec<-T: Data> is Data: VLeaf{value: T} VNode{lo: Vec<T>, hi: Vec<T>}def pow2(k: Nat) -> Nat: match k: case 0n: 1n case 1n+p: Nat.double(pow2(p))# Branch decision at a node of depth d for slot j: True = lower half.def dec(d: Nat, +j: Nat) -> Bool: match d: case 0n: False{} case 1n+q: Nat.is_lt(j, pow2(q))def get_go(-T: Data, d: Nat, t: Vec<T>, +j: Nat, left: Bool) -> Maybe<&2, T>: match d t left: case 0n VLeaf{x} _: Some{x} case 0n VNode{l, r} _: None{} case 1n+p VLeaf{x} _: None{} case 1n+ +p VNode{l, r} True{}: get_go(T, p, l, j, dec(p, j)) case 1n+ +p VNode{l, r} False{}: get_go(T, p, r, Nat.sub(j, pow2(p)), dec(p, Nat.sub(j, pow2(p))))# Slot j of a depth-d vector (None only for a malformed tree).def get(-T: Data, +d: Nat, t: Vec<T>, +j: Nat) -> Maybe<&2, T>: get_go(T, d, t, j, dec(d, j))def set_go(-T: Data, d: Nat, t: Vec<T>, +j: Nat, +v: T, left: Bool) -> Vec<T>: match d t left: case 0n VLeaf{x} _: VLeaf{v} case 0n VNode{l, r} _: VNode{l, r} case 1n+p VLeaf{x} _: VLeaf{x} case 1n+ +p VNode{l, r} True{}: VNode{set_go(T, p, l, j, v, dec(p, j)), r} case 1n+ +p VNode{l, r} False{}: VNode{l, set_go(T, p, r, Nat.sub(j, pow2(p)), v, dec(p, Nat.sub(j, pow2(p))))}# Replace slot j (j < 2^d).def set(-T: Data, +d: Nat, t: Vec<T>, +j: Nat, +v: T) -> Vec<T>: set_go(T, d, t, j, v, dec(d, j))# Smallest depth whose capacity covers n more slots: `room` counts the free# slots left at the current depth (capacity 2^d).def depth_go(n: Nat, +d: Nat, room: Nat) -> Nat: match n room: case 0n _: d case 1n+p 0n: depth_go(p, 1n+d, Nat.sub(pow2(d), 1n)) case 1n+p 1n+r: depth_go(p, d, r)def depth_for(n: Nat) -> Nat: depth_go(n, 0n, 1n)