package grenier
Module Maxtrie.PatSetSource
Immutable sets of non-negative integers.
Sets are represented as Patricia tries in which every node hoists the largest key of its subtree and carries a bitmap of Sys.word_size - 1 consecutive elements. A set with n distinct bitmap keys has exactly n nodes, there are no internal branching nodes, and the depth of a tree is bounded by the number of bits of an integer.
The representation is canonical: two sets are equal if and only if they are structurally equal. The maximum of a set is at the root of its tree.
Elements must be non-negative: add and singleton raise Invalid_argument on a negative element; the other operations treat negative elements as absent.
The type of sets.
Construction
add x s is the union of singleton x and s. If x is already in s, then s itself is returned.
remove x s is the set s deprived of the element x. If x is not in s, then s itself is returned.
union s1 s2 is the union of the sets s1 and s2. If the union is equal to s2, then s2 itself is returned.
inter s1 s2 is the intersection of the sets s1 and s2. If the result is equal to s1, then s1 itself is returned.
diff s1 s2 is the set difference of s1 and s2. If the result is equal to s1, then s1 itself is returned.
above x s is the set of the elements of s that are strictly greater than x.
below x s is the set of the elements of s that are strictly less than x.
at_least x s is the set of the elements of s that are greater than or equal to x.
at_most x s is the set of the elements of s that are less than or equal to x.
filter p s is the set of the elements of s that satisfy p. The predicate is applied to the elements in increasing order. If every element satisfies p, then s itself is returned.
partition p s is (filter p s, filter (fun x -> not (p x)) s).
Cardinality
Tests
compare is a total order on sets, compatible with equal. It is a structural order, not the lexicographic order on sorted elements.
Comparisons with sharing. Sharing.equal and Sharing.compare return the same results as equal and compare, but as a side effect they make the structurally equal subtrees of their arguments physically equal. This makes later comparisons of these sets faster and reduces memory usage when many equal sets are built independently. It is invisible to every other operation, and safe in the presence of concurrent domains.
quick_subset s1 s2 is a fast test for the property s1 <> ∅ ∧ s1 ⊆ s2, under the precondition s1 ⊆ s2 ∨ s1 ∩ s2 = ∅. Under this precondition, it is equivalent to not (disjoint s1 s2). Its cost is that of mem.
Extraction
choose s is an element of s (currently its maximum, which is the cheapest one to find).
Iteration
iter f s applies f to the elements of s in increasing order.
rev_iter f s applies f to the elements of s in decreasing order.
fold f s b folds f over the elements of s in increasing order.
for_all p s determines whether all elements of s satisfy p.
exists p s determines whether some element of s satisfies p.
find_first_opt p s is the least element of s that satisfies p, if any. The predicate need not be monotonic.
Decomposition
compare_minimum is a total preorder on sets: the empty set is less than any non-empty set, and two non-empty sets are compared by their minimum elements.
sorted_union ss is the union of the sets in the list ss. (Any list of sets is accepted; this function is efficient when the sets are sorted and do not overlap.)
extract_unique_prefix s1 s2 requires s2 to be non-empty. It splits s1 into (head1, tail1) where head1 is the subset of the elements of s1 that are less than minimum s2.
extract_shared_prefix s1 s2 is (head, (tail1, tail2)) where head is the longest common prefix of s1 and s2 (viewed as increasing sequences), s1 = head ∪ tail1 and s2 = head ∪ tail2.
extract_unique_suffix s1 s2 requires s2 to be non-empty. It splits s1 into (head1, tail1) where head1 is the subset of the elements of s1 that are greater than maximum s2.
extract_shared_suffix s1 s2 is (head, (tail1, tail2)) where head is the longest common suffix of s1 and s2 (viewed as increasing sequences), s1 = head ∪ tail1 and s2 = head ∪ tail2.