Module: collections-internals Author: Keith Dennison Synopsis: Define and its operations Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND define sealed domain make(singleton()); define sealed primary class () slot member-vector-pad :: = 0, init-keyword: pad:; slot member-vector :: = make(, size: 0), init-keyword: member-vector:; end; // // INITIALIZE // define sealed method initialize (set :: , #key member-vector = unsupplied(), pad = unsupplied(), upper-bound-hint = unsupplied(), members = unsupplied(), all-members-from :: false-or() = #f) => () next-method(); if (~supplied?(member-vector)) let pad :: = 0; if (all-members-from) upper-bound-hint := all-members-from; pad := 1; end if; if (supplied?(upper-bound-hint)) let vector :: = make(, size: upper-bound-hint); set.member-vector-pad := pad; set.member-vector := vector; end if; end if; if (supplied?(members)) // do(method(i :: ) set-add!(set, i) end, members); do(curry(set-add!, set), members); end if; end method; // // \= // define sealed method \= (set1 :: , set2 :: ) => (result :: ) if (set1 == set2) #t; elseif (set1.member-vector-pad ~= set2.member-vector-pad) #f; else let vector1 = set1.member-vector; let vector2 = set2.member-vector; let min-size = min(size(vector1), size(vector2)); let result = #t; for (i :: from 0 below min-size) result := result & (vector1[i] = vector2[i]); end for; for (i :: from min-size below size(vector1)) result := result & (vector1[i] = set1.member-vector-pad); end for; for (i :: from min-size below size(vector2)) result := result & (vector2[i] = set2.member-vector-pad); end for; result; end if; end method; // // MEMBER? // define sealed method member? (i :: , set :: , #key test) => (result :: ) if (i < 0) element-range-error(set, i); end if; if (i < size(set.member-vector)) element-no-bounds-check(set.member-vector, i) = 1; // set.member-vector[i] = 1; else set.member-vector-pad = 1; end if; // ALTERNATIVE? // element(set, i, default: not-found()) = i; end method; // // SET-ADD // define sealed method set-add (set :: , i :: ) => (new-set :: ) if (i < 0) element-range-error(set, i); end if; let vector = if (i >= size(set.member-vector) & set.member-vector-pad = 0) make(, size: (i + 1), round-up-size?: #t, fill: 0, copy-from: set.member-vector); else copy-sequence(set.member-vector); end if; if (i < size(vector)) element-no-bounds-check-setter(1, vector, i); // vector[i] := 1; end if; make(, pad: set.member-vector-pad, member-vector: vector); end method; // // SET-ADD! // define sealed method set-add! (set :: , i :: ) => (set :: ) if (i < 0) element-range-error(set, i); end if; if (i >= size(set.member-vector)) if (set.member-vector-pad = 0) set.member-vector := make(, size: (i + 1), round-up-size?: #t, fill: 0, copy-from: set.member-vector); element-no-bounds-check-setter(1, set.member-vector, i); // set.member-vector[i] := 1; end if; else element-no-bounds-check-setter(1, set.member-vector, i); // set.member-vector[i] := 1; end if; set end method; // // ADD! // define sealed inline method add! (set :: , i :: ) => (set :: ) set-add!(set, i); end method; // // SET-REMOVE // define sealed method set-remove (set :: , i :: ) => (new-set :: ) if (i < 0) element-range-error(set, i); end if; let vector = if (i >= size(set.member-vector) & set.member-vector-pad = 1) make(, size: (i + 1), round-up-size?: #t, fill: 1, copy-from: set.member-vector); else copy-sequence(set.member-vector); end if; if (i < size(vector)) element-no-bounds-check-setter(0, vector, i); // vector[i] := 0; end if; make(, pad: set.member-vector-pad, member-vector: vector); end method; // // SET-REMOVE! // define sealed method set-remove! (set :: , i :: ) => (new-set :: ) if (i < 0) element-range-error(set, i); end if; if (i >= size(set.member-vector)) if (set.member-vector-pad = 1) set.member-vector := make(, size: (i + 1), round-up-size?: #t, fill: 1, copy-from: set.member-vector); element-no-bounds-check-setter(0, set.member-vector, i); // set.member-vector[i] := 0; end if; else element-no-bounds-check-setter(0, set.member-vector, i); // set.member-vector[i] := 0; end if; set end method; // // REMOVE! // define sealed inline method remove! (set :: , i :: , #key test, count) => (new-set :: ) set-remove!(set, i); end method; // // ELEMENT // define sealed method element (set :: , key :: , #key default = unsupplied()) => (element) let bit = element(set.member-vector, key, default: not-found()); if (found?(bit)) bit == 1 elseif (set.infinite?) #t elseif (supplied?(default)) default else element-range-error(set, key); end end method; // // ELEMENT-SETTER // define sealed method element-setter (object :: , set :: , key :: ) => (el1 :: ) if (object ~= key) remove!(set, key); end if; set-add!(set, object); object; end method; // // INFINITE? // define sealed method infinite?(set :: ) => (result :: ) set.member-vector-pad = 1; end method; // // EMPTY? // define sealed method empty?(set :: ) => (result :: ) // ~infinite?(set) & empty?(set.member-vector); size(set) = 0; end method; // // SIZE // define sealed method size(set :: ) => (size :: false-or()) if (set.member-vector-pad = 1) #f; else bit-count(set.member-vector, bit-value: 1); end if; end method; // // SET-UNION // define sealed method set-union (set1 :: , set2 :: ) => (new-set :: ) let (vector, pad) = bit-vector-or(set1.member-vector, set2.member-vector, pad1: set1.member-vector-pad, pad2: set2.member-vector-pad); make(, member-vector: vector, pad: pad); end method; // // SET-UNION! // define sealed method set-union! (set1 :: , set2 :: ) => (set1 :: ) let (vector, pad) = bit-vector-or!(set1.member-vector, set2.member-vector, pad1: set1.member-vector-pad, pad2: set2.member-vector-pad); set1.member-vector := vector; set1.member-vector-pad := pad; set1; end method; // // SET-INTERSECTION // define sealed method set-intersection (set1 :: , set2 :: ) => (new-set :: ) let (vector, pad) = bit-vector-and(set1.member-vector, set2.member-vector, pad1: set1.member-vector-pad, pad2: set2.member-vector-pad); make(, member-vector: vector, pad: pad); end method; // // SET-INTERSECTION! // define sealed method set-intersection! (set1 :: , set2 :: ) => (set1 :: ) let (vector, pad) = bit-vector-and!(set1.member-vector, set2.member-vector, pad1: set1.member-vector-pad, pad2: set2.member-vector-pad); set1.member-vector := vector; set1.member-vector-pad := pad; set1; end method; // // SET-DIFFERENCE // define sealed method set-difference (set1 :: , set2 :: ) => (new-set :: ) let (vector, pad) = bit-vector-andc2(set1.member-vector, set2.member-vector, pad1: set1.member-vector-pad, pad2: set2.member-vector-pad); make(, member-vector: vector, pad: pad); end method; // // SET-DIFFERENCE! // define sealed method set-difference! (set1 :: , set2 :: ) => (set1 :: ) let (vector, pad) = bit-vector-andc2!(set1.member-vector, set2.member-vector, pad1: set1.member-vector-pad, pad2: set2.member-vector-pad); set1.member-vector := vector; set1.member-vector-pad := pad; set1; end method; // // SET-COMPLEMENT // define sealed method set-complement (set :: ) => (new-set :: ) let (vector, pad) = bit-vector-not(set.member-vector, pad: set.member-vector-pad); make(, member-vector: vector, pad: pad); end method; // // SET-COMPLEMENT! // define sealed method set-complement! (set :: ) => (set :: ) let (vector, pad) = bit-vector-not!(set.member-vector, pad: set.member-vector-pad); set.member-vector := vector; set.member-vector-pad := pad; set; end method; // // COPY-BIT-SET! // define function copy-bit-set! (set1 :: , set2 :: ) => () set1.member-vector-pad := set2.member-vector-pad; set1.member-vector := copy-sequence(set2.member-vector); end function; // // // EMPTY-BIT-SET! // define function empty-bit-set!(set :: ) => () set.member-vector-pad := 0; fill!(set.member-vector, 0); end function; // // UNIVERSAL-BIT-SET! // define function universal-bit-set!(set :: ) => () set.member-vector-pad := 1; fill!(set.member-vector, 1); end function; // // ITERATION PROTOCOLS // define generic current-word (state :: ) => (word :: ); define generic current-word-setter (new :: , state :: ) => (word :: ); define sealed domain make(singleton()); define primary sealed class () raw slot current-word :: ; slot current-element :: , required-init-keyword: current-element:; slot word-offset :: , required-init-keyword: word-offset:; slot bit-offset :: , required-init-keyword: bit-offset:; end class; define inline-only method current-word (state :: ) => (word :: ) primitive-cast-pointer-as-raw(primitive-initialized-slot-value(state, integer-as-raw(0))) end method current-word; define inline-only method current-word-setter (word :: , state :: ) => (word :: ) primitive-slot-value(state, integer-as-raw(0)) := primitive-cast-raw-as-pointer(word); word end method current-word-setter; define sealed method initialize (state :: , #key word :: ) => () next-method(); state.current-word := primitive-unwrap-machine-word(word) end method initialize; define inline function bs-ip-current-key (collection :: , state :: ) => (key :: ) state.current-element; end function; define inline function bs-ip-current-element (collection :: , state :: ) => (element :: ) state.current-element; end function; define inline function bs-ip-current-element-setter (value :: , collection :: , state :: ) => (value :: ) error("Cannot update current element of a set during iteration."); end function; define inline function bs-ip-copy-state (collection :: , state :: ) => (new-state :: ) make(, word: primitive-wrap-machine-word(state.current-word), bit-offset: state.bit-offset, word-offset: state.word-offset, current-element: state.current-element); end function; // // FORWARD-ITERATION-PROTOCOL // define inline function bs-fip-initial-state (set :: ) => (initial-state :: ) let current-word :: = integer-as-raw(0); let word-offset :: = word-size(set.member-vector) - 1; let bit-offset :: = $machine-word-size; block (return) for (j :: from 0 below word-size(set.member-vector)) for (i :: from 0 below $machine-word-size, word :: = bit-vector-word(set.member-vector, j) then primitive-machine-word-unsigned-shift-right(word, integer-as-raw(1))) if (raw-as-integer(primitive-machine-word-logand(word, integer-as-raw(1))) = 1) current-word := word; word-offset := j; bit-offset := i; return() end if end for end for end block; make(, word: primitive-wrap-machine-word(current-word), word-offset: word-offset, bit-offset: bit-offset, current-element: ((word-offset * $machine-word-size) + bit-offset)); end function; define inline function bs-fip-limit (set :: ) => (limit :: ) size(set.member-vector); end function; define inline function bs-fip-next-state (collection :: , state :: ) => (new-state :: ) if (state.current-element >= size(collection.member-vector)) state.current-element := state.current-element + 1; else block(return) for (i :: from state.bit-offset + 1 below $machine-word-size, word :: = primitive-machine-word-unsigned-shift-right(state.current-word, integer-as-raw(1)) then primitive-machine-word-unsigned-shift-right(word, integer-as-raw(1))) state.current-element := state.current-element + 1; if (raw-as-integer(primitive-machine-word-logand(word, integer-as-raw(1))) = 1) state.current-word := word; state.bit-offset := i; return(); end if; end for; for (j :: from state.word-offset + 1 below word-size(collection.member-vector)) for (i :: from 0 below $machine-word-size, word :: = bit-vector-word(collection.member-vector, j) then primitive-machine-word-unsigned-shift-right(word, integer-as-raw(1))) state.current-element := state.current-element + 1; if (raw-as-integer(primitive-machine-word-logand(word, integer-as-raw(1))) = 1) state.current-word := word; state.bit-offset := i; state.word-offset := j; return(); end if; end for; end for; state.current-element := size(collection.member-vector); end block; end if; state; end function; define inline function bs-fip-finished-state? (collection :: , state :: , limit :: ) => (boolean :: ) (collection.member-vector-pad = 0 & state.current-element >= limit) end function; define sealed method forward-iteration-protocol(set :: ) => (initial-state :: , limit :: , next-state :: , finished-state? :: , current-key :: , current-element :: , current-element-setter :: , copy-state :: ) values(bs-fip-initial-state(set), bs-fip-limit(set), bs-fip-next-state, bs-fip-finished-state?, bs-ip-current-key, bs-ip-current-element, bs-ip-current-element-setter, bs-ip-copy-state); end method; // // BACKWARD-ITERATION-PROTOCOL // define inline function bs-bip-initial-state (set :: ) => (initial-state :: ) let current-word :: = integer-as-raw(0); let word-offset :: = 0; let bit-offset :: = -1; block (return) for (woff :: from word-size(set.member-vector) - 1 to 0 by -1) let word :: = bit-vector-word(set.member-vector, woff); for (boff :: from $machine-word-size - 1 to 0 by -1) word := primitive-machine-word-unsigned-rotate-left(word, integer-as-raw(1)); if (raw-as-integer(primitive-machine-word-logand(word, integer-as-raw(1))) = 1) current-word := word; word-offset := woff; bit-offset := boff; return() end if end for end for end block; let state = make(, word: primitive-wrap-machine-word(current-word), word-offset: word-offset, bit-offset: bit-offset, current-element: ((word-offset * $machine-word-size) + bit-offset)); state; end function; define inline function bs-bip-limit (set :: ) => (limit :: ) 0; end function; define inline function bs-bip-next-state (collection :: , state :: ) => (new-state :: ) block(return) let word :: = state.current-word; for (i :: from state.bit-offset - 1 above -1 by -1) state.current-element := state.current-element - 1; word := primitive-machine-word-unsigned-rotate-left (word, integer-as-raw(1)); if (raw-as-integer(primitive-machine-word-logand (word, integer-as-raw(1))) = 1) state.bit-offset := i; state.current-word := word; return(); end if; end for; for (j :: from state.word-offset - 1 above -1 by -1) let word :: = bit-vector-word(collection.member-vector, j); for (i :: from $machine-word-size above 0 by -1) word := primitive-machine-word-unsigned-rotate-left (word, integer-as-raw(1)); state.current-element := state.current-element - 1; if (raw-as-integer(primitive-machine-word-logand (word, integer-as-raw(1))) = 1) state.bit-offset := i - 1; state.word-offset := j; state.current-word := word; return(); end if; end for; end for; state.bit-offset := -1; state.word-offset := -1; state.current-element := -1; end block; state; end function; define inline function bs-bip-finished-state? (collection :: , state :: , limit :: ) => (boolean :: ) state.current-element < 0; end function; define sealed method backward-iteration-protocol(set :: ) => (initial-state :: , limit :: , next-state :: , finished-state? :: , current-key :: , current-element :: , current-element-setter :: , copy-state :: ) if (infinite?(set)) error("BACKWARD-ITERATION-PROTOCOL called on infinite set %=", set); end if; values(bs-bip-initial-state(set), bs-bip-limit(set), bs-bip-next-state, bs-bip-finished-state?, bs-ip-current-key, bs-ip-current-element, bs-ip-current-element-setter, bs-ip-copy-state); end method;