Skip to content

feat: Equaler/Disjointer/Subsetter predicate fast paths #minor - #43

Merged
freeformz merged 1 commit into
mainfrom
predicate-fast-paths
Jul 13, 2026
Merged

feat: Equaler/Disjointer/Subsetter predicate fast paths #minor#43
freeformz merged 1 commit into
mainfrom
predicate-fast-paths

Conversation

@freeformz

Copy link
Copy Markdown
Owner

Summary

Second item from the optional-interface survey (follow-up to #42): the predicate functions now have optimization hooks, using the same declining-boolean pattern as the set-algebra and Maxer/Minner interfaces.

New optional Equaler/Disjointer/Subsetter interfaces

Package-level Equal, Disjoint, and Subset consult their first operand and fall back to the generic element-wise path on decline. Superset is Subset with the operands swapped, so it consults its second operand's Subsetter — no fourth interface needed.

Predicates short-circuit and allocate nothing, so the wins are larger than the algebra ones:

  • SortedSet: Equal is a direct slices.Equal; Disjoint/Subset are short-circuiting two-pointer scans — O(N+M) worst case, no hashing
  • BitSet: Equal is a cardinality check + word compare, Disjoint ANDs the span overlap, Subset is word-wise AND NOT — all O(W) with early exit

Correctness subtleties handled: BitSet spans retained after Removes (equal sets can have different spans — words missing from a span compare as zero; for Equal, matching words over the receiver's span plus equal cardinalities imply no bits outside it), and typed-nil receivers/operands decline to the generic path rather than dereferencing backing storage (the class of bug review caught on #42).

Testing

  • TestSortedSet_PredicateOps / TestBitSet_PredicateOps: rapid differential tests of all four predicates against Map-based generic results, with equal/subset/superset/disjoint operand shapes drawn explicitly (independent draws would rarely produce them); mixed operands prove the fallback; targeted BitSet cases cover differing retained spans, non-overlapping spans, bits outside the other's span, and sign-bit mapping extremes
  • TestPredicateOptionalInterfaces: third-party-style stub proving the package-level functions honor external implementations (including Superset via the second operand) and fall back on decline
  • TestNilReceiverPredicates: pins the typed-nil decline behavior
  • go vet, staticcheck, and go test -race ./... all clean

🤖 Generated with Claude Code

https://claude.ai/code/session_01RLrWSEKLMPuf1kq1KDCoxs

Same optional-interface pattern as the set-algebra and Maxer/Minner hooks:
package-level Equal, Disjoint, and Subset consult their first operand
(Superset is Subset with the operands swapped, so it consults its second
operand's Subsetter) and fall back to the generic path on decline.

- SortedSet: short-circuiting two-pointer scans of the two sorted slices;
  Equal is a direct slices.Equal
- BitSet: word-wise compare / AND / AND NOT with early exit, correct across
  differing retained spans (missing words compare as zero); cardinality
  pre-checks keep the common unequal/too-big cases O(1)
- typed-nil receivers and operands decline to the generic path
- rapid differential tests against Map-based generic results with explicitly
  drawn equal/subset/superset/disjoint operand shapes, span-shape and
  sign-extreme BitSet cases, third-party stub coverage, nil-receiver pins

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLrWSEKLMPuf1kq1KDCoxs
Copilot AI review requested due to automatic review settings July 13, 2026 19:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds optional predicate-optimization interfaces to the sets package so Equal, Disjoint, Subset, and Superset can take fast paths when the operand types support them, matching the existing “declining boolean” pattern used for set algebra and Max/Min.

Changes:

  • Introduces new optional interfaces Equaler, Disjointer, and Subsetter, and wires them into the package-level predicate functions (including Superset via swapped operands).
  • Implements optimized predicate methods for SortedSet (slice/scan-based) and BitSet (word-wise with early exits and span-aware comparisons).
  • Adds differential + targeted tests to validate fast paths, fallback behavior, external implementations, and typed-nil decline behavior; updates docs to describe the new hooks.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
sorted.go Implements Equaler/Disjointer/Subsetter fast paths for SortedSet using slice equality and two-pointer scans.
sorted_test.go Adds rapid differential tests for predicate fast paths and verifies decline behavior for non-SortedSet operands.
set.go Defines the new optional predicate interfaces and updates Subset/Equal/Disjoint to consult them (and Superset via Subset(b, a)).
README.MD Documents the new predicate optional interfaces and how they’re consulted.
coverage_test.go Adds third-party-style stub tests proving package-level functions honor external implementations and decline on request; adds typed-nil predicate tests.
CLAUDE.md Updates architecture/docs to include the new predicate optimization interfaces.
bitset.go Implements Equaler/Disjointer/Subsetter fast paths for BitSet with span-aware word operations.
bitset_test.go Adds rapid differential tests plus targeted span-shape cases for BitSet predicate fast paths and decline behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@freeformz
freeformz merged commit fbead22 into main Jul 13, 2026
11 checks passed
@freeformz
freeformz deleted the predicate-fast-paths branch July 13, 2026 19:54
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.

2 participants