Skip to content

use bitmask AND for cross set computation, skip dead anchors#18

Merged
andy-k merged 6 commits intomainfrom
letter-bits-table
Mar 28, 2026
Merged

use bitmask AND for cross set computation, skip dead anchors#18
andy-k merged 6 commits intomainfrom
letter-bits-table

Conversation

@andy-k
Copy link
Copy Markdown
Owner

@andy-k andy-k commented Mar 28, 2026

Summary

  • Precompute LetterBits table (letter_bits + accepting_bits per KWG sibling group) for O(1) child tile lookups
  • Replace iterative child loops in one-sided cross set cases with accepting_bits lookup
  • Replace sorted merge-intersect in left-and-right cross set case with letter_bits AND pre-filter
  • Skip dead anchors (both extension sets zero) regardless of want_raw mode
  • Drop 24MB LetterBits table from WorkingBuffer — compute bitmasks on the fly instead (cache-friendly, WASM-safe)
  • Keep LetterBits struct in kwg.rs for callers that want precomputed tables

Test plan

  • movegen baseline unchanged across all commits
  • cargo fmt, clippy, build pass on all commits

andy-k and others added 6 commits March 28, 2026 15:30
Add LetterBits: a precomputed bitmask of child tiles for each
KWG sibling group position. Computed once per KWG (lazily on
first use, invalidated on reset_for_another_kwg).

Replace collect_bits iteration in gen_extension_sets with a
single letter_bits table lookup via extension_bits_from_letter_bits.
Eliminates all KWG child iteration from extension set computation.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Extend LetterBits to also precompute accepting_bits: bitmask of
child tiles that complete a word (node.accepts() is true). This
enables O(1) cross set child enumeration in a follow-up commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Replace iterative KWG child loops in the "right, no left" and
"left, no right" cross set cases with O(1) accepting_bits table
lookups. The "left and right" merge-intersect case still
iterates (different algorithm, not a simple lookup).

Thread letter_bits table through gen_cross_set for access during
cross set computation. Lazily initialized before cross set loops.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Replace the sorted merge-intersect of two KWG sibling groups
with an O(1) bitwise AND of their letter_bits. Only candidate
tiles present in both groups need the full KWG word verification
traversal. Eliminates the dual-pointer merge loop.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The extension set anchor skip (both left and right extension
sets are zero) is not equity-based pruning — it means no word
can be formed at this anchor. Apply it before the want_raw
check so dead anchors are skipped in all modes.

Also use && short-circuit instead of | to avoid loading the
second extension set when the first is already zero.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Replace precomputed letter_bits/accepting_bits table lookups
with on-the-fly sibling group iteration. The table was 24MB
(2x 12MB for ~1.5M KWG nodes) which hurts cache and is too
large for WASM targets. The on-the-fly computation is short
sequential loops over contiguous siblings — cache-friendly.

Keep LetterBits struct and compute_letter_bits() in kwg.rs for
callers that want precomputed tables.

Remove stale letter_bits comments and clone comment for
accepts_alpha_cache (source of truth is the struct field).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@andy-k andy-k merged commit f4c4ccf into main Mar 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant