From cb626fc402d751e96703722942844f53f180906d Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 10 May 2026 23:48:46 +0000 Subject: [PATCH] ocaml: phase 5.1 fenwick_tree.ml baseline (BIT over 8 elements, fingerprint 228) Fenwick / Binary Indexed Tree for prefix sums. The classic `i & -i` low-bit trick needs negative-aware AND, but our `land` evaluator (iter 127, bitwise via floor/mod arithmetic) only handles non-negative operands. Workaround: a portable lowbit helper that finds the largest power of 2 dividing i: let lowbit i = let r = ref 1 in while !r * 2 <= i && i mod (!r * 2) = 0 do r := !r * 2 done; !r After building from [1;3;5;7;9;11;13;15]: total = prefix_sum 8 = 64 update 1 by +100 after = prefix_sum 8 = 164 total + after = 228 Tests recursive update / prefix_sum chains via helper-extracted lowbit; documents a non-obvious limit of the bitwise-emulation layer. 168 baseline programs total. --- lib/ocaml/baseline/expected.json | 1 + lib/ocaml/baseline/fenwick_tree.ml | 33 ++++++++++++++++++++++++++++++ plans/ocaml-on-sx.md | 11 ++++++++++ 3 files changed, 45 insertions(+) create mode 100644 lib/ocaml/baseline/fenwick_tree.ml diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index f028eba3..864e52a3 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -56,6 +56,7 @@ "expr_eval.ml": 16, "expr_simp.ml": 22, "factorial.ml": 3628800, + "fenwick_tree.ml": 228, "fib_doubling.ml": 102334155, "fib_mod.ml": 391360, "fraction.ml": 7, diff --git a/lib/ocaml/baseline/fenwick_tree.ml b/lib/ocaml/baseline/fenwick_tree.ml new file mode 100644 index 00000000..8b4a2aa7 --- /dev/null +++ b/lib/ocaml/baseline/fenwick_tree.ml @@ -0,0 +1,33 @@ +let n = 8 + +let bit = Array.make (n + 1) 0 + +let lowbit i = + let r = ref 1 in + while !r * 2 <= i && i mod (!r * 2) = 0 do + r := !r * 2 + done; + !r + +let rec update i delta = + if i <= n then begin + bit.(i) <- bit.(i) + delta; + update (i + lowbit i) delta + end + +let rec prefix_sum i = + if i <= 0 then 0 + else bit.(i) + prefix_sum (i - lowbit i) + +let range_sum l r = prefix_sum r - prefix_sum (l - 1) + +;; + +let a = [| 1; 3; 5; 7; 9; 11; 13; 15 |] in +for i = 0 to n - 1 do + update (i + 1) a.(i) +done; +let total = prefix_sum n in +update 1 100; +let after = prefix_sum n in +total + after diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 930aadcd..2b0d06f3 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,17 @@ _Newest first._ binary search tree (`type 'a tree = Leaf | Node of 'a * 'a tree * 'a tree`) with insert + in-order traversal. Tests parametric ADT, recursive match, List.append, List.fold_left. +- 2026-05-10 Phase 5.1 — fenwick_tree.ml baseline (Binary Indexed + Tree over [1;3;5;7;9;11;13;15], total + after = 228). Initial + prefix_sum n = 64; after +100 at index 1, prefix_sum n = 164; + 64 + 164 = 228. Because our `land` evaluator implementation only + handles non-negative operands (iter 127 bitwise-via-arithmetic + workaround), and Fenwick relies on `i & -i` to extract the + lowest set bit, we replace `i land (-i)` with a portable + `lowbit` helper: largest power-of-2 dividing i. Tests recursive + update / prefix_sum chains using helper-extracted lowbit, + highlights a non-obvious tradeoff in the bitwise-emulation + layer. 168 baseline programs total. - 2026-05-10 Phase 5.1 — segment_tree.ml baseline (range-sum segment tree over [1;3;5;7;9;11;13;15] with one point update, encoded r1 + r2*100 = 4232). build/query/update use the standard