pax_global_header00006660000000000000000000000064130664607630014525gustar00rootroot0000000000000052 comment=810927e19d933bcf38ffeb7a23ce521efc432d45 cl-containers-20170403-git/000077500000000000000000000000001306646076300153115ustar00rootroot00000000000000cl-containers-20170403-git/.boring000066400000000000000000000011631306646076300165730ustar00rootroot00000000000000# Boring file regexps: \.hi$ \.o$ \.o\.cmd$ # *.ko files aren't boring by default because they might # be Korean translations rather than kernel modules. # \.ko$ \.ko\.cmd$ \.mod\.c$ (^|/)\.tmp_versions($|/) (^|/)CVS($|/) (^|/)RCS($|/) ~$ #(^|/)\.[^/] (^|/)_darcs($|/) \.bak$ \.BAK$ \.orig$ (^|/)vssver\.scc$ \.swp$ (^|/)MT($|/) (^|/)\{arch\}($|/) (^|/).arch-ids($|/) (^|/), \.class$ \.prof$ (^|/)\.DS_Store$ (^|/)BitKeeper($|/) (^|/)ChangeSet($|/) (^|/)\.svn($|/) \.py[co]$ \# \.cvsignore$ (^|/)Thumbs\.db$ (^|/)autom4te\.cache($|/) (^|/)scratch($|/) (^|/)two words($|/) (^|/)test-results($|/) \.dribble \.drb (^|/)make($|/) cl-containers-20170403-git/.gitignore000066400000000000000000000003111306646076300172740ustar00rootroot00000000000000# really this is private to my build process make/ common-lisp.net .vcs GNUmakefile init-lisp.lisp website/changelog.xml lift.tar.gz website/output/ test-results*/ lift-local.config *.dribble *.fasl cl-containers-20170403-git/COPYING000066400000000000000000000047761306646076300163620ustar00rootroot00000000000000Copyright (c) 2004-2008 Gary Warren King (gwking@metabang.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ;;; ----------------------------------------------------------------------- Copyright (c) 1994-2004 University of Massachusetts Department of Computer Science Experimental Knowledge Systems Laboratory Professor Paul Cohen, Director. All rights reserved. Permission to use, copy, modify and distribute this software and its documentation is hereby granted without fee for non-commercial uses only (not for resale), provided that the above copyright notice of EKSL, this paragraph and the one following appear in all copies and in supporting documentation. EKSL makes no representation about the suitability of this software for any purposes. It is provided "AS IS", without express or implied warranties including (but not limited to) all implied warranties of merchantability and fitness for a particular purpose, and notwithstanding any other provision contained herein. In no event shall EKSL be liable for any special, indirect or consequential damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortuous action, arising out of or in connection with the use or performance of this software, even if EKSL is advised of the possiblity of such damages. Thanks to Marc Atkin, Brendan Burns, Andrew Hannon, Anuan Gao, Brent Heeringa, Joshua Moody, Tim Oates, Michael O'Neil, Rob St. Amant, Charles Sutton, Louis Theran, David Westbrook, and other former students and staff of EKSL. cl-containers-20170403-git/GNUmakefile000066400000000000000000000003071306646076300173630ustar00rootroot00000000000000# add shared-copy shared_destination = "gking@common-lisp.net:/project/cl-containers/public_html/shared/" shared-copy: FORCE rcopy website/source/shared/ $(shared_destination) @$(run_postactions) cl-containers-20170403-git/cl-containers-documentation.asd000066400000000000000000000012231306646076300234100ustar00rootroot00000000000000(defsystem "cl-containers-documentation" :author "Gary King " :maintainer "Gary Warren King " :licence "MIT Style License" :description "Documentation for CL-Containers" :components ((:module "setup" :pathname "docs/" :components ((:file "package") (:file "setup" :depends-on ("package")))) (:module "docs" :depends-on ("setup") :pathname "website/source/" :components ((:docudown-source "index.md") (:docudown-source "user-guide.md") #+(or) (:docudown-wild "shared:**:*.*" :output "../output/shared/")))) :depends-on ("cl-containers" "docudown")) cl-containers-20170403-git/cl-containers-test.asd000066400000000000000000000012511306646076300215170ustar00rootroot00000000000000(defsystem "cl-containers-test" :author "Gary King " :maintainer "Gary Warren King " :licence "MIT Style License" :description "Tests for CL-Containers" :components ((:module "setup" :pathname "tests/" :components ((:file "package") (:file "test-containers" :depends-on ("package")))) (:module "tests" :depends-on ("setup") :components ((:file "priority-queues") (:file "trees") (:file "dlist")))) :depends-on ("cl-containers" (:version "lift" "1.7.0")) :perform (test-op (op c) (describe (symbol-call :lift :run-tests :config :generic)))) cl-containers-20170403-git/cl-containers.asd000066400000000000000000000074611306646076300205530ustar00rootroot00000000000000#| Author: Gary King, et. al. Major contributions by Andrew Hannon, David Westbrook, Gary King, Brent Heeringa, Louis Theran |# ;; try hard (unless (or (member :asdf-system-connections *features*) (find-system 'asdf-system-connections nil)) (warn "The CL-Containers system would enjoy having ~ asdf-system-connections around. See http://www.cliki.net/asdf-system-connections for details and download instructions.")) (when (and (not (member :asdf-system-connections *features*)) (find-system 'asdf-system-connections nil)) (load-system "asdf-system-connections")) (defsystem "cl-containers" :version "0.12.1" :author "Brendan Burns, Andrew Hannon, Brent Heeringa, Gary King, Joshua Moody, Charles Sutton, Louis Theran, David Westbrook, and other former students and staff of EKSL." :maintainer "Gary Warren King " :licence "MIT Style License" :description "A generic container library for Common Lisp" :components ((:module "setup" :pathname "dev/" :components ((:file "package") (:file "conditions" :depends-on ("package")) )) (:module "dev" :depends-on ("setup") :components ((:file "container-api") (:file "containers") (:file "basic-operations" :depends-on ("container-api" "containers")) (:file "queues" :depends-on ("basic-operations")) (:file "stacks" :depends-on ("basic-operations")) (:file "trees" :depends-on ("basic-operations" "vectors")) (:file "lists" :depends-on ("basic-operations")) (:file "bags-and-sets" :depends-on ("basic-operations")) (:file "ring-buffers" :depends-on ("basic-operations" "queues")) (:file "miscellaneous" :depends-on ("basic-operations")) (:file "associative" :depends-on ("basic-operations")) (:file "compatibility" :depends-on ("basic-operations" "associative")) (:file "vectors" :depends-on ("basic-operations")) (:file "quad-tree" :depends-on ("basic-operations" "trees")) (:file "heaps" :depends-on ("basic-operations")) (:file "container-mixins" :depends-on ("basic-operations")) (:file "union-find-container" :depends-on ("basic-operations")) (:file "package-container" :depends-on ("basic-operations")) (:file "iterator-api") (:file "iterators" :depends-on ("iterator-api" "basic-operations")) (:file "file-iterators" :depends-on ("iterators")) #+(or digitool openmcl) (:file "containers-readtable" :depends-on ("containers")) (:file "dynamic-classes") (:file "dynamic-class-defs" :depends-on ("dynamic-classes" "containers")))) (:module "website" :components ((:module "source" :components ((:static-file "index.md")))))) :in-order-to ((test-op (test-op "cl-containers-test"))) :depends-on ((:version "metatilities-base" "0.6.6"))) #+asdf-system-connections (defsystem-connection "cl-containers/with-moptilities" :requires ("cl-containers" "moptilities") :components ((:module "dev" :components ((:file "containers-moptilities"))))) #+asdf-system-connections (defsystem-connection "cl-containers/with-utilities" :requires ("cl-containers" "metatilities-base") :components ((:module "dev" :components ((:file "utilities-integration"))))) #+asdf-system-connections (defsystem-connection "cl-containers/with-variates" :requires ("cl-containers" "cl-variates") :components ((:module "dev" :components ((:file "container-sampling") (:file "weighted-sampling" :depends-on ("container-sampling")))))) #+(and (not sbcl) asdf-system-connections) (defsystem-connection "cl-containers/with-metacopy" :requires ("cl-containers" "metacopy") :components ((:module "dev" :components ((:file "copying"))))) cl-containers-20170403-git/dev/000077500000000000000000000000001306646076300160675ustar00rootroot00000000000000cl-containers-20170403-git/dev/associative.lisp000066400000000000000000000652141306646076300213020ustar00rootroot00000000000000(in-package #:containers) ;;; Associative-Containers, various flavors (defmethod some-key-value-p ((container associative-container-mixin) (predicate t)) (iterate-key-value container (lambda (k v) (let ((it (funcall predicate k v))) (when it (return-from some-key-value-p it))))) (values nil)) (defmethod every-key-value-p ((container associative-container-mixin) (predicate t)) (iterate-key-value container (lambda (k v) (unless (funcall predicate k v) (return-from every-key-value-p nil)))) (values t)) (defmethod samep ((c1 associative-container-mixin) (c2 associative-container-mixin)) (block test (iterate-key-value c1 (lambda (k v) (unless (eq (item-at c2 k) v) (return-from test nil)))) (iterate-key-value c2 (lambda (k v) (unless (eq (item-at c1 k) v) (return-from test nil)))) (values t))) (defmethod collect-keys ((container associative-container-mixin) &key (filter nil) (transform 'identity)) (collect-key-value container :filter (when filter (lambda (k v) (declare (ignore v)) (funcall filter k))) :transform (lambda (k v) (declare (ignore v)) (funcall transform k)))) (defmethod search-for-key ((container associative-container-mixin) key-to-find &key test key) (iterate-keys container (lambda (k) (when (funcall (or test #'samep) (or (and key (funcall key k)) k) key-to-find) (return-from search-for-key k)))) (values nil)) (defmethod remove-items-if ((container iteratable-container-mixin) test) (iterate-elements container (lambda (element) (when (funcall test element) (delete-item container element)))) (values container)) (defmethod remove-items-if ((container associative-container-mixin) test) (iterate-key-value container (lambda (key value) (when (funcall test value) (delete-item-at container key)))) (values container)) (defmethod count-items ((container iteratable-container-mixin) item &key (key 'identity) (test 'eql)) (let ((result 0)) (iterate-nodes container (lambda (item2) ;; putting item first is consistent with CL test functions (when (funcall test item (funcall key item2)) (incf result)))) (values result))) (defmethod count-elements ((container iteratable-container-mixin) item &key (key 'identity) (test 'eql)) (let ((result 0)) (iterate-elements container (lambda (item2) ;; putting item first is consistent with CL test functions (when (funcall test item (funcall key item2)) (incf result)))) (values result))) (defmethod count-elements ((container list) item &key (key 'identity) (test 'eql)) (let ((result 0)) (mapc (lambda (item2) ;; putting item first is consistent with CL test functions (when (funcall test item (funcall key item2)) (incf result))) container) (values result))) (defmethod count-elements-if ((container iteratable-container-mixin) test &key (key 'identity)) (let ((result 0)) (iterate-elements container (lambda (item) ;; putting item first is consistent with CL test functions (when (funcall test (funcall key item)) (incf result)))) (values result))) (defmethod count-elements-if ((container list) test &key (key 'identity)) (count-if test container :key key)) ;;; array-container ;;; ;;; This is a regular array wrapped by the standard associative container ;;; framework. (defmethod print-container-summary ((container array-container) stream) (format stream "~{~Dx~}" (array-dimensions (contents container)))) (defun make-array-container (dimensions &key element-type initial-element) (make-instance 'array-container :dimensions (ensure-list dimensions) :initial-element initial-element :element-type element-type)) (defmethod make-container-for-contents ((container array-container) &rest args) (let ((dimensions (getf args :dimensions)) (initial-element (getf args :initial-element)) (element-type (getf args :element-type))) (when (initial-element-fn container) (setf initial-element +empty-initial-element+)) (make-array dimensions :initial-element initial-element :element-type (or element-type t) :adjustable t))) (defmethod make-container ((class (eql 'array-container)) &rest args) (let ((dimensions (getf args :dimensions)) (size (getf args :size))) (remf args :dimensions) (remf args :size) (apply #'make-array-container (or dimensions size) args))) (defmethod item-at ((container array-container) &rest indexes) (declare (dynamic-extent indexes)) (let ((result (apply #'aref (contents container) indexes))) (if (and (eq result +empty-initial-element+) (initial-element-fn container)) (setf (apply #'item-at container indexes) (funcall (initial-element-fn container))) result))) (defmethod item-at! ((container array-container) value &rest indexes) (declare (dynamic-extent indexes)) (setf (apply #'aref (contents container) indexes) value)) (defmethod dimensions ((container array-container)) (array-dimensions (contents container))) (defmethod iterate-nodes ((container array-container) fn) (dotimes (i (array-total-size (contents container))) (funcall fn (row-major-aref (contents container) i)))) (defmethod nth-element ((container array-container) (index integer)) (nth-element (contents container) index)) ;;; Sparse-Array-Container ;;; ;;; This uses a hash table and only allocates the memory for ;;; the "cells" of the array that you set. (defmethod initialize-instance :around ((object sparse-array-container) &key dimensions) (setf (slot-value object 'dimensions) (ensure-list dimensions)) (setf (slot-value object 'use-fixnums?) (< (total-size object) most-positive-fixnum)) (call-next-method)) (defmethod make-container-for-contents ((container sparse-array-container) &rest args) (declare (ignore args)) (setf (slot-value container 'test) (if (use-fixnums? container) #'eq #'equal)) (call-next-method)) (defmethod total-size ((container sparse-array-container)) (reduce #'* (dimensions container))) (defun sparse-array-row-major-index (dims subscripts) (declare (dynamic-extent dims subscripts)) (let ((val 0)) (loop for subscript in subscripts for dimension in dims do (setf val (+ (* val dimension) subscript))) val)) (defun sparse-array-value-to-index (dims value) (let ((val value)) (reverse (loop for dimension in (reverse dims) collect (mod val dimension) do (setf val (floor (/ val dimension))))))) #+TESTING (addtest (sparse-array-index-conversion) (loop for x from 1 to 5 do (loop for y from 1 to 10 do (loop for z from 1 to 20 do (ensure (equal (sparse-array-value-to-index '(5 10 20) (sparse-array-row-major-index '(5 10 20) (list x y z))) (list x y z))))))) (defmethod item-at ((container sparse-array-container) &rest indexes) (declare (dynamic-extent indexes)) (multiple-value-bind (value found) (if (use-fixnums? container) (gethash (sparse-array-row-major-index (dimensions container) indexes) (contents container)) (gethash indexes (contents container))) (if found value (maybe-set-initial-element container #'item-at! indexes)))) (defmethod item-at! ((container sparse-array-container) value &rest indexes) ;; (declare (dynamic-extent indexes)) (if (use-fixnums? container) (setf (gethash (sparse-array-row-major-index (dimensions container) indexes) (contents container)) value) (setf (gethash indexes (contents container)) value))) ;;; simple-associative-container ;;; ;;; like a regular hash-table (defmethod item-at-1 ((container simple-associative-container) index) (multiple-value-bind (value found?) (gethash index (contents container)) (if found? (values value t) (maybe-set-initial-element container #'item-at-1! (list index))))) (defmethod item-at-1! ((container simple-associative-container) value index) (setf (gethash index (contents container)) value)) (defmethod (setf item-at-1) (value container index) (item-at-1! container value index)) (defmethod item-at ((container simple-associative-container) &rest indexes) (declare (dynamic-extent indexes)) (assert (length-at-most-p indexes 1)) (item-at-1 container (first indexes))) (defmethod item-at! ((container simple-associative-container) value &rest indexes) (assert (length-at-most-p indexes 1)) (setf (item-at-1 container (first indexes)) value)) (defmethod delete-item-at ((container simple-associative-container) &rest indexes) (declare (dynamic-extent indexes)) (assert (length-at-most-p indexes 1)) (remhash (first indexes) (contents container))) (defmethod iterate-key-value ((container simple-associative-container) function) (maphash function (contents container))) ;;; associative-container ;;; ;;; Nested hash tables (defmethod initialize-instance :after ((object associative-container) &key (test 'eq)) (assert (member (typecase test (function test) (symbol (symbol-function test))) (list #'eq #'eql #'equal)) nil "Test function must be one of #'eq, #'eql or #'equal")) (defmethod item-at ((container associative-container) &rest indexes) (multiple-value-bind (value found?) (descend-ht (contents container) indexes) (if found? (values value t) (maybe-set-initial-element container #'item-at! indexes)))) #+WIP (defmethod item-at ((container associative-container) &rest indexes) (declare (dynamic-extent indexes)) (multiple-value-bind (ht last-index) (find-or-create-ht (contents container) indexes (lambda () (make-container-for-contents container))) (gethash last-index ht))) (defmethod delete-item-at ((container associative-container) &rest indexes) (declare (dynamic-extent indexes)) (multiple-value-bind (ht last-index) (find-or-create-ht (contents container) indexes #'(lambda () (make-container-for-contents container))) (remhash last-index ht)) (values container)) ;; Shouldn't there be simpler version of this for the 'contents-as-hashtable-mixin' class ;; that just calls maphash to map the function over the contents - Westy (defmethod iterate-key-value ((container contents-as-hashtable-mixin) function) (labels ((collect-it (k v fn &optional (collected-keys nil)) (if (typep v 'hash-table) (descend v fn (append collected-keys (list k))) (funcall fn (if collected-keys (append collected-keys (list k)) k) v))) (descend (ht fn &optional (collected-keys nil)) (maphash #'(lambda (k v) (collect-it k v fn collected-keys)) ht))) (descend (contents container) function))) ;;?? this would be weird if you stored HT's in your associative container ;; If we just went by the index-list, then it would be okay, however, ;; you could get into trouble by giving a bogus last argument... (defun descend-ht (ht index-list) (assert (not (null index-list)) nil "Index list must be non-null.") (multiple-value-bind (value found?) (gethash (first index-list) ht) (if found? (if (typep value 'hash-table) (descend-ht value (rest index-list)) (values value t)) (values nil nil)))) (defun find-or-create-ht (ht index-list create-fn) ;(spy ht index-list) (assert (not (null index-list)) nil "Index list must be non-null.") (multiple-value-bind (value found?) (gethash (first index-list) ht) (unless (and found? (typep value 'hash-table)) (setf value (setf (gethash (first index-list) ht) (funcall create-fn)))) (cond ((null (rest index-list)) (values ht (first index-list))) ((length-1-list-p (rest index-list)) (values value (first (rest index-list)))) (t (find-or-create-ht value (rest index-list) create-fn))))) #+Test (let* ((mk-fn (lambda () (make-hash-table))) (ht (funcall mk-fn)) (value 5)) (multiple-value-bind (ht last-index) (find-or-create-ht ht '(:a :b :c) mk-fn) (spy ht last-index) (setf (gethash last-index ht) value)) ht) (defmethod item-at! ((container associative-container) value &rest indexes) (multiple-value-bind (ht last-index) (find-or-create-ht (contents container) indexes #'(lambda () (make-container-for-contents container))) (setf (gethash last-index ht) value))) (defmethod print-container ((container associative-container) &optional (stream *standard-output*)) (iterate-key-value container (lambda (k v) (format stream "~&(~s => ~s)" k v))) (values container)) (defmethod print-container ((container stable-associative-container) &optional (stream *standard-output*)) (iterate-key-value-stably container (lambda (k v) (format stream "~&(~s => ~s)" k v))) (values container)) ;;; Associative-list based container (defmethod initialize-container ((container alist-container)) (setf (slot-value container 'contents) nil)) (defmethod make-container-for-contents ((container alist-container) &rest args) (declare (ignore args)) nil) #+Ignore ;; Clayton Morrison 2005-03-23: bug: alist indexes like '(b a) may ;; make it impossible to find items indexed by '(b)... (defmethod item-at ((container alist-container) &rest indexes) (declare (dynamic-extent indexes)) (let* ((key (if (length-1-list-p indexes) #'car #'identity)) (real-indexes (if (length-1-list-p indexes) (first indexes) indexes)) (it (cdr (assoc real-indexes (contents container) :test (test container) :key key)))) (if it (values it t) (maybe-set-initial-element container #'item-at! indexes)))) ;; only compares first of indexes and alist-key if _both_ are length-1 lists (defmethod item-at ((container alist-container) &rest indexes) (declare (dynamic-extent indexes)) (let* ((it (cdr (assoc indexes (contents container) ;; in an assoc predicate, the first arg is always ;; the key (in this case, indexes) :test (lambda (key1 key2) (if (and (length-1-list-p key1) (length-1-list-p key2)) (funcall (test container) (first key1) (first key2)) (funcall (test container) key1 key2))))))) (if it (values it t) (maybe-set-initial-element container #'item-at! indexes)))) (defmethod item-at-1 ((container alist-container) index) (let* ((it (cdr (assoc index (contents container) :test (lambda (key1 key2) (funcall (test container) key1 key2)))))) (if it (values it t) (maybe-set-initial-element container #'item-at-1! (list index))))) (defmethod item-at-1! ((container alist-container) value index) (let* ((item (assoc index (contents container) :test (test container) :key #'identity))) (if item (setf (cdr item) value) (progn (setf item (cons index value)) (push item (slot-value container 'contents)))) value)) (defun maybe-set-initial-element (container setter-fn indexes) (if (has-initial-element-p container) (let ((ie (make-initial-element container))) (unless (eq ie +empty-initial-element+) (apply setter-fn container ie indexes) (values ie nil))) (values nil nil))) (defmethod item-at! ((container alist-container) value &rest indexes) (let* ((key (if (length-1-list-p indexes) #'car #'identity)) (real-indexes (if (length-1-list-p indexes) (first indexes) indexes)) (item (assoc real-indexes (contents container) :test (test container) :key key))) (if item (setf (cdr item) value) (progn (setf item (cons indexes value)) (push item (slot-value container 'contents)))) value)) (defmethod delete-item-at ((container alist-container) &rest indexes) (declare (dynamic-extent indexes)) (setf (slot-value container 'contents) (delete indexes (slot-value container 'contents) :test (test container) :key #'first)) (values container)) ;;?? Does this make sense (defmethod size ((container alist-container)) (let ((result 0)) (dolist (assoc (contents container)) (when (cdr assoc) (incf result))) result)) (defmethod iterate-nodes ((container alist-container) function) (dolist (assoc (contents container)) (when (cdr assoc) (funcall function (cdr assoc))))) (defmethod iterate-keys ((container alist-container) function) (dolist (assoc (contents container)) (when (cdr assoc) (if (length-1-list-p (first assoc)) (funcall function (caar assoc)) (funcall function (first assoc)))))) (defmethod reverse-find ((container alist-container) value &key (test (test container))) (car (rassoc value (contents container) :test test))) (defmethod empty! ((container alist-container)) (initialize-container container) (values nil)) (defmethod iterate-key-value ((container alist-container) function) (loop for (k . value) in (contents container) when value do (funcall function (if (length-1-list-p k) (first k) k) value))) (defmethod sort-keys ((container alist-container) sorter &key key) (sort-container container sorter (if key (lambda (element) (funcall key (caar element))) #'caar)) (values container)) (defmethod sort-elements ((container alist-container) sorter &key key) (sort-container container sorter (if key (lambda (element) (funcall key (cdr element))) #'cdr)) (values container)) (defmethod sort-container ((container uses-contents-mixin) sorter key-fn) (setf (slot-value container 'contents) (sort (contents container) sorter :key key-fn)) (values container)) ;;; keyed-associative-container ;;; ;;; This container has two types of keys. The 'keyed' in ;;; keyed-associative-container specifies a key function applied to the ;;; key of a key/value pair. This key function provides a way to transform ;;; the key into a thing that can be compared with eq, eql, or equal. In ;;; effect, this lets you have hashtables with arbitrary tests for equality. ;;; If there are multiple indexes, the key is applied to the arguments as a ;;; whole, and is assumed to return multiple-values. That is, the key should ;;; have arity equal to the dimensions of the container, and should return ;;; an equal number of values. ;;; ;;; This functionality is similar to the hashCode() style function required ;;; in java hashtables in that the 'key' function returns a hash, or more ;;; appropriately, something that can be hashed by the built in s ;;; ;;; Importantly, the original key is used for all iterating procedures, so ;;; one can expect key instead of key-function(key). Finally, note that the ;;; key function is applied to each of the index keys seperately, and not ;;; as a whole. (defclass* keyed-associative-container (associative-container keyed-container-mixin) ((key-map :accessor key-map :type associative-container) (in-item-at? nil ir)) (:default-initargs :test #'eq :key #'identity-2)) ;;; initialize-instance :: keyed-associative-container -> nil ;;; We need to initialize the key-map here because we need the test function ;;; given for the underlying hashtable. We could just get it directly from ;;; the keyword :test, but this will suffice (defmethod initialize-instance :after ((container keyed-associative-container) &key) (setf (key-map container) (make-container 'associative-container :test (test container)))) ;;?? Gary King 2003-08-13: kill these someday ;;; singleton-or-list ;;; If the list 'lst' contains only one item, then return it, otherwise ;;; return the original list (defun identity-2 (&rest lst) (if (length-1-list-p lst) (first lst) lst)) ;;; item-key :: keyed-associative-container -> ... -> t (defmethod item-key ((container keyed-associative-container) &rest indexes) (apply (key container) indexes)) (defmethod item-at :around ((container keyed-associative-container) &rest indexes) (declare (dynamic-extent indexes)) (cond ((in-item-at? container) (call-next-method)) (t (unwind-protect (progn (setf (slot-value container 'in-item-at?) t) (multiple-value-call #'call-next-method container (apply #'item-key container indexes))) (setf (slot-value container 'in-item-at?) nil))))) (defmethod delete-item-at :around ((container keyed-associative-container) &rest indexes) (declare (dynamic-extent indexes)) (cond ((in-item-at? container) (call-next-method)) (t (unwind-protect (progn (setf (slot-value container 'in-item-at?) t) (let ((key-list (multiple-value-list (apply #'item-key container indexes)))) (apply #'call-next-method container key-list) (apply #'delete-item-at (key-map container) key-list))) (setf (slot-value container 'in-item-at?) nil)))) container) (defmethod item-at! :around ((container keyed-associative-container) value &rest indexes) (declare (dynamic-extent indexes)) (cond ((in-item-at? container) (call-next-method)) (t (unwind-protect (progn (setf (slot-value container 'in-item-at?) t) (let ((key-list (multiple-value-list (apply #'item-key container indexes)))) (apply #'call-next-method container value key-list) (apply #'item-at! (key-map container) indexes key-list))) (setf (slot-value container 'in-item-at?) nil)))) value) ;;; iterate-key-value :: ;;; keyed-associative-container -> function -> keyed-associative-container ;;; Because we want the original key, and not the key-function key, we must ;;; compute a closure around fn and our key-map ;;?? GWK, I'm not sure I understand this. If multiple keys have the same ;; key-function, then how can we use the original key? #+Ignore (defmethod iterate-key-value :around ((container keyed-associative-container) fn) (call-next-method container #'(lambda (&rest args) (apply fn (append (apply #'item-at (key-map container) (butlast args)) (last args)))))) #+Test (let ((c (make-container 'keyed-associative-container :test #'eq :key #'oddp :initial-element 0))) (dolist (elt '(1 2 3 4 5 6 7 7 8 9 10)) (incf (item-at c elt))) (iterate-key-value c (lambda (k v) (format t "~%~A -> ~A~&" k v)))) (defgeneric key-exists-p (container &rest indexes) (:documentation "")) #+Remove ;; this one fails if :initial-element or :initial-element-fn (defmethod key-exists-p ((container associative-container-mixin) &rest indexes) (declare (dynamic-extent indexes)) (multiple-value-bind (value found?) (apply #'item-at container indexes) (declare (ignore value)) found?)) ;;?? UCK (defmethod key-exists-p ((container associative-container-mixin) &rest indexes) (declare (dynamic-extent indexes)) (let ((old-ie (if (slot-boundp container 'initial-element) (initial-element container) :unbound)) (old-ief (if (slot-boundp container 'initial-element-fn) (initial-element-fn container) :unbound))) (unwind-protect (progn (setf (slot-value container 'initial-element) +empty-initial-element+ (slot-value container 'initial-element-fn) +empty-initial-element+) (multiple-value-bind (value found?) (apply #'item-at container indexes) (declare (ignore value)) found?)) (unless (eq old-ie :unbound) (setf (slot-value container 'initial-element) old-ie)) (unless (eq old-ief :unbound) (setf (slot-value container 'initial-element-fn) old-ief))))) (defmethod iterate-key-value ((container (eql nil)) fn) (declare (ignore fn)) (values container))cl-containers-20170403-git/dev/bags-and-sets.lisp000066400000000000000000000124611306646076300214140ustar00rootroot00000000000000(in-package #:containers) ;;; Bags ;;; ;;; Support: insert-item, delete-item, search-for-item, size, empty-p, empty! ;;; iterate-nodes (defclass* abstract-bag/set-container (uses-contents-mixin findable-container-mixin unordered-container-mixin iteratable-container-mixin initial-contents-mixin) ()) (defmethod make-container-for-contents ((container abstract-bag/set-container) &rest args) (apply #'make-container 'bag/set-container args)) (defclass* bag-container (abstract-bag/set-container concrete-container) ((contents :reader contents))) (defmethod insert-item ((container bag-container) item) (insert-item (contents container) item)) (defmethod size ((container abstract-bag/set-container)) (size (contents container))) (defmethod empty-p ((container abstract-bag/set-container)) (empty-p (contents container))) (defmethod empty! ((container abstract-bag/set-container)) (empty! (contents container)) (values)) (defmethod search-for-item ((container abstract-bag/set-container) item &key (test #'eq) (key #'identity)) (search-for-item (contents container) item :test test :key key)) (defmethod search-for-match ((container abstract-bag/set-container) predicate &key (key 'identity)) (search-for-match (contents container) predicate :key key)) (defmethod delete-item ((container abstract-bag/set-container) item) (when (delete-item (contents container) item) item)) (defmethod find-item ((container abstract-bag/set-container) item) (find-item (contents container) item)) ;;; Sets ;;; Support: insert-item, delete-item, search-for-item, size, empty-p, empty! ;;; iterate-nodes (defclass* set-container (abstract-bag/set-container concrete-container) ((contents :reader contents))) (defmethod insert-item ((container set-container) item) (unless (find-item (contents container) item) (insert-item (contents container) item)) item) ;;; bag/set-container container (defclass* bag/set-container (contents-as-hashtable-mixin unordered-container-mixin concrete-container) ((set-or-bag :set ir))) (defmethod insert-item ((container bag/set-container) item) (multiple-value-bind (value found?) (gethash item (contents container)) (if found? (setf (gethash item (contents container)) (if (eq (set-or-bag container) :set) 1 (incf value))) (setf (gethash item (contents container)) 1))) (values item)) (defmethod delete-item ((container bag/set-container) item) (multiple-value-bind (value found?) (gethash item (contents container)) (when found? (if (= value 1) (remhash item (contents container)) (setf (gethash item (contents container)) (decf value))) item))) (defmethod size ((container bag/set-container)) (let ((result 0)) (maphash (lambda (k v) (declare (ignore k)) (incf result v)) (contents container)) result)) (defmethod search-for-item ((container bag/set-container) item &key (test 'eq) (key 'identity)) (maphash (lambda (k v) (declare (ignore v)) (when (funcall test item (funcall key k)) (return-from search-for-item (values k t)))) (contents container)) (values nil nil)) (defmethod iterate-nodes ((container bag/set-container) fn) (maphash (lambda (k v) (loop repeat v do (funcall fn k))) (contents container))) (defmethod find-item ((container bag/set-container) item) (multiple-value-bind (value found?) (gethash item (contents container)) (declare (ignore value)) (when found? item))) (defmethod find-value ((container bag/set-container) item) (multiple-value-bind (value found?) (gethash item (contents container)) (when found? value))) ;;; keyed-bag/set-container ;;; ;;; when a hash table just won't do (defclass* keyed-bag/set-container (bag/set-container) ((key-map nil r)) (:export-p t)) (defmethod initialize-instance :after ((object keyed-bag/set-container) &key) (setf (slot-value object 'key-map) (make-hash-table :test (test object)))) (defmethod insert-item ((container keyed-bag/set-container) item) (let ((key (funcall (key container) item))) (setf (gethash key (key-map container)) item) (call-next-method container key)) (values item)) (defmethod delete-item ((container keyed-bag/set-container) item) (call-next-method container (funcall (key container) item))) ;; weird, won't necessary find the item we ask for... (defmethod find-item ((container keyed-bag/set-container) item) (let ((key (funcall (key container) item))) (call-next-method container key))) (defmethod iterate-nodes ((container keyed-bag/set-container) fn) (maphash (lambda (k v) (let ((item (gethash k (key-map container)))) (loop repeat v do (funcall fn item)))) (contents container)))cl-containers-20170403-git/dev/basic-operations.lisp000066400000000000000000000751671306646076300222420ustar00rootroot00000000000000 (in-package #:containers) ;;; stuff and nonsense (defgeneric make-container (class &rest args) (:documentation "Creates a new container of type class using the additional arguments (args).") (:method ((class symbol) &rest args) (apply #'make-instance class args))) (defgeneric empty-p (abstract-container) (:documentation "Returns t if there are no items in the container.") (:method ((container t)) (zerop (size container)))) (defmethod iterate-elements ((container abstract-container) fn) (iterate-nodes container fn)) (defmethod iterate-elements ((container container-uses-nodes-mixin) fn) (iterate-nodes container (lambda (x) (funcall fn (element x))))) (defmethod find-element ((container container-uses-nodes-mixin) (thing t)) (let ((node (find-node container thing))) (when node (element node)))) (defmethod delete-item ((container container-uses-nodes-mixin) (item t)) (let ((it (search-for-node container item))) (when it (delete-item container it)))) (defmethod delete-element ((container container-uses-nodes-mixin) (thing t)) (delete-item container thing)) (defmethod print-container ((container iteratable-container-mixin) &optional (stream *standard-output*)) (iterate-elements container #'(lambda (item) (print item stream))) (values container)) (defmethod nth-element :around ((container t) (index integer)) (if (< -1 index (size container)) (call-next-method) (error 'index-out-of-range-error :container container :index index))) (defmethod nth-element ((container iteratable-container-mixin) (index integer)) ;; possibly slow but servicable method (iterate-elements container (lambda (elt) (when (minusp (decf index)) (return-from nth-element elt)))) (error "Index ~D out of range for container ~A" index container)) (defmethod collect-nodes ((container iteratable-container-mixin) &key filter transform) (collector-internal container #'iterate-nodes filter transform)) (defmethod collect-elements ((container iteratable-container-mixin) &key filter transform) (collector-internal container #'iterate-elements filter transform)) (defun collector-internal (container iterate-fn filter-fn transform-fn) (let ((result nil)) (funcall iterate-fn container (lambda (item) (when (or (not filter-fn) (and filter-fn (funcall filter-fn item))) (push (if transform-fn (funcall transform-fn item) item) result)))) (nreverse result))) (defmethod search-for-item ((container iteratable-container-mixin) item &key (test (test container)) (key 'identity)) (%search-in-container container 'iterate-elements item test key)) (defmethod search-for-element ((container iteratable-container-mixin) item &key (test (test container)) (key 'identity)) (%search-in-container container 'iterate-elements item test key)) (defmethod search-for-node ((container iteratable-container-mixin) item &key (test (test container)) (key 'identity)) (%search-in-container container 'iterate-nodes item test key)) (defun %search-in-container (container iterator item test key) (funcall iterator container (lambda (x) (when (funcall test item (funcall key x)) (return-from %search-in-container (values x t))))) (values nil nil)) (defmethod search-for-match ((container iteratable-container-mixin) predicate &key (key 'identity)) (%search-for-match container predicate key)) (defun %search-for-match (container predicate key) (iterate-elements container (lambda (element) (when (funcall predicate (funcall key element)) (return-from %search-for-match element)))) nil) (defmethod search-for-matching-node ((container iteratable-container-mixin) predicate &key (key 'identity)) (iterate-nodes container (lambda (element) (when (funcall predicate (funcall key element)) (return-from search-for-matching-node element)))) nil) (defmethod search-for-node ((container container-uses-nodes-mixin) (item t) &key (test (test container)) (key 'identity)) (iterate-nodes container (lambda (node) (when (funcall test item (funcall key (element node))) (return-from search-for-node (values node t)))))) (defmethod search-for-node ((container container-uses-nodes-mixin) (item container-node-mixin) &key (test (test container)) (key 'identity)) (iterate-nodes container (lambda (node) (when (funcall test item (funcall key node)) (return-from search-for-node (values node t))))) (values nil nil)) (defmethod search-for-node* ((container container-uses-nodes-mixin) (item t) &key (test (test container)) (key 'identity)) (search-for-node container (make-node-for-container container item) :test test :key key)) (defmethod search-for-node* ((container container-uses-nodes-mixin) (item container-node-mixin) &key (test (test container)) (key 'identity)) (iterate-nodes container (lambda (element) (when (funcall test (funcall key item) (funcall key element)) (return-from search-for-node* (values element t))))) (values nil nil)) ;;; best-item and its friends, argmax and argmin (defmethod best-item ((container iteratable-container-mixin) function &key (key 'identity) (test '>) (filter nil)) (%best-helper container #'iterate-elements function key test filter)) (defmethod best-item ((items list) function &key (key 'identity) (test '>) (filter 'identity)) (%best-helper items #'iterate-elements function key test filter)) (defmethod best-node (container function &key (key 'identity) (test '>) (filter nil)) (%best-helper container #'iterate-nodes function key test filter)) (defmethod best-element (container function &key (key 'identity) (test '>) (filter nil)) (%best-helper container #'iterate-elements function key test filter)) (defun %best-helper (container iterator function key test filter) (if (empty-p container) (values nil nil nil) (let ((max-value nil) (result nil) (result-found? nil)) (funcall iterator container (lambda (item) (when (or (not filter) (funcall filter item)) (let ((test-value (funcall function (funcall key item)))) (when (or (not result-found?) (funcall test test-value max-value)) (setf max-value test-value result item result-found? t)))))) (values result max-value t)))) (defmethod argmax ((items t) function &rest args &key key filter) (declare (ignore key filter)) (apply #'best-item items function :test #'> args)) (defmethod argmin ((items t) function &rest args &key key filter) (declare (ignore key filter)) (apply #'best-item items function :test #'< args)) #+test (progn (argmax '(0 1 -2 3 -4) #'square) (best-item '(0 1 -4 2 -3) #'square :test #'<) (best-item '(0 1 -4 2 -3) #'square) (best-item '(0 1 -4 2 -3 1 3 -1 -4 1 2 -4 -1 -2 10) #'square) (best-item '(0 1 -4 2 -3 1 3 -1 -4 1 2 -4 -1 -2 10) #'square) ;;; --------------------------------------------------------------------------- (argmax (make-container 'list-container :initial-contents '(0 1 -2 3 -4)) (lambda (x) (* x x)) :filter #'oddp) (argmax (make-container 'list-container :initial-contents '(0 1 -2 3 -4)) (lambda (x) (* x x)) :filter #'evenp) (argmin (make-container 'list-container :initial-contents '(1 0 -2 3 -4)) (lambda (x) (* x x)))) (defmethod reduce-container ((container iteratable-container-mixin) function &rest args &key (key 'identity) (initial-value nil initial-value-supplied-p) (start 0) end) (declare (dynamic-extent args) (ignore key initial-value initial-value-supplied-p start end)) (apply #'reduce-elements container function args)) (defmethod reduce-elements ((container iteratable-container-mixin) function &key (key 'identity) (initial-value nil initial-value-supplied-p) (start 0) end) (reduce-internal container #'iterate-elements function key initial-value initial-value-supplied-p start end)) (defmethod reduce-nodes ((container iteratable-container-mixin) function &key (key 'identity) (initial-value nil initial-value-supplied-p) (start 0) end) (reduce-internal container #'iterate-nodes function key initial-value initial-value-supplied-p start end)) #+NotYet (defmethod reduce-key-value ((container iteratable-container-mixin) function &key (key 'identity) (initial-value nil initial-value-supplied-p)) (reduce-internal container #'iterate-nodes function key initial-value initial-value-supplied-p start end)) (defun reduce-internal (container iterator function key initial-value supplied-p start end) (cond ((empty-p container) (if supplied-p (funcall function initial-value) (funcall function))) (t (let ((accumulator (when supplied-p (funcall key initial-value))) (first-time t) (count 0)) (funcall iterator container (lambda (elt) (when (and (>= count start) (or (not end) (< count end))) (let ((elt* (funcall key elt))) (cond (first-time (setf first-time nil) (if supplied-p (setf accumulator (funcall function accumulator elt*)) (setf accumulator elt*))) (t (setf accumulator (funcall function accumulator elt*)))))))) (values accumulator))))) #+test (progn (reduce-container (make-container 'list-container :initial-contents '(0 1 -2 3 -4)) '+) (reduce-container (make-container 'list-container :initial-contents '(5 0 1 -2 3 -4)) 'max) (reduce-container (make-container 'list-container :initial-contents '(5 0 1 -2 3 -4)) 'max :initial-value 7 :key '1+)) (defmethod delete-item-if ((container iteratable-container-mixin) test) (iterate-elements container (lambda (item) (when (funcall test item) (delete-item container item)))) (values container)) (defmethod first-element ((container iteratable-container-mixin)) (iterate-nodes container (lambda (item) (return-from first-element item)))) (defmethod (setf first-element) (value (container iteratable-container-mixin)) (declare (ignore value)) (error "Don't know how to set the first element of ~A" container)) (defmethod delete-item :after ((container container-uses-nodes-mixin) (item i-know-my-node-mixin)) (setf (my-node item) nil)) ;;; Default (and not necessary efficient generic implementations) (defmethod delete-list ((container non-associative-container-mixin) list) (dolist (item list) (delete-item container item)) container) (defmethod insert-list ((container non-associative-container-mixin) list) (dolist (item list) (insert-item container item)) container) ;;?? :start :end :test? (defmethod insert-sequence ((container ordered-container-mixin) (sequence array)) (loop for item across sequence do (insert-item container item)) container) (defmethod insert-sequence ((container ordered-container-mixin) (sequence list)) (loop for item in sequence do (insert-item container item)) container) (defmethod insert-sequence ((container ordered-container-mixin) (sequence iteratable-container-mixin)) (iterate-elements sequence (lambda (element) (insert-item container element))) container) (defmethod insert-new-item ((container searchable-container-mixin) item &key (test (test container)) (key (key container))) (unless (search-for-item container (funcall key item) :test test :key key) (insert-item container item)) (values container)) (defmethod successor ((container container-uses-nodes-mixin) (item t)) (%operate-after-finding container item #'successor)) (defmethod predecessor ((container container-uses-nodes-mixin) (item t)) (%operate-after-finding container item #'predecessor)) (defmethod %operate-after-finding ((container container-uses-nodes-mixin) (element t) operation) (let ((element (search-for-node container element :key #'element))) (unless element (error 'element-not-found-error :container container :element element)) (funcall operation container element))) ;;; contents-as-sequence-mixin (defmethod size ((container contents-as-sequence-mixin)) (length (contents container))) (defmethod empty-p ((container contents-as-sequence-mixin)) (= (size container) 0)) (defmethod sort-elements ((container contents-as-sequence-mixin) sorter &key (key 'identity)) (setf (slot-value container 'contents) (sort (contents container) sorter :key key))) ;;; contents-as-array-mixin (defmethod empty! ((container contents-as-array-mixin)) (setf (contents container) (adjust-array (contents container) 0 :fill-pointer (array-has-fill-pointer-p (contents container)) :element-type (array-element-type (contents container))))) (defmethod search-for-item ((container contents-as-array-mixin) item &key (test (test container)) (key 'identity)) (loop for container-item across (contents container) do (when (funcall test (funcall key container-item) item) (return-from search-for-item container-item)))) (defmethod iterate-nodes ((container contents-as-array-mixin) function) (let ((array (contents container)) (index 0)) (loop while (< index (length array)) do (let ((current-size (length array))) ;?? non-optimal for vectors (funcall function (aref array index)) (when (= current-size (length array)) (incf index))))) container) (defmethod find-item ((container contents-as-array-mixin) item) (find item (contents container))) (defmethod some-item-p ((container iteratable-container-mixin) (predicate function)) (%some-thing-p container #'iterate-nodes predicate)) (defmethod every-item-p ((container iteratable-container-mixin) (predicate function)) (%every-thing-p container #'iterate-nodes predicate)) (defmethod some-element-p ((container iteratable-container-mixin) (predicate function)) (%some-thing-p container #'iterate-elements predicate)) (defmethod every-element-p ((container iteratable-container-mixin) (predicate function)) (%every-thing-p container #'iterate-elements predicate)) (defun %every-thing-p (container iterator predicate) (funcall iterator container (lambda (item) (unless (funcall predicate item) (return-from %every-thing-p nil)))) (values t)) (defun %some-thing-p (container iterator predicate) (funcall iterator container (lambda (item) (when (funcall predicate item) (return-from %some-thing-p item)))) (values nil)) ;;; contents-as-list-mixin (defmethod insert-item ((container contents-as-list-mixin) item) (push item (slot-value container 'contents)) (values item)) (defmethod append-item ((container contents-as-list-mixin) item) (setf (contents container) (nreverse (contents container))) (push item (contents container)) (setf (contents container) (nreverse (contents container)))) (defmethod append-new-item ((container contents-as-list-mixin) item &key (test 'eq) (key 'identity)) (unless (member item (contents container) :test test :key key) (append-item container item))) (defmethod empty-p ((container contents-as-list-mixin)) (null (contents container))) (defmethod empty! ((container contents-as-list-mixin)) (setf (slot-value container 'contents) nil) (values)) (defmethod search-for-item ((container contents-as-list-mixin) item &key (test (test container)) (key 'identity)) (find item (contents container) :test test :key key)) ;;; contents-as-hashtable-mixin #+Remove ;; Gary King 2006-05-14: redundent with the definition for uses-contents-mixin (defmethod initialize-instance :after ((container contents-as-hashtable-mixin) &key &allow-other-keys) (when (or (not (slot-boundp container 'contents)) (null (contents container))) (setf (contents container) (make-container-for-contents container)))) (defmethod make-container-for-contents ((container contents-as-hashtable-mixin) &rest args) (declare (ignore args)) (make-hash-table :test (test container))) (defmethod size ((container contents-as-hashtable-mixin)) (hash-table-count (contents container))) (defmethod empty! ((container contents-as-hashtable-mixin)) (clrhash (contents container)) (values)) ;;?? same as method for bag/set-container (defmethod search-for-item ((container contents-as-hashtable-mixin) item &key (test (test container)) (key 'identity)) (maphash (lambda (k v) (declare (ignore v)) (when (funcall test item (funcall key k)) (return-from search-for-item (values k t)))) (contents container))) (defmethod iterate-nodes ((container contents-as-hashtable-mixin) fn) (iterate-key-value container (lambda (k v) (declare (ignore k)) (funcall fn v)))) (defmethod iterate-keys ((container contents-as-hashtable-mixin) function) (maphash (lambda (k v) (declare (ignore v)) (funcall function k)) (contents container))) (defmethod collect-key-value ((container key-value-iteratable-container-mixin) &rest args &key filter transform) (declare (dynamic-extent args) (ignore filter transform)) (apply #'%collect-key-value container args)) (defun %collect-key-value (container &key filter transform) (let ((result nil)) (iterate-key-value container (lambda (k v) (when (or (not filter) (funcall filter k v)) (push (if transform (funcall transform k v) (cons k v)) result)))) (nreverse result))) (defmethod find-item ((container contents-as-hashtable-mixin) item) (values (gethash item (contents container)))) ;; slow, but works (defmethod reverse-find ((container contents-as-hashtable-mixin) value &key (test (test container))) (iterate-key-value container (lambda (k v) (when (funcall test value v) (return-from reverse-find k)))) nil) (defmethod find-value ((container contents-as-hashtable-mixin) item) (multiple-value-bind (value found?) (gethash item (contents container)) (when found? value))) ;;; stable-associative-container (defmethod item-at! ((object stable-associative-container) value &rest indexes) (multiple-value-bind (o found?) (apply #'item-at (slot-value object 'associative-container) indexes) (declare (ignore o)) (unless found? (setf (item-at (slot-value object 'numbered-container) (incf (slot-value object 'counter))) (if (length-1-list-p indexes) (first indexes) indexes))) (setf (apply #'item-at (slot-value object 'associative-container) indexes) value))) (defmethod add-default-item ((object stable-associative-container) &rest indexes) (when (has-initial-element-p (slot-value object 'associative-container)) (setf (item-at (slot-value object 'numbered-container) (incf (slot-value object 'counter))) (if (length-1-list-p indexes) (first indexes) indexes)))) (defmethod item-at ((object stable-associative-container) &rest indexes) (declare (dynamic-extent indexes)) (multiple-value-bind (o found?) (apply #'item-at (slot-value object 'associative-container) indexes) (unless found? (apply #'add-default-item object indexes)) o)) (defmethod size ((container stable-associative-container)) (size (slot-value container 'numbered-container))) (defmethod iterate-keys ((container stable-associative-container) fn) (iterate-keys (slot-value container 'associative-container) fn)) (defmethod iterate-nodes ((container stable-associative-container) fn) (iterate-nodes (slot-value container 'associative-container) fn)) (defmethod iterate-elements-stably ((container stable-associative-container) fn) (iterate-key-value-stably container (lambda (k v) (declare (ignore k)) (funcall fn v)))) (defmethod iterate-key-value ((container stable-associative-container) fn) (iterate-key-value (slot-value container 'associative-container) fn)) (defmethod collect-keys ((container stable-associative-container) &rest args &key filter transform) (declare (ignore filter transform) (dynamic-extent args)) (apply #'collect-keys (slot-value container 'associative-container) args)) (defmethod iterate-key-value-stably ((container stable-associative-container) fn) (loop for i from 1 to (size (slot-value container 'numbered-container)) for key = (item-at (slot-value container 'numbered-container) i) do (funcall fn key (apply #'item-at (slot-value container 'associative-container) (ensure-list key))))) (defmethod collect-key-value-stably ((container stable-associative-container)) (let ((result nil)) (iterate-key-value-stably container (lambda (k v) (push (cons k v) result))) (nreverse result))) (defmethod collect-elements-stably ((container iteratable-container-mixin) &key filter transform) (collector-internal container #'iterate-elements-stably filter transform)) (defmethod empty! ((container stable-associative-container)) (setf (slot-value container 'counter) 0) (empty! (slot-value container 'associative-container)) (empty! (slot-value container 'numbered-container))) ;;; associative-array (defmethod item-at! ((container associative-array) value &rest indexes) (setf (apply #'item-at (array-data container) (loop for index in indexes for i = 0 then (1+ i) collect (tuple-index container i index))) value)) (defun tuple-index (container dim index) (with-slots (dim-container num-container) container (multiple-value-bind (result found?) (item-at (item-at dim-container dim) index) (unless found? (setf (item-at (item-at dim-container dim) index) (setf result (incf (item-at num-container dim))))) result))) (defmethod item-at ((container associative-array) &rest indexes) (declare (dynamic-extent indexes)) (with-slots (dim-container) container (apply #'item-at (array-data container) (loop for index in indexes for dim = 0 then (1+ dim) collect (item-at (item-at dim-container dim) index))))) (defmethod iterate-nodes ((container associative-array) fn) (with-slots (row-container col-container) container (loop for i from 0 to (1- (size row-container)) do (loop for j from 0 to (1- (size col-container)) do (funcall fn (item-at (array-data container) i j)))))) (defmethod container-dimension ((container associative-array) dimension) (with-slots (dim-container) container (size (item-at dim-container dimension)))) (defmethod dimensions ((container associative-array)) (with-slots (dimensions dim-container) container (loop for dim from 0 to (1- dimensions) collect (size (item-at dim-container dim))))) #+Example (let ((c (make-container 'associative-array :test #'equal :dimensions 2))) (loop for row in (list "one" "two" "three") for row-num = 1 then (1+ row-num) do (loop for col in (list "A" "B" "C") for col-num = 1 then (1+ col-num) do (setf (item-at c row col) (* row-num col-num)))) (print (item-at c "two" "B")) c) ;;; some high level helpers (defmethod find-item ((container container-uses-nodes-mixin) (item t)) (find-item container (make-node-for-container container item))) (defmethod insert-item ((container container-uses-nodes-mixin) (item t)) (let ((node (make-node-for-container container item))) (values (insert-item container node) node))) ;;; Odd (in a non-prejoritive sense) methods ;;?? Gary King 2003-04-06: cute but probably not cuddly (defun collect-using (map-fn filter &rest args) "Collects stuff by applying the map-fn to the arguments. Assumes that the map-fn signature has the function to be applied as its last argument." (declare (dynamic-extent filter args)) (let ((result nil)) (apply map-fn (append args (list (lambda (thing &optional value) ;;?? Gary King 2003-11-14: value is here to handle ;; associative containers. But it's not used so this is ;; really a bit ugly (declare (ignorable value)) (when (or (not filter) (funcall filter thing)) (push thing result)))))) (nreverse result))) (defun count-using (map-fn filter &rest args) "Counts stuff by applying the map-fn to the arguments. Assumes that the map-fn signature has the function to be applied as its last argument." (let ((result 0)) (apply map-fn (append args (list (lambda (thing) (when (or (not filter) (funcall filter thing)) (incf result)))))) (values result))) (defmethod container-difference (c1 c2 &key (key1 'identity) (key2 'identity)) ;; things in 1 not in 2 (collect-elements c1 :filter (lambda (e) (let ((real-e (funcall key1 e))) (not (search-for-item c2 real-e :key key2)))))) (defun associative-container-p (container) "Returns true if the container is associative. Tries to work for native Lisp containers too." (typecase container (hash-table (values t t)) (associative-container (values t t)) (abstract-container (values nil t)) (t (values nil nil)))) (defmethod add-initial-contents ((object initial-contents-mixin) (initial-contents list)) (add-initial-contents-internal object initial-contents)) (defmethod add-initial-contents ((object initial-contents-mixin) (initial-contents iteratable-container-mixin)) (add-initial-contents-internal object initial-contents)) (defun add-initial-contents-internal (object initial-contents) ;; not necessarily the fastest, but should work as a good default (iterate-elements initial-contents (lambda (element) (insert-item object element)))) (defmethod add-initial-contents ((object initial-contents-key-value-mixin) initial-contents) ;; not necessarily the fastest, but should work as a good default (loop for contents = initial-contents then (rest contents) while contents do (setf (item-at object (first contents)) (second contents)) (setf contents (rest contents)))) (defmethod element-position ((container iteratable-container-mixin) element &key (test 'eq) (key 'identity)) (let ((position 0)) (iterate-elements container (lambda (e) (when (funcall test (funcall key e) element) (return-from element-position position)) (incf position))) (values nil))) (defmethod element-position ((container contents-as-sequence-mixin) element &key (test 'eq) (key 'identity)) (position element (contents container) :test test :key key)) (defmethod samep ((l1 list-container) (l2 list-container)) (set-equal (contents l1) (contents l2))) (defmethod samep ((l1 list) (l2 list-container)) (set-equal l1 (contents l2))) (defmethod samep ((l1 list-container) (l2 list)) (set-equal (contents l1) l2)) (defmethod samep ((l1 list) (l2 list)) (set-equal l1 l2)) (defmethod reverse-container ((container ordered-container-mixin)) ;; expensive generic method (let ((reversed (nreverse (collect-elements container)))) (empty! container) (iterate-elements reversed (lambda (e) (insert-item container e))) container)) ;;; *************************************************************************** ;;; * End of File * ;;; ***************************************************************************cl-containers-20170403-git/dev/compatibility.lisp000066400000000000000000000311551306646076300216360ustar00rootroot00000000000000(in-package #:containers) ;;; just regular lists (defmethod iteratable-p ((thing list)) (values t)) ;; need both b/c list-container cannot use abstract-containers (defmethod iterate-elements ((list null) fn) (declare (ignore fn))) (defmethod iterate-nodes ((list null) fn) (declare (ignore fn))) ;; need both b/c list-container cannot use abstract-containers (defmethod iterate-elements ((list list) fn) (mapc fn list)) (defmethod iterate-nodes ((list list) fn) (mapc fn list)) (defmethod collect-elements ((list list) &key filter transform) (cond ((and filter transform) (let ((result nil)) (mapc (lambda (item) (when (funcall filter item) (push (funcall transform item) result))) list) (nreverse result))) ((not (null filter)) (let ((result nil)) (mapc (lambda (item) (when (funcall filter item) (push item result))) list) (nreverse result))) ((not (null transform)) (let ((result nil)) (mapc (lambda (item) (push (funcall transform item) result)) list) (nreverse result))) (t (values list)))) (defmethod element-position ((list list) element &key (key 'identity) (test 'eq)) (position element list :key key :test test)) (defmethod empty-p ((list list)) (null list)) (defmethod first-element ((list list)) (first list)) (defmethod (setf first-element) (value (list list)) (setf (first list) value)) (defmethod last-element ((list list)) (first (last list))) (defmethod (setf last-element) (value (list list)) (setf (first (last list)) value)) (defmethod nth-element ((list list) (n integer)) (nth n list)) (defmethod search-for-match ((list list) predicate &key (key 'identity)) (%search-for-match list predicate key)) (defmethod size ((list list)) (length list)) (defmethod find-item ((list list) item) (find item list)) (defmethod search-for-item ((list list) item &key test key) (find item list :test test :key key)) (defmethod search-for-element ((list list) item &key (test nil) (key 'identity)) (find item list :test test :key key)) (defmethod reduce-elements ((container list) function &key (key 'identity) (initial-value nil initial-value-supplied-p) (start 0) end) (reduce-internal container #'iterate-elements function key initial-value initial-value-supplied-p start end)) (defmethod some-item-p ((container list) (predicate function)) (%some-thing-p container #'iterate-elements predicate)) (defmethod some-element-p ((container list) predicate) (%some-thing-p container #'iterate-elements predicate)) (defmethod every-item-p ((container list) (predicate function)) (%every-thing-p container #'iterate-elements predicate)) (defmethod every-element-p ((container list) predicate) (%every-thing-p container #'iterate-elements predicate)) ;;; vectors (defmethod iterate-elements ((vector vector) fn) (iterate-nodes vector fn)) (defmethod iterate-nodes ((vector vector) fn) (loop for i across vector doing (funcall fn i))) (defmethod iteratable-p ((thing vector)) (values t)) (defmethod collect-elements ((vector vector) &key filter transform) (loop for element across vector when (or (not filter) (funcall filter element)) collect (if (not transform) element (funcall transform element)))) (defmethod size ((vector vector)) ;; nb. Since we allow fill pointers now length and array-total-size ;; may be different. The implementation of empty-p and last-element ;; suggest that size should be length. (length vector)) (defmethod empty-p ((vector vector)) (zerop (size vector))) (defmethod first-element ((vector vector)) (aref vector 0)) (defmethod (setf first-element) (value (vector vector)) (setf (aref vector 0) value)) (defmethod last-element ((vector vector)) (aref vector (1- (size vector)))) (defmethod (setf last-element) (value (vector vector)) (setf (aref vector (1- (size vector))) value)) (defmethod search-for-match ((vector vector) predicate &key (key 'identity)) (%search-for-match vector predicate key)) (defmethod some-item-p ((container vector) (predicate function)) (%some-thing-p container #'iterate-elements predicate)) (defmethod some-element-p ((container vector) predicate) (%some-thing-p container #'iterate-elements predicate)) (defmethod every-item-p ((container vector) (predicate function)) (%every-thing-p container #'iterate-elements predicate)) (defmethod every-element-p ((container vector) predicate) (%every-thing-p container #'iterate-elements predicate)) (defmethod sort-elements ((container sequence) sorter &key (key 'identity)) (sort (copy-seq container) sorter :key key)) (defmethod nth-element ((container vector) (index number)) (aref container index)) ;;; arrays (defmethod iterate-elements ((array array) fn) (maparray array fn)) (defmethod iterate-nodes ((array array) fn) (iterate-elements array fn)) (defmethod iteratable-p ((thing array)) (values t)) (defmethod collect-elements ((array array) &key filter transform) (let ((result nil)) (iterate-elements array (lambda (element) (when (or (not filter) (funcall filter element)) (push (if (not transform) element (funcall transform element)) result)))) (nreverse result))) (defmethod size ((array array)) ;; nb. Since we allow fill pointers now length and array-total-size ;; may be different. The implementation of empty-p and last-element ;; suggest that size should be length. (length array)) (defmethod first-element ((array array)) (row-major-aref array 0)) (defmethod (setf first-element) (value (array array)) (setf (row-major-aref array 0) value)) (defmethod last-element ((array array)) (row-major-aref array (size array))) (defmethod (setf last-element) (value (array array)) (setf (row-major-aref array (size array)) value)) (defmethod search-for-match ((array array) predicate &key (key 'identity)) (%search-for-match array predicate key)) (defmethod some-element-p ((array array) predicate) (%some-thing-p array #'iterate-elements predicate)) (defmethod every-element-p ((array array) predicate) (%every-thing-p array #'iterate-elements predicate)) #+NotYet (defmethod sort-elements ((container sequence) sorter &key (key 'identity)) (sort (copy-seq container) sorter :key key)) (defmethod nth-element ((container array) (index number)) (row-major-aref container index)) (defmethod item-at ((array array) &rest indexes) (declare (dynamic-extent indexes)) (apply #'aref array indexes)) (defmethod item-at! ((array array) value &rest indexes) (declare (dynamic-extent indexes)) (setf (apply #'aref array indexes) value)) ;;; hash tables (defmethod iteratable-p ((thing hash-table)) (values t)) ;; need both b/c hash-tables cannot use abstract-containers (defmethod iterate-elements ((hash-table hash-table) fn) (maphash (lambda (k v) (declare (ignore k)) (funcall fn v)) hash-table)) (defmethod iterate-nodes ((hash-table hash-table) fn) (iterate-elements hash-table fn)) (defmethod collect-elements ((hash-table hash-table) &key filter transform) (let* ((result nil) (fn (cond ((and filter transform) (lambda (key item) (declare (ignore key)) (when (or (not filter) (and filter (funcall filter item))) (push (if transform (funcall transform item) item) result)))) ((not (null filter)) (lambda (key item) (declare (ignore key)) (when (funcall filter item) (push item result)))) ((not (null transform)) (lambda (key item) (declare (ignore key)) (push (funcall transform item) result))) (t (lambda (key item) (declare (ignore key)) (push item result)))))) (maphash fn hash-table) (nreverse result))) (defmethod collect-keys ((hash-table hash-table) &key filter (transform 'identity)) (let ((result nil)) (maphash (lambda (k v) (declare (ignore v)) (when (or (not filter) (funcall filter k)) (push (funcall transform k) result))) hash-table) result)) #+Hmmm (defmethod collect-keys ((hash-table hash-table) &key filter transform) (%hash-table-collector (lambda (k v) (declare (ignore v)) k) (when filter (lambda (k v) (declare (ignore v)) (funcall filter k))) (when transform (lambda (k v) (declare (ignore v)) (funcall transform k))))) #+Hmmm (defun %hash-table-collector (hash-table function filter transform) (let* ((result nil) (fn (cond ((and filter transform) (lambda (key item) (when (or (not filter) (and filter (funcall filter key item))) (push (if transform (funcall transform key item) item) result)))) ((not (null filter)) (lambda (key item) (when (funcall filter key item) (push item result)))) ((not (null transform)) (lambda (key item) (push (funcall transform key item) result))) (t (lambda (key item) (push item result)))))) (maphash fn hash-table) (nreverse result))) (defmethod iterate-key-value ((hash-table hash-table) fn) (maphash fn hash-table)) (defmethod empty! ((hash-table hash-table)) (clrhash hash-table) (values)) (defmethod empty-p ((hash-table hash-table)) (= (size hash-table) 0)) (defmethod size ((hash-table hash-table)) (hash-table-count hash-table)) (defmethod item-at ((hash-table hash-table) &rest indexes) (gethash indexes hash-table)) (defmethod item-at! ((value t) (hash-table hash-table) &rest indexes) (setf (gethash indexes hash-table) value)) (defmethod item-at-1 ((hash-table hash-table) index) (multiple-value-bind (value found?) (gethash index hash-table) (if found? (values value t) (values nil nil)))) (defmethod item-at-1! ((hash-table hash-table) (value t) index) (setf (gethash index hash-table) value)) (defmethod print-container ((hash-table hash-table) &optional (stream *standard-output*)) (iterate-key-value hash-table (lambda (k v) (format stream "~&(~s => ~s)" k v)))) ;;; alist (defmethod item-at ((container list) &rest indexes) (cdr (assoc (first indexes) container))) (defmethod item-at-1 ((container list) index) (cdr (assoc index container))) (defmethod iterate-key-value ((container list) function) (loop for (k . value) in container when value do (funcall function k value)) #+No (loop for keys = container then (rest keys) for values = (rest keys) then (rest keys) while keys do (funcall function (first keys) (first values)) (setf keys (rest keys)))) (defmethod collect-key-value ((container list) &rest args &key filter transform) (declare (dynamic-extent args) (ignore filter transform)) (apply #'%collect-key-value container args)) (defmethod collect-keys ((container list) &key filter (transform 'identity)) "If the list begins with an atom, then it is treated as a property list; otherwise, it is treated as an associative-list." (if (atom (car container)) ;; treat as property list (loop for current in container by #'cddr when (or (not filter) (funcall filter current)) collect (if transform (funcall transform current) current)) ;; treat as alist (%collect-key-value container :filter filter :transform (lambda (k v) (declare (ignore v)) (funcall transform k))))) (defmethod delete-item-at ((container list) &rest indexes) (when (assoc (first indexes) container) (setf (cdr (assoc (first indexes) container)) nil))) cl-containers-20170403-git/dev/conditions.lisp000066400000000000000000000024231306646076300211320ustar00rootroot00000000000000(in-package #:cl-containers) (defcondition container-condition () ((container :initarg :container :reader container))) (defcondition container-error (container-condition error) () (:export-p t) (:export-slots-p t)) (defcondition index-out-of-range-error (container-error) ((index 0 ir)) (:report (lambda (c s) (if (< (index c) 0) (format s "Index ~D is negative, it must be between 0 and the size of the container." (index c)) (format s "Index ~D out of range for container ~A, size is only ~D." (index c) (class-name (class-of (container c))) (size (container c))))))) (define-condition key-does-not-exist-error (container-error) ()) (define-condition queue-empty (container-error) ((message :initarg :message :reader message)) (:report (lambda (c stream) (format stream "~A" (message c))))) (define-condition record-not-found-error (container-error) ((table :initarg :table :accessor table) (value :initarg :value :accessor value))) (defcondition element-not-found-error (container-error) ((element :initarg :element :reader element)) (:export-p t) (:export-slots-p element)) cl-containers-20170403-git/dev/container-api.lisp000066400000000000000000000455121306646076300215200ustar00rootroot00000000000000 (in-package #:containers) (defgeneric sample-elements (container generator count) (:documentation "Return a list of count elements of the container uniformly at random using the generator. The sampling is done _with_ replacement.")) (defgeneric sample-key (associative-container generator) (:documentation "Return an element from of the keys of the associative container uniformly at random using the generator.")) (defgeneric sample-unique-elements (container generator count) (:documentation "Return a list of count elements from the container sampled uniformly at random without replacement.")) (defgeneric sample-element (container generator) (:documentation "Return an element of the container uniformly at random using the generator.")) (defgeneric sample-item (container generator) (:documentation "Return an item of the container uniformly at random using the generator. Same as sample-element unless container is of type container-uses-nodes-mixin.")) (defgeneric best-item (items function &key key test filter) (:documentation "Returns the item in items with the 'best' value of function where 'best' is determined by test. You can use filter to limit which items are compared and key to select out what part of each item actually gets tested. See argmin and argmax for specializations.")) (defgeneric argmax (items function &key key filter) (:documentation "Returns the item in items with the biggest (#'>) value of function. See best-item for a generalization. See best-item for a generalization.")) (defgeneric argmin (items function &key key filter) (:documentation "Returns the item in items with the smallest (#'<) value of function.")) (defgeneric size (abstract-container) (:documentation "Returns the number of items currently in the container.")) (defgeneric empty! (abstract-container) (:documentation "Removes all items from the container and returns nil.")) (defgeneric some-item-p (container predicate) (:documentation "Returns the first item in the container for which predicate holds. Predicate should be a function of one argument for iteratable containers and a function of two arguments for associative containers.")) (defgeneric every-item-p (container predicate) (:documentation "Returns true if every item in the container satisfies the predicate. Predicate should be a function of one argument for iteratable containers and a function of two arguments for associative containers.")) (defgeneric make-container-for-contents (container &rest args) (:documentation "Creates a sub-container to be used as contents for a super-container.")) (defgeneric nth-element (container index) (:documentation "Returns the nth element in the container's 'natural' order.")) (defgeneric nth-item (container index) (:documentation "Returns the nth item in the container's 'natural' order. This is the same as nth-element unless the contaienr is of type container-uses-nodes-mixin.")) (defgeneric item-at (indexed-container-mixin &rest indexes) (:documentation "Returns the item specified by the indexes.")) (defgeneric (setf item-at) (value container &rest indexes) (:documentation "")) (defgeneric item-at! (indexed-container-mixin value &rest indexes) (:documentation "[Destructively] modifies the item specified by the indexes to the value.")) (defgeneric (setf item-at-1) (value container index) (:documentation "")) (defgeneric find-item (findable-container-mixin item) (:documentation "Find item in container using the container's test method for comparisons. The test method must take two parameters. The first will be the item being searched for; the second will be an item in the container. If the container has a key (keyed-container-mixin), then the test is performed on the item and the key of each element in the container. Find-item returns nil if the item is not found and it returns the element in the container if it is.")) (defgeneric find-node (findable-container-mixin thing) (:documentation "Find node containing thing in container using the container's test method for comparisons. The test method must take two parameters. The first will be the item being searched for; the second will be an item in the container. If the container has a key (keyed-container-mixin), then the test is performed on the item and the key of each element in the container. Find-item returns nil if the thing is not found and it returns the node in the container if it is. Find-node is the same as find-element for containers that do not use nodes.")) (defgeneric find-element (findable-container-mixin thing) (:documentation "For now, compare find-item.")) (defgeneric search-for-item (container item &key test key) (:documentation "Hunt for the item in the container. Key and Test are as in member.")) (defgeneric search-for-match (container predicate &key key) (:documentation "Hunt for an item in the container that satisfies the predicate. Key is as in count-if.")) (defgeneric iterate-nodes (iteratable-container-mixin function) (:documentation "Applies function to each node in the container. If the container doesn't have nodes, then this is equivalent to iterate-elements.")) (defgeneric print-container (iteratable-container-mixin &optional stream) (:documentation "Prints the contents of container (using PRINT). Returns the container.")) (defgeneric collect-nodes (container &key filter transform) (:documentation "Returns a possibly filtered and possibly transformed list of the nodes in a container. If the container uses nodes, then the items are the nodes. If not, collect-nodes is equivalent to collect-elements.")) (defgeneric collect-elements (container &key filter transform) (:documentation "Returns a possibly filtered and possibly transformed list of the elements in a container. If the container uses nodes, then the elements are the things 'in' the nodes. Warning: it is possible for the result to share structure with the original container.")) (defgeneric collect-key-value (container &key filter transform) (:documentation "Iterate over the keys and values of the container and return a list of the ones that pass the filter function transformed by the transform function.")) (defgeneric collect-keys (container &key filter transform) (:documentation "Collects the `keys` of a container into a list. The `filter` and `transform` arguments should be `nil` or functions of one argument. If `filter` is non-nil, then the list returned will contain only `keys` that return true. If transform is non-nil, then it will be applied to each key that passes the filter.")) (defgeneric iterate-value-key (container function)) (defgeneric (setf first-element) (x y) (:documentation "")) (defun first-item (x) (first-element x)) (defun last-item (x) (last-element x)) (defgeneric delete-first (ordered-container-mixin) (:documentation "Removes (and returns) the first item in an ordered container. Behavior is undefined if the container is empty.")) (defgeneric delete-last (ordered-container-mixin) (:documentation "Removes (and returns) the last item in an ordered container. Behavior is undefined if the container is empty.")) (defgeneric insert-item (non-associative-container-mixin item) (:documentation "Adds item to the container")) (defgeneric append-item (ordered-container item) (:documentation "Add an item to the end of an ordered container.")) (defgeneric insert-new-item (non-associative-container-mixin item &key test key) (:documentation "Adds item to the container unless it is already there")) (defgeneric append-new-item (ordered-container item &key test key) (:documentation "Add an item to the end of an ordered container unless its already there.")) (defgeneric insert-sequence (non-associative-container-mixin sequence) (:documentation "Adds each item in the sequence to the container in an upspecified order.")) (defgeneric insert-list (non-associative-container-mixin list) (:documentation "Adds each item in the list to the container in an upspecified order.")) (defgeneric delete-list (non-associative-container-mixin list) (:documentation "Deletes each item in the list from the container.")) (defgeneric reverse-find (contents-as-hashtable-mixin value &key test) (:documentation "Finds the key in the associative-container whose value is VALUE.")) (defgeneric ensure-sorted (container) (:documentation "This method ensures that the sorted-list-container is sorted, and then returns the container.")) (defgeneric force-sort (container) (:documentation "This method forces a sort on the next pertinent access of the container.")) (defgeneric remove-items-if (container test) (:documentation "Removes items from a container that satisfy the test. The container is returned.")) (defgeneric container->array (ordered-container-mixin)) (defgeneric element-position (ordered-container-mixin element &key test key) (:documentation "Returns the position of element in container using test and key to match. Key defaults to identity and test defaults to eq.")) (defgeneric reverse-container (ordered-container-mixin) (:documentation "Destructively alters the elements/nodes of an ordered container so that they are reversed.")) (defgeneric unique-elements (container &key key) (:documentation "")) (defgeneric unique-nodes (container &key key) (:documentation "")) (defgeneric add-default-item (object &rest indexes) (:documentation "")) (defgeneric add-initial-contents (object initial-contents) (:documentation "")) (defgeneric best-element (container function &key key test filter) (:documentation "")) (defgeneric best-node (container function &key key test filter) (:documentation "")) (defgeneric biggest-item (heap) (:documentation "")) (defgeneric children (many-child-node) (:documentation "")) (defgeneric clean-up (container) (:documentation "")) (defgeneric collect-elements-stably (container &key filter transform) (:documentation "")) (defgeneric collect-items (object &rest args &key filter transform) (:documentation "")) (defgeneric collect-key-value-stably (container) (:documentation "")) (defgeneric combine-elements (iterator) (:documentation "")) (defgeneric container-difference (c1 c2 &key key1 key2 ) (:documentation "")) (defgeneric container-dimension (container dimension) (:documentation "")) (defgeneric count-elements (container item &key key test) (:documentation "")) (defgeneric count-elements-if (container test &key key) (:documentation "")) (defgeneric count-items (container item &key key test) (:documentation "")) (defgeneric delete-biggest-item (heap) (:documentation "")) (defgeneric delete-element (q item) (:documentation "")) (defgeneric delete-item (ordered-container-mixin item) (:documentation "")) (defgeneric delete-item-after (list node) (:documentation "")) (defgeneric delete-item-at (container &rest indexes) (:documentation "")) (defgeneric delete-item-before (list node) (:documentation "")) (defgeneric delete-item-if (ordered-container-mixin test) (:documentation "")) (defgeneric delete-node (tree node) (:documentation "")) (defgeneric dequeue (abstract-queue) (:documentation "")) #+(or) ;; no, it's a slot (defgeneric dimensions (x) (:documentation "")) #+(or) ;; no, it's a slot (defgeneric element (x) (:documentation "")) #+(or) ;; no, it's a slot (defgeneric (setf element) (x y) (:documentation "")) (defgeneric enqueue (abstract-queue item) (:documentation "")) (defgeneric error-if-queue-empty (q &optional message &rest rest) (:documentation "")) (defgeneric every-element-p (array predicate) (:documentation "")) (defgeneric every-key-value-p (container predicate) (:documentation "")) (defgeneric exchange-heap-nodes (n1 n2 heap) (:documentation "")) (defgeneric find-child-node (node child &key test key) (:documentation "")) (defgeneric find-set (item) (:documentation "")) (defgeneric find-value (container item) (:documentation "")) (defgeneric first-element (x) (:documentation "")) (defgeneric graft-nodes (node1 node2) (:documentation "")) (defgeneric has-children-p (node) (:documentation "")) (defgeneric heap-node-parent (node heap) (:documentation "")) (defgeneric heapify (heap node) (:documentation "")) (defgeneric height (tree) (:documentation "")) (defgeneric increment-end (container) (:documentation "")) (defgeneric initialize-container (container) (:documentation "")) (defgeneric inorder-walk (tree walk-fn) (:documentation "")) (defgeneric inorder-walk-nodes (tree walk-fn) (:documentation "")) (defgeneric insert-item-after (list node new-node) (:documentation "")) (defgeneric insert-item-at (container item index) (:documentation "Inserts item at the specified index, increasing the index of all following elements")) (defgeneric insert-item-before (list node new-node) (:documentation "")) (defgeneric insert-item-ordered (list new-node) (:documentation "")) (defgeneric insert-item-ordered-about-node (list node new-node) (:documentation "")) (defgeneric item-at-1 (container index) (:documentation "")) (defgeneric item-at-1! (hash-table value index) (:documentation "")) (defgeneric item-key (container &rest indexes) (:documentation "")) (defgeneric iterate-container (iterator fn) (:documentation "")) (defgeneric iterate-elements (graph fn) (:documentation "")) (defgeneric iterate-elements-stably (container fn) (:documentation "")) (defgeneric iterate-key-value (container function) (:documentation "")) (defgeneric iterate-key-value-stably (container fn) (:documentation "")) (defgeneric iterate-keys (container function) (:documentation "")) (defgeneric iterate-left (list item fn &optional inclusive?) (:documentation "")) (defgeneric iterate-left-nodes (list item fn) (:documentation "")) (defgeneric iterate-nodes-about-node (list item left-fn right-fn) (:documentation "")) (defgeneric iterate-right (list item fn &optional inclusive?) (:documentation "")) (defgeneric iterate-right-nodes (list item fn) (:documentation "")) (defgeneric l-child (node heap) (:documentation "")) (defgeneric l-child-index (node) (:documentation "")) (defgeneric last-element (x) (:documentation "")) (defgeneric (setf last-element) (x y) (:documentation "")) (defgeneric left-and-right-nodes-for-item (list item) (:documentation "")) (defgeneric left-node-for-item (list item) (:documentation "")) (defgeneric link-nodes (node1 node2) (:documentation "")) (defgeneric make-initial-element (container) (:documentation "")) (defgeneric make-node-for-container (container item &key) (:documentation "")) (defgeneric make-set (item) (:documentation "")) (defgeneric next-item (x) (:documentation "")) (defgeneric node-empty-p (node) (:documentation "")) (defgeneric node-parent-index (node) (:documentation "")) (defgeneric pop-item (abstract-stack) (:documentation "")) (defgeneric postorder-walk (tree walk-fn) (:documentation "")) (defgeneric postorder-walk-nodes (tree walk-fn) (:documentation "")) (defgeneric predecessor (sorted-container-mixin item) (:documentation "Return the item that comes *before* item in the container. Only makes sense for sorted containers. Raises an element-not-found-error if the item isn't present in the container.")) (defgeneric preorder-walk (tree walk-fn) (:documentation "")) (defgeneric preorder-walk-nodes (tree walk-fn) (:documentation "")) (defgeneric print-container-contents (container stream) (:documentation "")) (defgeneric print-container-summary (container stream) (:documentation "")) (defgeneric push-item (stack item) (:documentation "")) (defgeneric r-child (node heap) (:documentation "")) (defgeneric r-child-index (node) (:documentation "")) (defgeneric rb-delete-fixup (tree x) (:documentation "")) (defgeneric reduce-container (container function &rest args &key key initial-value start end) (:documentation "")) (defgeneric reduce-elements (container function &key key initial-value start end) (:documentation "")) (defgeneric reduce-nodes (container function &key key initial-value start end) (:documentation "")) (defgeneric replace-item (list node start-item &key length finish-item) (:documentation "")) (defgeneric representative (container item) (:documentation "")) (defgeneric representative-node (container item) (:documentation "")) (defgeneric right-node-for-item (list item) (:documentation "")) (defgeneric rotate-left (tree x) (:documentation "")) (defgeneric rotate-right (tree x) (:documentation "")) (defgeneric search-for-element (list item &key test key) (:documentation "")) (defgeneric search-for-key (container key-to-find &key test key) (:documentation "")) (defgeneric search-for-matching-node (container predicate &key key) (:documentation "")) (defgeneric search-for-node (container item &key test key) (:documentation "")) (defgeneric search-for-node* (container item &key test key) (:documentation "")) (defgeneric set-dirty-flag (container flag) (:documentation "")) (defgeneric some-element-p (array predicate) (:documentation "")) (defgeneric some-key-value-p (container predicate) (:documentation "")) (defgeneric sort-container (container sorter key-fn) (:documentation "")) (defgeneric sort-elements (container sorter &key key) (:documentation "")) (defgeneric sort-keys (container sorter &key key) (:documentation "")) (defgeneric sort-update-left (list node) (:documentation "")) (defgeneric sort-update-right (list node) (:documentation "")) (defgeneric successor (sorted-container-mixin item) (:documentation "Return the item that comes after item in the container. Only makes sense for sorted containers. Raises an element-not-found-error if the item isn't present in the container.")) (defgeneric total-size (x) (:documentation "")) (defgeneric update-element (tree value &rest indexes) (:documentation "")) (defgeneric update-item (list item) (:documentation "")) (defgeneric walk-tree (node walk-fn &optional mode) (:documentation "")) (defgeneric walk-tree-nodes (node walk-fn &optional mode) (:documentation "")) (defgeneric (setf packages) (value container) (:documentation "")) (defgeneric container->list (graph) (:documentation "")) (defgeneric current-item (container) (:documentation "")) (defgeneric iterate-children (node fn) (:documentation "Calls `fn` on every child of `node`.")) (defgeneric first-node (container) (:documentation "")) (defgeneric %operate-after-finding (container element operation) ) (defgeneric insert-initial-contents-p (container) (:documentation "Returns true if this container type should rely on the default behavior of basic-initial-contents-mixin.")) (defgeneric iteratable-p (thing) (:documentation "Returns true if thing knows how to iterate-nodes.") (:method ((thing t)) (values nil))) (defgeneric key-value-iteratable-p (thing) (:documentation "Returns true if thing knows how to iterate-nodes.") (:method ((thing t)) (values nil))) cl-containers-20170403-git/dev/container-mixins.lisp000066400000000000000000000031221306646076300222450ustar00rootroot00000000000000(in-package #:containers) (defclass* filtered-container-mixin () ((element-filter nil ia) (key-filter nil ia)) (:export-slots element-filter)) (defmethod iterate-elements :around ((container filtered-container-mixin) fn) (let ((filter (element-filter container))) (if filter (call-next-method container (lambda (element) (when (funcall filter element) (funcall fn element)))) (call-next-method container fn)))) (defmethod collect-elements :around ((container filtered-container-mixin) &key filter transform) (let ((element-filter (element-filter container))) (if element-filter (call-next-method container :filter (lambda (element) (when (funcall element-filter element) (or (not filter) (funcall filter element)))) :transform transform) (call-next-method container)))) (defmethod iterate-key-value :around ((container filtered-container-mixin) fn) (let ((element-filter (element-filter container)) (key-filter (key-filter container))) (if (or element-filter key-filter) (call-next-method container (lambda (k v) (when (and (or (not element-filter) (and element-filter (funcall element-filter v))) (or (not key-filter) (and key-filter (funcall key-filter k)))) (funcall fn k v)))) (call-next-method)))) cl-containers-20170403-git/dev/container-sampling.lisp000066400000000000000000000153111306646076300225530ustar00rootroot00000000000000 (in-package #:containers) (eval-when (:compile-toplevel :load-toplevel :execute) (use-package (find-package 'cl-variates) (find-package 'cl-containers))) (defmethod sample-item ((container t) (generator variates:random-number-generation-mixin)) (sample-item container (variates:random-number-generator generator))) (defmethod sample-item ((container iteratable-container-mixin) (generator variates:basic-random-number-generator)) (let ((index (variates:integer-random generator 0 (1- (size container))))) (nth-item container index))) (defmethod sample-item ((container sequence) (generator variates:basic-random-number-generator)) (declare (inline sample-element)) (sample-element container generator)) (defmethod nth-item ((container iteratable-container-mixin) index) ;; possibly slow but servicable method (iterate-container container (lambda (elt) (when (minusp (decf index)) (return-from nth-item elt)))) (error "Index ~D out of range for container ~A" index container)) (defmethod sample-element ((container t) (generator variates:random-number-generation-mixin)) (sample-element container (variates:random-number-generator generator))) (defmethod sample-element ((container (eql nil)) (generator variates:basic-random-number-generator)) (values nil)) (defmethod sample-element ((container iteratable-container-mixin) (generator variates:basic-random-number-generator)) (let ((element (variates:integer-random generator 0 (1- (size container))))) (nth-element container element))) (defmethod sample-element ((container sequence) (generator variates:basic-random-number-generator)) (let ((element (variates:integer-random generator 0 (1- (size container))))) (nth-element container element))) (defmethod sample-unique-elements ((container t) (generator variates:random-number-generation-mixin) (count integer)) (sample-unique-elements container (variates:random-number-generator generator) count)) (defmethod sample-unique-elements ((container iteratable-container-mixin) (generator variates:basic-random-number-generator) (count integer)) (%sample-unique-elements container generator count) #+Old (loop for bit across (variates:select-sample generator count (size container)) for index = 0 then (1+ index) unless (zerop bit) collect (nth-element container index))) (defmethod sample-unique-elements ((container list) (generator variates:basic-random-number-generator) (count integer)) (%sample-unique-elements container generator count) #+Old (loop for bit across (variates:select-sample generator count (size container)) for index = 0 then (1+ index) unless (zerop bit) collect (nth-element container index))) (defmethod sample-unique-elements ((container array) (generator variates:basic-random-number-generator) (count integer)) (%sample-unique-elements container generator count) #+Old (loop for bit across (variates:select-sample generator count (size container)) for index = 0 then (1+ index) unless (zerop bit) collect (nth-element container index))) #+SLOWER ;;?? Gary King 2005-11-04: intuitively, this should win because it bails out ;; early. However, loop must be doing something clever and so it doesn't. (defun %sample-unique-elements (container generator count) (let ((result nil)) (loop for bit across (variates:select-sample generator count (size container)) for index = 0 then (1+ index) unless (zerop bit) do (decf count) (push (nth-element container index) result) when (zerop count) do (return)) (nreverse result))) (defun %sample-unique-elements (container generator count) (let ((result nil)) (loop for bit across (variates:select-sample generator count (size container)) for index = 0 then (1+ index) unless (zerop bit) do (push (nth-element container index) result) ) (nreverse result))) #+Test (let ((l (collect-elements (make-generator :start 0 :end 1000)))) (timeit (:report t) (loop repeat 1000 do (sample-unique-elements l *random-generator* 10)))) (defmethod sample-elements ((container t) (generator variates:random-number-generation-mixin) (count integer)) (sample-elements container (variates:random-number-generator generator) count)) (defmethod sample-elements ((container iteratable-container-mixin) (generator variates:basic-random-number-generator) (count integer)) (loop repeat count collect (sample-element container generator))) (defmethod sample-elements ((container list) (generator variates:basic-random-number-generator) (count integer)) (loop repeat count collect (sample-element container generator))) (defun safe-sample-unique-elements (container generator count) (if (length-at-most-p container count) (collect-elements container) (sample-unique-elements container generator count))) #+Test (let ((c (make-container 'list-container :initial-contents (loop for i from 0 to 10 collect i)))) (containers::sample-unique-elements c variates:*random-generator* 5)) #+Test (let ((c (make-container 'array-container :dimensions '(5 5)))) (loop for i from 0 to 4 do (loop for j from 0 to 4 do (setf (item-at c i j) (* (1+ i) (1+ j))))) (containers::sample-unique-elements c variates:*random-generator* 5)) (defmethod variates:shuffle-elements! ((container abstract-container) &key (generator variates:*random-generator*) (times 0 times-supplied?)) (let ((size (1- (size container)))) (dotimes (i (if times-supplied? times (* 2 size))) (rotatef (nth-element container (variates:integer-random generator 0 size)) (nth-element container (variates:integer-random generator 0 size)))))) (defmethod variates:shuffle-elements! ((container uses-contents-mixin) &rest args) (declare (dynamic-extent args)) (apply #'variates:shuffle-elements! (contents container) args) container) cl-containers-20170403-git/dev/container-thread-safe.lisp000066400000000000000000000016641306646076300231320ustar00rootroot00000000000000(in-package #:containers) (defclass* thread-safe-container-mixin () () (:export-p t)) (defmethod insert-item :around ((container thread-safe-container-mixin) item) (declare (ignore item)) (u:with-write-access (:container) (call-next-method))) (defmethod delete-first :around ((container thread-safe-container-mixin)) (u:with-write-access (:container) (call-next-method))) (defmethod iterate-nodes :around ((container thread-safe-container-mixin) fn) (declare (ignore fn)) (u:with-read-access (:container) (call-next-method))) (defmethod empty! :around ((container thread-safe-container-mixin)) (u:with-write-access (:container) (call-next-method))) (defmethod first-item :around ((container thread-safe-container-mixin)) (u:with-read-access (:container) (call-next-method))) (defmethod size :around ((container thread-safe-container-mixin)) (u:with-read-access (:container) (call-next-method))) cl-containers-20170403-git/dev/containers-moptilities.lisp000066400000000000000000000002611306646076300234640ustar00rootroot00000000000000(in-package #:cl-containers) (defmethod mopu:when-finalized ((iterator basic-stream-iterator)) ;;?? ;(format t "~%GC: Maybe closing stream" iterator) (finish iterator)) cl-containers-20170403-git/dev/containers-readtable.lisp000066400000000000000000000155561306646076300230620ustar00rootroot00000000000000(in-package #:containers) #| #[basic-queue 3 4 5 6] #[vector-container 4 1 2 3] #[associative-container [4 5] [2 :a] [3 2]] #[associative-container (4 5) ([1 2] :a) (3 2)] (make-container 'associative-container :initial-contents '((4 3) 5 6 7)) (print-container *) #[associative-container 4 5 1 :a 3 :c] BB on DB with strong ontology |# (defvar *container-readtable* (copy-readtable)) (defvar *container-print-representation* :summary ;; :contents "Specifies the output format for container printing. This can be :contents or :summary.") (defvar *container-print-length* nil "Specifies the maximum number of container elements to print when *container-print-representation* is :contents. If *container-print-length* less than the size of the container, then *container-print-length* elements will be printed followed by an ellipse. If *container-print-length* is null, then all elements will be printed.") (defvar *container-print-association-string* " -> " "Specify the string used to separate keys and values when printing the contents of an associative-container.") (defvar *container-print-association-separator* "; " "Specify the string used to separate pairs when printing the contents of an associative-container.") (set-macro-character #\[ #'(lambda (stream ignore) (declare (ignore ignore)) (read-container-element stream #\])) nil *container-readtable*) (set-macro-character #\] #'(lambda (stream ch) (warn "Ignoring extra \"~c\" on ~s ." ch stream)) nil *container-readtable*) #+MCL ;;?? Gary King 2005-11-17: need to port (defun read-container (stream &optional (termch #\])) (let* ((head (cons nil nil)) (tail head)) (declare (dynamic-extent head) (list head tail)) (loop (multiple-value-bind (form form-p) (ccl::%read-list-expression stream nil termch) (when (not form-p) (return)) (rplacd tail (setq tail (cons form nil))))) (cdr head))) #+MCL ;;?? Gary King 2005-11-17: need to port (defun read-container-element (stream &optional (termch #\])) (let* ((head (cons nil nil)) (tail head)) (declare (dynamic-extent head) (list head tail)) (loop (multiple-value-bind (form form-p) (ccl::%read-list-expression stream nil termch) (when (not form-p) (return)) (rplacd tail (setq tail (cons form nil))))) (cdr head))) #+MCL ;;?? Gary King 2005-11-17: need to port (set-dispatch-macro-character #\# #\[ (lambda (stream subchar numarg) (declare (ignore subchar numarg)) (let ((*readtable* *container-readtable*)) (destructuring-bind (type &rest data) (ccl::read-list stream t #\]) (make-container type :initial-contents data))))) #+MCL ;;?? Gary King 2005-11-17: need to port (defmethod print-object ((container abstract-container) stream) (ecase *container-print-representation* (:contents (format stream "#[~A" (type-of container)) (print-container-contents container stream) (princ #\] stream)) (:summary (print-unreadable-object (container stream :type t :identity t) (print-container-summary container stream))))) (defmethod print-container-summary ((container abstract-container) stream) (format stream "~D" (size container))) (defmethod print-container-contents ((container abstract-container) stream) (let* ((base-print-fn (lambda (element) (princ " " stream) (prin1 element stream))) (print-fn (if *container-print-length* (let ((count 0)) (lambda (element) (when (> (incf count) *container-print-length*) (princ " ..." stream) (return-from print-container-contents)) (funcall base-print-fn element))) base-print-fn))) (iterate-elements container print-fn))) (defmethod print-container-contents ((container associative-container-mixin) stream) (let* ((first? t) (base-print-fn (lambda (key value) (if first? (princ " " stream) (princ *container-print-association-separator* stream)) (setf first? nil) (prin1 key stream) (princ *container-print-association-string* stream) (prin1 value stream))) (print-fn (if *container-print-length* (let ((count 0)) (lambda (key value) (when (> (incf count) *container-print-length*) (princ " ..." stream) (return-from print-container-contents)) (funcall base-print-fn key value))) base-print-fn))) (iterate-key-value container print-fn))) (defmethod print-container-contents ((container array-container-abstract) stream) (princ "..." stream)) #+Test (let ((*container-print-length* 5) (*container-print-representation* :contents) (c (make-container 'list-container))) (loop repeat 20 do (insert-item c (variates:integer-random variates:*random-generator* 0 100))) (print c) (values)) #+Test (let ((*container-print-length* 5) (*container-print-representation* :contents) (c (make-container 'alist-container))) (loop for i from 1 to 20 do (setf (item-at c i) (variates:integer-random variates:*random-generator* 0 100))) (print c) (values)) ;;; container-printing-mixin (defclass* container-printing-mixin () ((print-representation :unbound ia) (print-length :unbound ia) (print-association-string :unbound ia) (print-association-separator :unbound ia)) (:default-initargs :print-representation :summary :print-length nil :print-association-string " -> " :print-association-separator ";")) (defmethod print-object :around ((container container-printing-mixin) stream) (declare (ignorable stream)) (let ((*container-print-representation* (print-representation container)) (*container-print-length* (print-length container)) (*container-print-association-string* (print-association-string container)) (*container-print-association-separator* (print-association-separator container))) (call-next-method))) #+Example (let ((c (make-container '(simple-associative-container container-printing-mixin) :initial-contents '(:a 1 :b 2 :c 3 :d 4 :e 5) :print-representation :summary))) (print c) (values)) #+Example (let ((c (make-container '(simple-associative-container container-printing-mixin) :initial-contents '(:a 1 :b 2 :c 3 :d 4 :e 5) :print-representation :contents :print-length 3))) (print c) (values))cl-containers-20170403-git/dev/containers.lisp000066400000000000000000000417071306646076300211360ustar00rootroot00000000000000 (in-package #:containers) (defparameter +empty-initial-element+ (cons :nothing nil)) (defclass* abstract-container () () (:documentation "Inherited by all container classes, this is a good place to put those pesky superclasses you need everyone to inherit.") (:export-p t)) (defclass* concrete-container () () (:documentation "Inherited by all container classes that can/should be instantiated using make-container.")) (defclass* container-node-mixin () ((element nil ia)) ;?? :unbound (:export-slots element) (:export-p t)) (defclass* parent-node-mixin (container-node-mixin) ((parent nil ia)) (:documentation "A mixin for nodes with parent pointers")) (defclass* two-child-node (parent-node-mixin) ((right-child nil a) (left-child nil a) (parent nil ia))) ;;; Generic container class and various generic operations ;;; Various useful (?) container mixins ;;; keyed containers ;;; supports: key ;;; (defclass* keyed-container-mixin (abstract-container) ((key :initform 'identity ; 20020126, LST: changed to a bare symbol, since you can dump that. :initarg :key :reader key))) ;;; Typed containers ;;; supports: element-type ;;; (defclass* typed-container-mixin (abstract-container) ((element-type :initform nil :initarg :element-type :reader element-type))) ;;; Bounded containers (containers of fixed size) ;;; supports: total-size ;;; (defclass* bounded-container-mixin (abstract-container) ()) ;;; Indexed containers (containers you can point into) ;;; supports: item-at, (setf item-at) ;;; (defclass* indexed-container-mixin (abstract-container) ()) (defmethod (setf item-at) (value container &rest indexes) (apply #'item-at! container value indexes)) ;;; initial-element-mixin ;;; supports: initial-element ;;; (defclass* initial-element-mixin (abstract-container) ((initial-element :unbound ia) (initial-element-fn nil ir :initarg :initial-element-function :reader initial-element-function) (has-initial-element-p nil r))) (defmethod initialize-instance :after ((object initial-element-mixin) &key) (assert (or (null (initial-element-fn object)) (functionp (initial-element-fn object)) (and (symbolp (initial-element-fn object)) (symbol-function (initial-element-fn object)))) nil "Initial-element-fn must be nil or a function.") (when (and (initial-element-fn object) (symbolp (initial-element-fn object)) (symbol-function (initial-element-fn object))) (setf (slot-value object 'initial-element-fn) (symbol-function (initial-element-fn object)))) (when (or (initial-element-fn object) (slot-boundp object 'initial-element)) (setf (slot-value object 'has-initial-element-p) t (slot-value object 'initial-element-fn) (cond ((initial-element-fn object) (initial-element-fn object)) ((slot-boundp object 'initial-element) (lambda () (initial-element object))))))) (defun return-empty-initial-element () +empty-initial-element+) ;;?? Gary King 2004-05-01: this could be optimized into a single call at ;; creation time -- i.e., do the tests then once, not now many times. (defmethod make-initial-element ((container initial-element-mixin)) (funcall (initial-element-fn container))) ;;; initial-contents-mixin ;;; supports: initial-contents ;;; (defclass* basic-initial-contents-mixin (abstract-container) ()) (defclass* initial-contents-mixin (basic-initial-contents-mixin) () (:export-p t)) (defclass* initial-contents-key-value-mixin (basic-initial-contents-mixin) ()) (defmethod initialize-instance :after ((object basic-initial-contents-mixin) &key initial-contents) (when (insert-initial-contents-p object) (add-initial-contents object initial-contents))) ;;; findable-containers, searchable-containers ;;; supports: test, find-item or search-for-item and search-for-match ;;; ;;; A searchable container is any one that can be searched even if it's not ;;; efficient. A findable-container incorporates a pre-specified search into ;;; its construction so that things can be found fast. (defclass* test-container-mixin () ((test :initform 'eq :initarg :test :reader test))) ;;; container-uses-nodes-mixin ;;; ;;; A container that puts things into nodes (like a binary-search-tree or a heap) ;;; (defclass* container-uses-nodes-mixin (abstract-container) () (:export-p t)) (defclass* findable-container-mixin (test-container-mixin keyed-container-mixin abstract-container) ()) (defclass* searchable-container-mixin (test-container-mixin abstract-container) ()) ;;; Iterate-able containers (containers you can run over...) ;;; supports: iterate-nodes [subclasses should override] ;;; NOTES: If you subclass from this and implement iterate-nodes, ;;; then you get print-container, collect-items, ;;; search-for-item, and delete-item-if for free. (defclass* iteratable-container-mixin (searchable-container-mixin) ()) (defclass* key-value-iteratable-container-mixin (iteratable-container-mixin) ()) ;;?? deprecate ;;?? backward compatibility (defmethod iterate-container (object fn) (funcall #'iterate-nodes object fn)) (defmethod collect-items (object &rest args &key filter transform) (declare (dynamic-extent args) (ignore filter transform)) (apply #'collect-nodes object args)) ;;; i-know-my-node-mixin ;; This would be inherited by elements inserted into the container... ;; It is a hack for optimization and speed (if it had a better name, ;; you would probably call it a trick...) (defclass* i-know-my-node-mixin () ((my-node nil iar)) :export-slots (:export-p t)) (defmethod make-node-for-container :around ((container t) (item i-know-my-node-mixin) &key) (let ((node (call-next-method))) (setf (my-node item) node) (values node))) ;;; unordered-container-mixin ;;; the items are not in any order (e.g., a bag) (defclass* non-associative-container-mixin (abstract-container) () (:export-p t) (:documentation "A non associative container should implement at least empty-p, empty, insert-item and delete-item.")) (defclass* unordered-container-mixin (non-associative-container-mixin) ()) ;;; ordered-container-mixin ;;; the items are in an order, but not sorted (e.g., a list, not a bag) ;;; of course, some of these operations could be very expensive (defclass* ordered-container-mixin (non-associative-container-mixin) ()) ;;; sorted-container-mixin (defclass* sorted-container-mixin (keyed-container-mixin ordered-container-mixin) ((sorter #'< ia))) ;;; classified-container-mixin ;;; ;;; A classified container determines, based on the key, where an element is ;;; best suited. For example, a quad-tree uses the classifier to choose which ;;; of a node's 4 children an element belongs in. (defclass* classified-container-mixin (ordered-container-mixin keyed-container-mixin) "A classified container returns some value appropriate to the specific container class. For example, a quad tree is of the type classified-container-mixin, and the classifier returns one of :TOP-LEFT, :TOP-RIGHT, :BOTTOM-LEFT or :BOTTOM-RIGHT" ((classifier :initform #'< :initarg :classifier :accessor classifier))) ;;; uses-contents-mixin ;;; ;;; Container returns its contents via a contents method (defclass* uses-contents-mixin (abstract-container) ((contents nil r))) (defmethod initialize-instance :after ((object uses-contents-mixin) &rest args &key &allow-other-keys) (when (or (not (slot-boundp object 'contents)) (null (contents object))) (setf (slot-value object 'contents) (apply #'make-container-for-contents object args)))) (defmethod collect-elements ((object uses-contents-mixin) &rest args &key filter transform) (declare (ignore filter transform) (dynamic-extent args)) (apply #'collect-elements (contents object) args)) (defmethod iterate-nodes ((object uses-contents-mixin) fn) (funcall #'iterate-nodes (contents object) fn)) ;;; contents-as-sequence-mixin (defclass* contents-as-sequence-mixin (uses-contents-mixin iteratable-container-mixin) ()) ;;; contents-as-array-mixin ;;; ;;; Underlying structure is an array (defclass* contents-as-array-mixin (uses-contents-mixin iteratable-container-mixin) ((contents :accessor contents))) (defmethod size ((container contents-as-array-mixin)) (total-size container)) (defmethod total-size ((container contents-as-array-mixin)) (array-total-size (contents container))) ;;; initialize-instance ;;; --------------------------------------------------------------------------- ;;; So one negative about making an array here is that we have to distinguish ;;; the initial-contents / initial-element case ourselves. Also, we make ;;; the array 'adjustable'. This isn't too big a deal since the only method ;;; that relies on the adjustability is 'empty!' and we can easily rewrite it ;;; to test for adjustability, however MCL and ALLEGRO make all arrays ;;; adjustable anyway. (defmethod insert-initial-contents-p ((container contents-as-array-mixin)) (values nil)) #+Old (defmethod initialize-instance :around ((container contents-as-array-mixin) &key) (let ((*insert-initial-contents-p* nil)) (call-next-method))) (defmethod make-container-for-contents ((container contents-as-array-mixin) &rest args) (let ((initial-size (getf args :initial-size 0)) (initial-contents (getf args :initial-contents nil)) (initial-element (getf args :initial-element nil)) (element-type (getf args :element-type t)) (fill-pointer (getf args :fill-pointer t))) (if initial-contents (make-array (length initial-contents) :initial-contents initial-contents :adjustable t :fill-pointer fill-pointer :element-type element-type) (make-array initial-size :initial-element initial-element :adjustable t :fill-pointer fill-pointer :element-type element-type)))) ;;; Contents-as-list-mixin ;;; ;;; A container whose underlying structure is a list ;;; supports: insert-item, size, empty-p, empty! and iterate-nodes (defclass* contents-as-list-mixin (keyed-container-mixin initial-contents-mixin ordered-container-mixin contents-as-sequence-mixin) ((contents :initform '() :accessor contents))) (defmethod make-container-for-contents ((object contents-as-list-mixin) &rest args) (declare (ignore args)) (values nil)) (defclass* list-container (contents-as-list-mixin concrete-container) ()) ;;; contents-as-hashtable-mixin ;;; ;;; A container whose underlying structure is a hashtable ;;; supports: insert-item, size, empty-p, empty! and iterate-nodes ;;?? should we apply the key function to the indexes? (defclass* contents-as-hashtable-mixin (uses-contents-mixin key-value-iteratable-container-mixin findable-container-mixin) ((contents :unbound :accessor contents) ;; unbound for make-ht-for-container )) ;;; Associative-Containers, various flavors (defclass* associative-container-mixin (initial-contents-key-value-mixin indexed-container-mixin) ()) ;;; array-container ;;; ;;; This is a regular array wrapped by the standard associative container ;;; framework. (defclass* array-container-abstract (associative-container-mixin bounded-container-mixin uses-contents-mixin) ()) (defclass* array-container (array-container-abstract typed-container-mixin initial-element-mixin iteratable-container-mixin concrete-container) ((contents :initform nil :accessor contents))) ;;; Sparse-Array-Container ;;; ;;; This uses a hash table and only allocates the memory for ;;; the "cells" of the array that you set. (defclass* sparse-array-container (associative-container-mixin contents-as-hashtable-mixin test-container-mixin initial-element-mixin bounded-container-mixin concrete-container) ((dimensions nil ir) (use-fixnums? nil r)) (:default-initargs :test #'equal)) ;;; simple-associative-container ;;; ;;; like a regular hash-table (defclass* simple-associative-container (associative-container-mixin initial-element-mixin contents-as-hashtable-mixin test-container-mixin concrete-container ) ()) ;;; associative-container ;;; ;;; Nested hash tables (defclass* associative-container (initial-element-mixin contents-as-hashtable-mixin test-container-mixin associative-container-mixin concrete-container) ()) ;;; biassociative-container-mixin ;;; ;;; A biassociative container is one in which FIND-ITEM and REVERSE-FIND ;;; are just as fast. (Positive example: alist, negative example: hashtable). ;;; (defclass* biassociative-container-mixin (associative-container-mixin) ()) ;;; Associative-list based container (defclass* alist-container (biassociative-container-mixin initial-element-mixin key-value-iteratable-container-mixin uses-contents-mixin concrete-container) ((test #'equal i))) ;;; stable-associative-container ;;; ;;; an associative container that supports "stable" iteration; i.e., you ;;; can iterate over things in the same order that you put them in. This ;;; is still (Gary King 2003-04-24) a work in progress as it only supports ;;; item-at (setf item-at) and iterate-nodes (defclass* stable-associative-container (key-value-iteratable-container-mixin iteratable-container-mixin associative-container-mixin) ((associative-container :unbound) (numbered-container :unbound) (counter 0 r)) (:export-p t) (:default-initargs :container-type 'associative-container)) (defmethod initialize-instance :after ((object stable-associative-container) &rest args &key container-type &allow-other-keys) (setf (slot-value object 'associative-container) (apply #'make-container container-type :test (test object) args) (slot-value object 'numbered-container) (make-container container-type :test (test object)))) ;;; associative-array (defclass* associative-array (concrete-container) ((dim-container :unbound) (num-container :unbound) (array-data :unbound r) (dimensions :unbound))) (defmethod initialize-instance :after ((object associative-array) &key (test 'eq) (dimensions 2) (max-size 1000)) (let ((array-dimensions (make-list dimensions :initial-element max-size))) (setf (slot-value object 'dimensions) dimensions (slot-value object 'dim-container) (make-instance 'array-container :dimensions max-size :initial-element-fn (lambda () (make-container 'associative-container :test test))) (slot-value object 'num-container) (make-instance 'array-container :dimensions dimensions :initial-element 0) (slot-value object 'array-data) (make-container 'sparse-array-container :dimensions array-dimensions)))) (defmethod insert-initial-contents-p ((container basic-initial-contents-mixin)) (values t)) (defmethod iteratable-p ((thing iteratable-container-mixin)) (values t)) (defmethod key-value-iteratable-p ((thing key-value-iteratable-container-mixin)) (values t)) cl-containers-20170403-git/dev/copying.lisp000066400000000000000000000051361306646076300204350ustar00rootroot00000000000000 (in-package #:containers) (defgeneric copy-container (abstract-container) (:method ((container abstract-container)) (metacopy:copy-thing container))) (metacopy:defcopy-methods container-node-mixin :copy-all t) (metacopy:defcopy-methods keyed-container-mixin :copy-all t) (metacopy:defcopy-methods typed-container-mixin :copy-all t) (metacopy:defcopy-methods initial-element-mixin :copy-all t) (metacopy:defcopy-methods test-container-mixin :copy-all t) (metacopy:defcopy-methods i-know-my-node-mixin :copy-all t) (metacopy:defcopy-methods sorted-container-mixin :copy-all t) (metacopy:defcopy-methods classified-container-mixin :copy-all t) (metacopy:defcopy-methods uses-contents-mixin :copy-all t) (metacopy:defcopy-methods priority-queue-on-container :copy-all t) (metacopy:defcopy-methods stack-container :copy-all t) (metacopy:defcopy-methods rooted-tree-container :copy-all t) (metacopy:defcopy-methods parent-node-mixin :copy-all t) (metacopy:defcopy-methods many-unordered-child-node :copy-all t) (metacopy:defcopy-methods two-child-node :copy-all t) (metacopy:defcopy-methods bst-node :copy-all t) (metacopy:defcopy-methods quad-tree :copy-all t) (metacopy:defcopy-methods four-child-node :copy-all t) (metacopy:defcopy-methods quad-tree-node :copy-all t) (metacopy:defcopy-methods basic-queue :copy-all t) (metacopy:defcopy-methods bag-container :copy-all t) (metacopy:defcopy-methods set-container :copy-all t) (metacopy:defcopy-methods bag/set-container :copy-all t) (metacopy:defcopy-methods keyed-bag/set-container :copy-all t) (metacopy:defcopy-methods sorted-list-container :copy-all t) (metacopy:defcopy-methods dlist-container-node :copy-all t) (metacopy:defcopy-methods dlist-container :copy-all t) (metacopy:defcopy-methods red-black-node :copy-all t) (metacopy:defcopy-methods ring-buffer :copy-all t) (metacopy:defcopy-methods array-container :copy-all t) (metacopy:defcopy-methods sparse-array-container :copy-all t) (metacopy:defcopy-methods alist-container :copy-all t) (metacopy:defcopy-methods keyed-associative-container :copy-all t) (metacopy:defcopy-methods heap-node :copy-all t) (metacopy:defcopy-methods k-best-heap-container :copy-all t) (metacopy:defcopy-methods stable-associative-container :copy-all t) (metacopy:defcopy-methods associative-array :copy-all t) (metacopy:defcopy-methods vector-container-mixin :copy-all t) ;;; *************************************************************************** ;;; * End of File * ;;; ***************************************************************************cl-containers-20170403-git/dev/dynamic-class-defs.lisp000066400000000000000000000053601306646076300224320ustar00rootroot00000000000000;; this is the only part that depends on dynamic-classes (in-package #:cl-containers) (defvar *current-iteratee* nil) (defmethod make-container ((classes list) &rest args) (let ((name (find-or-create-class 'abstract-container classes))) (apply #'make-instance name args))) (add-parameter->dynamic-class :iterator :transform 'transforming-iterator-mixin) (add-parameter->dynamic-class :iterator :filter 'filtered-iterator-mixin) (add-parameter->dynamic-class :iterator :unique 'unique-value-iterator-mixin) (add-parameter->dynamic-class :iterator :circular 'circular-iterator-mixin) #+(or) ;;?? Gary King 2005-07-18: didn't work?? (add-dynamic-class-for-parameters :generator 'arithmetic-sequence-generator nil '(:start :by)) (add-parameter->dynamic-class :generator :start 'arithmetic-sequence-generator) (add-parameter->dynamic-class :generator :by 'arithmetic-sequence-generator) (add-parameter->dynamic-class :generator :transform 'transforming-iterator-mixin) (add-parameter->dynamic-class :generator :filter 'filtered-iterator-mixin) (add-parameter->dynamic-class :generator :unique 'unique-value-iterator-mixin) (add-parameter->dynamic-class :generator :end 'finite-arithmetic-sequence-generator) (defmethod existing-subclass ((class-type (eql :iterator)) class-list) (find-existing-subclass 'abstract-generator class-list)) (defmethod existing-subclass ((class-type (eql :generator)) class-list) (find-existing-subclass 'abstract-generator class-list)) (defun determine-iterator-class (iteratee iterator-class &rest parameters) (let ((*current-iteratee* iteratee)) (apply #'determine-dynamic-class :iterator iterator-class parameters))) (defun determine-generator-class (generator-class &rest parameters) (apply #'determine-dynamic-class :generator generator-class parameters)) (defmethod include-class-dependencies ((class-type (eql :iterator)) dynamic-class class-list &rest parameters &key treat-contents-as &allow-other-keys) (declare (ignore dynamic-class parameters)) (append class-list (list (or (and treat-contents-as (class-for-contents-as *current-iteratee* treat-contents-as)) (base-class-for-iteratee *current-iteratee*))))) ;;;; (defmethod class-for-contents-as ((contents t) (as t)) (values nil)) (defmethod base-class-for-iteratee ((container list)) 'list-iterator) (defmethod base-class-for-iteratee ((container array)) 'array-iterator) (defmethod base-class-for-iteratee ((container hash-table)) 'hash-table-iterator) (defmethod base-class-for-iteratee ((container uses-contents-mixin)) (base-class-for-iteratee (contents container))) cl-containers-20170403-git/dev/dynamic-classes.lisp000066400000000000000000000216371306646076300220500ustar00rootroot00000000000000(in-package #:cl-containers) #| pulled in from separate library 'cause it was just easier, dammit |# ;;; some class defining functions (defvar *define-class-form* 'metatilities:defclass* "The name of the form used to define a class. Usually, this will be bound to 'defclass* but when we are using GBBOpen, it will probably be bound to define-class or define-class*.") #+test (setf *define-class-form* 'metatilities:defclass*) (defun simple-define-class (superclasses &optional (name (simple-define-class-name superclasses))) "Define a class on the fly..." (cond ((and (length-1-list-p superclasses) (find-class (first superclasses) nil)) (values (first superclasses))) (t (muffle-redefinition-warnings (eval `(progn (when (find-class ',name nil) (setf (find-class ',name) nil)) (defclass* ,name ,(ensure-list superclasses) nil)))) (values name)))) (defun simple-define-class-name (superclasses &optional (package *package*)) (intern (format nil "~{~a~^-AND-~}" superclasses) package)) (defun define-class (class-name superclasses slots &rest class-options) "Define a class with all the bells and whistles on the fly... See simple-define-class for the simpler version." (muffle-redefinition-warnings (eval `(,*define-class-form* ,(or class-name (setf class-name (simple-define-class-name (ensure-list superclasses)))) ,(ensure-list superclasses) (,@(ensure-list slots)) ,@class-options))) (values class-name)) (defun map-subclasses (class fn &key proper?) "Applies fn to each subclass of class. If proper? is true, then the class itself is not included in the mapping. Proper? defaults to nil." (let ((mapped (make-hash-table :test #'eq))) (labels ((mapped-p (class) (gethash class mapped)) (do-it (class root) (unless (mapped-p class) (setf (gethash class mapped) t) (unless (and proper? root) (funcall fn class)) (mapc (lambda (class) (do-it class nil)) (class-direct-subclasses class))))) (do-it (get-class class) t)))) (defun superclasses (thing &key (proper? t)) "Returns a list of superclasses of thing. Thing can be a class, object or symbol naming a class. The list of classes returned is 'proper'; it does not include the class itself." (let ((result (class-precedence-list (finalize-class-if-necessary (get-class thing))))) (if proper? (rest result) result))) (defun find-existing-subclass (superclass superclasses) "Look through all the sub-classes of superclass and see if any of them descend from every class in superclasses." (let ((results nil)) (map-subclasses superclass (lambda (subclass) (let ((last-position -1)) (when (every (lambda (superclass) (let ((pos (position superclass (superclasses subclass :proper? nil) :key (lambda (x) (class-name x))))) (prog1 (and pos (< last-position pos)) (setf last-position pos)))) superclasses) (push (class-name subclass) results))))) (values (first results)))) (defun find-or-create-class (root classes) "Try to find a class which is a subclass of root and all of the other `classes` as well. If no such class exists, then it will be created and returned." (or (find-existing-subclass root classes) (let ((superclasses (remove-redundant-classes classes))) (define-class (simple-define-class-name (remove-redundant-classes superclasses)) classes nil)))) (defun remove-redundant-classes (classes) (loop for class in classes unless (class-redundant-p class classes) collect class)) (defun class-redundant-p (class classes) (some (lambda (other-class) (and (not (eq class other-class)) (subtypep other-class class))) classes)) ;;;; (defgeneric include-class-dependencies (class-type dynamic-class class-list &rest parameters) (:documentation "")) (defgeneric existing-subclass (class-type class-list) (:documentation "")) ;;; Support for dynamic classes based on the parameters for instantiation... ;;; ;;; Here is a quick history lesson: we've been doing this for shapes, since ;;; there was a massive amount of potential shape superclasses, and only a ;;; small subset were ever used for any given instance, and this was the ;;; cleanest and cutest approach... (defvar *parameter-dynamic-class-table* nil) (defun type->parameter-table (type) (cdr (assoc type *parameter-dynamic-class-table*))) (defun (setf type->parameter-table) (value type) (let ((it (assoc type *parameter-dynamic-class-table*))) (if it (setf (cdr it) value) (setf *parameter-dynamic-class-table* (append *parameter-dynamic-class-table* (list (cons type value)))))) (values value)) (defun parameter->dynamic-class (table parameter) (cdr (assoc parameter table))) (defun (setf parameter->dynamic-class) (value table parameter) (let ((it (assoc parameter table))) (if it (setf (cdr it) value) (let ((temp (cdr table)) (insert (list (cons parameter value)))) (setf (cdr insert) temp (cdr table) insert)))) (values value)) (defun table¶meter->dynamic-class (class-type parameter) (parameter->dynamic-class (type->parameter-table class-type) parameter)) (defun add-parameter->dynamic-class (class-type parameter &rest super-classes) (let* ((current-table (or (type->parameter-table class-type) (list (cons :remove :remove)))) (have-table? (not (eq (caar current-table) :remove)))) (dolist (super-class (ensure-list super-classes)) (let ((it (parameter->dynamic-class current-table parameter))) (if it (pushnew super-class it) (setf (parameter->dynamic-class current-table parameter) (list super-class))))) (unless have-table? (setf (type->parameter-table class-type) current-table))) (values nil)) (defun add-dynamic-class-for-parameters (class-type dynamic-class &rest parameters) (dolist (parameter (ensure-list parameters)) (add-parameter->dynamic-class class-type parameter dynamic-class))) #+Later (defun remove-parameter->dynamic-class (class-type parameter dynamic-class) (let ((primary-table (containers:item-at *parameter-dynamic-class-table* class-type))) (when (and primary-table (containers:item-at primary-table parameter)) (setf (containers:item-at primary-table parameter) (remove dynamic-class (containers:item-at primary-table parameter)))))) (defun empty-add-parameter->dynamic-class (class-type) (setf (type->parameter-table class-type) nil)) (defun empty-all-add-parameter->dynamic-class () (setf *parameter-dynamic-class-table* nil)) (defun dynamic-class-information () (loop for (type . data) in *parameter-dynamic-class-table* collect (list type (loop for (parameter . class) in data collect (list parameter class))))) (defmethod include-class-dependencies ((class-type (eql nil)) dynamic-class class-list &rest parameters) (declare (ignore dynamic-class class-list parameters))) (defmethod existing-subclass ((class-type (eql nil)) (class-list t)) (values nil)) (defun determine-dynamic-class (class-type dynamic-class &rest parameters) (let ((class-list (loop for parameter in parameters for keyword? = t then (not keyword?) when keyword? nconc (loop for class in (table¶meter->dynamic-class class-type parameter) when (or (not dynamic-class) (and dynamic-class (not (subtypep class dynamic-class)))) collect class)))) (setf class-list (apply #'include-class-dependencies class-type dynamic-class class-list parameters)) (when (and dynamic-class (not (some (lambda (class-name) (subtypep dynamic-class class-name)) class-list))) (setf class-list (nconc (list dynamic-class) class-list))) (setf class-list (delete-duplicates class-list)) (let ((it nil)) (cond ((setf it (existing-subclass class-type class-list)) it) (t (if (and (length-1-list-p class-list) (find-class (first class-list) nil)) (first class-list) (define-class nil class-list nil))))))) cl-containers-20170403-git/dev/eksl-priority-queue.lisp000066400000000000000000000043751306646076300227300ustar00rootroot00000000000000(in-package #:containers) ;;; Heap based queue using EKSL priority-queue ;;?? Needs a better name #+EKSL-PRIORITY-QUEUE (progn (defclass* priority-queue-heap (abstract-queue concrete-container iteratable-container-mixin) ((contents :initform nil :initarg :contents :accessor contents))) (defmethod make-container ((class (eql 'priority-queue-heap)) &rest args) (make-instance 'priority-queue-heap :contents (apply #'make-sorted-queue args))) (defun make-sorted-queue (&key (not-lessp-predicate #'<) (key #'identity) (initial-length 42)) (u:make-priority-queue not-lessp-predicate :key key :size initial-length)) (defmethod insert-item ((container priority-queue-heap) item) (u:priority-queue-insert item (contents container))) (defmethod find-item ((container priority-queue-heap) item) (u:priority-queue-find item (contents container))) (defmethod search-for-item ((container priority-queue-heap) item &key test key) (u:priority-queue-find item (contents container) :key key :test test)) (defmethod delete-item ((container priority-queue-heap) item) (u:priority-queue-delete item (contents container))) (defmethod delete-first ((container priority-queue-heap)) (u:priority-queue-pop (contents container))) ;; Should not be called on an empty queue... results might be undefined. (defmethod first-item ((container priority-queue-heap)) (u:priority-queue-head (contents container))) (defmethod empty-p ((container priority-queue-heap)) (u:priority-queue-empty-p (contents container))) (defmethod empty! ((container priority-queue-heap)) (u:priority-queue-empty (contents container)) (values)) (defmethod iterate-nodes ((container priority-queue-heap) fn) (u:priority-queue-map-in-priority-order (lambda (element index) (declare (ignore index)) (funcall fn element)) (contents container))) (defmethod size ((container priority-queue-heap)) (u:priority-queue-length (contents container))) (u:defcopy-methods priority-queue-heap :copy-all t) (u:make-load-form* priority-queue-heap)) cl-containers-20170403-git/dev/extra-stuff.lisp000066400000000000000000000003411306646076300212260ustar00rootroot00000000000000(defun determine-concrete-container-subclasses (root) (mapcar #'class-name (filter (lambda (class) (subtypep class 'concrete-container)) (subclasses (find-class root))))) cl-containers-20170403-git/dev/file-backed-table-container.lisp000066400000000000000000000055261306646076300241630ustar00rootroot00000000000000(in-package #:containers) (defclass* file-backed-table-container (table-container) ((pathspec nil ir) (size 0 a) (require-write (make-container 'list-container) r) ) (:documentation "This is a very half-assed class that pretends to store a table on disk. It doesn't support updating.") (:export-p t)) (defmethod save-row (column-names row out) (format out "~&\(~{~S ~}\)" (collect-elements column-names :transform (lambda (name) (slot-value row name))))) (defmethod save-table-header ((container file-backed-table-container) stream) (format stream "~&\(:prototype-name ~S :columns ~S\)" (class-name (prototype container)) (column-names container))) (defmethod load-table-header ((container file-backed-table-container) line) ;;?? STUB (values t)) (defmethod check-table-header ((container file-backed-table-container) line) ;;?? STUB (values t)) (defmethod save-changes ((container file-backed-table-container)) (let ((column-names (column-names container)) (write-header? nil)) (if (probe-file (pathspec container)) (check-table-header container (pathspec container)) (setf write-header? t)) (with-open-file (out (pathspec container) :if-exists :append :direction :output :if-does-not-exist :create) (let ((*print-right-margin* most-positive-fixnum)) (when write-header? (save-table-header container out)) (iterate-elements (require-write container) (lambda (row) (save-row column-names row out)))))) (empty! (require-write container))) (defmethod insert-record ((table file-backed-table-container) object) (insert-item (require-write table) object) (incf (size table)) (maybe-save-changes table)) (defmethod maybe-save-changes ((table file-backed-table-container)) (when (> (size (require-write table)) 10) (save-changes table))) (defmethod iterate-container ((container file-backed-table-container) fn) (save-changes container) (let ((first? t) (column-names (column-names container))) (u:map-lines-in-file (lambda (line) (if first? ;; skip header row (setf first? nil) ;; create element and call fn on it (funcall fn (create-record container column-names line)))) (pathspec container)))) (defmethod create-record ((container file-backed-table-container) (column-names list) (line string)) (let ((it (allocate-instance (prototype container)))) (loop for datum in (read-from-string line) for column in column-names do (setf (slot-value it column) datum)) it))cl-containers-20170403-git/dev/file-iterators.lisp000066400000000000000000000226701306646076300217200ustar00rootroot00000000000000(in-package #:containers) #| - file lines file forms string as characters string as words string as, e.g., paragraphs stemming |# (defclass* basic-stream-iterator (forward-iterator) ((stream nil i :reader iterator-stream) (close? nil r))) (defmethod initialize-instance :after ((object basic-stream-iterator) &key container) (setf (values (slot-value object 'stream) (slot-value object 'close?)) (open-file-for-iterator object container)) (advance object) ;; if garbage collected close the stream (funcall-if-exists 'care-when-finalized 'mopu object)) (defmethod finish ((iterator basic-stream-iterator)) (when (and (close? iterator) (streamp (iterator-stream iterator)) (open-stream-p (iterator-stream iterator))) (close (iterator-stream iterator)) (setf (slot-value iterator 'close?) nil))) (defmethod open-file-for-iterator ((object basic-stream-iterator) (filename string)) (values (open filename :if-does-not-exist :error :direction :input) t)) (defmethod open-file-for-iterator ((object basic-stream-iterator) (filename pathname)) (open-file-for-iterator object (namestring filename))) (defmethod open-file-for-iterator ((object basic-stream-iterator) (filename stream)) (values filename nil)) ;;; file-iterator ;;; ;;;?? assume that someone else is handling buffering for now... (defclass* file-iterator (basic-stream-iterator) ((current-char nil r))) (defmethod base-class-for-iteratee ((container pathname)) 'file-iterator) (defmethod move ((iterator file-iterator) (direction (eql :forward))) (advance iterator)) (defmethod advance ((iterator file-iterator)) (setf (slot-value iterator 'current-char) (read-char (iterator-stream iterator) nil :eof))) (defmethod current-element ((iterator file-iterator)) (current-char iterator)) (defmethod current-element-p ((iterator file-iterator)) (and (call-next-method) (not (eq (current-char iterator) :eof)))) (defmethod move-p ((iterator file-iterator) (direction (eql :forward))) (not (eq (current-char iterator) :eof))) ;;; file-line-iterator (defclass* file-line-iterator (basic-stream-iterator) ((current-line nil r))) (defmethod move ((iterator file-line-iterator) (direction (eql :forward))) (advance iterator)) (defmethod advance ((iterator file-line-iterator)) (setf (slot-value iterator 'current-line) (read-line (iterator-stream iterator) nil :eof))) (defmethod current-element ((iterator file-line-iterator)) (current-line iterator)) (defmethod current-element-p ((iterator file-line-iterator)) (and (call-next-method) (not (eq (current-line iterator) :eof)))) (defmethod move-p ((iterator file-line-iterator) (direction (eql :forward))) (not (eq (current-line iterator) :eof))) (defmethod class-for-contents-as ((contents pathname) (as (eql :lines))) 'file-line-iterator) ;;; file-form-iterator (defclass* file-form-iterator (basic-stream-iterator) ((current-form nil r))) (defmethod move ((iterator file-form-iterator) (direction (eql :forward))) (advance iterator)) (defmethod advance ((iterator file-form-iterator)) (setf (slot-value iterator 'current-form) (read (iterator-stream iterator) nil :eof))) (defmethod current-element ((iterator file-form-iterator)) (current-form iterator)) (defmethod current-element-p ((iterator file-form-iterator)) (and (call-next-method) (not (eq (current-form iterator) :eof)))) (defmethod move-p ((iterator file-form-iterator) (direction (eql :forward))) (not (eq (current-form iterator) :eof))) (defmethod class-for-contents-as ((contents pathname) (as (eql :forms))) 'file-form-iterator) ;;; delimited-iterator (defclass* delimited-iterator (forward-iterator) ((cache (make-array 20 :element-type 'character :fill-pointer 0 :adjustable t) r) (current-chunk nil r) (internal-iterator nil r) (element-characterizer 'metatilities:whitespacep ia) (skip-empty-chunks? t ia) (starting-element nil a))) (defclass* internal-iterator-mixin () ((iterator nil ir))) (defmethod initialize-instance :after ((object delimited-iterator) &key container &allow-other-keys) (setf (slot-value object 'internal-iterator) (make-internal-iterator object container)) (when (move-forward-p (internal-iterator object)) (move-forward (internal-iterator object))) (advance object)) (defmethod make-internal-iterator ((object delimited-iterator) container) (make-iterator container :iterator-class 'internal-iterator-mixin :iterator object)) (defgeneric characterize-element (iterator element) (:documentation "Examines element in the context of iterator and returns a value describing how to treat it. This can be one of: * nil or :appended - append element to the current chunk * t or :delimiter - complete the current chunk and start a new one \(ignore element\) * :ignored - act as if this element was never seen * :start-new - complete the current chunk and start a new one with this element ")) (defmethod characterize-element ((iterator delimited-iterator) (thing t)) (funcall (element-characterizer iterator) thing)) (defmethod move ((iterator delimited-iterator) (direction (eql :forward))) (advance iterator)) (defmethod move-internal ((iterator delimited-iterator) (direction (eql :forward))) (move-forward (internal-iterator iterator))) (defmethod advance ((iterator delimited-iterator)) (let ((internal (internal-iterator iterator))) (setf (fill-pointer (cache iterator)) 0) (when (starting-element iterator) (vector-push-extend (starting-element iterator) (cache iterator)) (setf (starting-element iterator) nil)) (loop while (move-forward-p internal) do (let ((element-is (characterize-element iterator (current-element internal)))) ;(format t "~%~A ~A" (current-element internal) element-is) (case element-is ((nil :appended) (vector-push-extend (current-element internal) (cache iterator))) ((t :delimiter) (if (skip-empty-chunks? iterator) (loop while (and (move-forward-p internal) (member (characterize-element iterator (current-element internal)) '(:ignored :delimiter t))) do ;(format t "~% '~A'" (current-element internal)) (move-internal iterator :forward)) (move-internal iterator :forward)) ;; leave loop (return)) (:ignored nil) (:start-new (setf (starting-element iterator) (current-element internal)) (move-internal iterator :forward) ;; leave loop (return)) (t (warn "Don't know how to ~S ~S" element-is (current-element internal))))) (move-forward internal)) (setf (slot-value iterator 'current-chunk) (combine-elements iterator)))) (defmethod combine-elements ((iterator delimited-iterator)) (format nil "~A" (coerce (cache iterator) 'string))) #+Experimental ;;?? trying to guarentee single calls to characterize-element (this doesn't work) (defmethod advance ((iterator delimited-iterator)) (let ((internal (internal-iterator iterator)) (first? t)) (setf (fill-pointer (cache iterator)) 0) (loop while (move-forward-p internal) do (when (characterize-element iterator (current-element internal)) (if (skip-empty-chunks? iterator) (loop while (or first? (and (move-forward-p internal) (characterize-element iterator (current-element internal)))) do (setf first? nil) (move-forward internal)) (move-forward internal)) (return)) (vector-push-extend (current-element internal) (cache iterator)) (move-forward internal)) (setf (slot-value iterator 'current-chunk) (coerce (cache iterator) 'string)))) (defmethod current-element ((iterator delimited-iterator)) (current-chunk iterator)) (defmethod current-element-p ((iterator delimited-iterator)) (and (call-next-method) (or (not (skip-empty-chunks? iterator)) (plusp (fill-pointer (cache iterator)))))) (defmethod move-p ((iterator delimited-iterator) (direction (eql :forward))) (or (move-p (internal-iterator iterator) direction) (plusp (size (cache iterator))))) (defclass* word-iterator (delimited-iterator) () (:default-initargs :element-characterizer 'metatilities:whitespacep)) (defclass* line-iterator (delimited-iterator) () (:default-initargs :element-characterizer (lambda (ch) (or (eq ch #\linefeed) (eq ch #\newline) (eq ch #\return))))) (defmethod class-for-contents-as ((contents t) (as (eql :lines))) 'line-iterator) (defmethod class-for-contents-as ((contents t) (as (eql :words))) 'word-iterator) #| (collect-elements (make-iterator "this is paragraph number one. this is paragraph number two. and this is paragraph number three." :treat-contents-as :lines)) (collect-elements (make-iterator #P"user-home:qt.lisp" :treat-contents-as :lines)) |# cl-containers-20170403-git/dev/flagged-issues.text000066400000000000000000000000501306646076300216720ustar00rootroot00000000000000Containers-readtable needs to be ported.cl-containers-20170403-git/dev/heaps.lisp000066400000000000000000000130551306646076300200640ustar00rootroot00000000000000(in-package #:containers) ;;; heap-container (defclass* heap-container (sorted-container-mixin vector-container container-uses-nodes-mixin) () (:default-initargs :sorter #'> :initial-size 0)) (defclass* heap-node (container-node-mixin) ((index nil ia))) (defmethod print-object ((node heap-node) stream) (print-unreadable-object (node stream :type t :identity nil) (format stream "~A" (element node)))) (defmethod l-child ((node heap-node) (heap heap-container)) (item-at heap (l-child-index node))) (defmethod r-child ((node heap-node) (heap heap-container)) (item-at heap (r-child-index node))) (defmethod heap-node-parent ((node heap-node) (heap heap-container)) (item-at heap (node-parent-index node))) (defmethod l-child-index ((node heap-node)) (1+ (ash (index node) 1))) (defmethod r-child-index ((node heap-node)) (ash (1+ (index node)) 1)) (defmethod node-parent-index ((node heap-node)) (ash (index node) -1)) (defmethod exchange-heap-nodes ((n1 heap-node) (n2 heap-node) (heap heap-container)) (item-at! heap n2 (index n1)) (item-at! heap n1 (index n2)) (let ((index (index n2))) (setf (index n2) (index n1)) (setf (index n1) index))) (defmethod make-node-for-container ((heap heap-container) (element t) &key) (when element (make-instance 'heap-node :element element :index 0))) ;;; Float the 'node' down the tree so the subtree ;;; rooted at 'node' obeys the heap property (defmethod heapify ((heap heap-container) (node heap-node)) (let ((largest (index node))) (when (and (< (l-child-index node) (size heap)) (funcall (sorter heap) (funcall (key heap) (element (l-child node heap)) ) (funcall (key heap) (element node)))) (setf largest (l-child-index node))) (when (and (< (r-child-index node) (size heap)) (funcall (sorter heap) (funcall (key heap) (element (r-child node heap))) (funcall (key heap) (element (item-at heap largest))))) (setf largest (r-child-index node))) (when (not (eq largest (index node))) (exchange-heap-nodes (item-at heap largest) node heap) (heapify heap (item-at heap largest)))) heap) (defmethod initialize-instance :after ((heap heap-container) &key) (loop for i from (floor (/ (size heap) 2)) downto 1 do (heapify heap (item-at heap (1- i))))) (defmethod biggest-item ((heap heap-container)) (unless (empty-p heap) (element (first-item heap)))) (defmethod delete-biggest-item ((heap heap-container)) (when (> (size heap) 0) (let ((max (first-item heap))) (exchange-heap-nodes (first-item heap) (last-item heap) heap) (delete-last heap) (heapify heap (first-item heap)) (setf (index max) nil) (element max)))) (defmethod delete-item ((heap heap-container) (node heap-node)) (labels ((sift (node) (when (and (/= 0 (index node)) (funcall (sorter heap) (element node) (element (heap-node-parent node heap)))) (exchange-heap-nodes node (heap-node-parent node heap) heap) (sift node)))) (let ((last (last-item heap)) (key (key heap))) (exchange-heap-nodes node last heap) (setf (index node) nil) (delete-last heap) (when (not (eq last node)) (cond ((and (/= 0 (index last)) (funcall (sorter heap) (funcall key (element last)) (funcall key (element (heap-node-parent last heap))))) (exchange-heap-nodes last (heap-node-parent last heap) heap) (sift last)) (t (heapify heap last)))))) (element node)) (defmethod insert-item ((heap heap-container) (node heap-node)) (let ((sorter (sorter heap)) (key (key heap))) (setf (index node) (size heap)) (call-next-method heap node) (labels ((find-spot (a-node) (when (and (> (index a-node) 0) (funcall sorter (funcall key (element node)) (funcall key (element (heap-node-parent a-node heap))))) (exchange-heap-nodes a-node (heap-node-parent a-node heap) heap) (find-spot a-node)))) (find-spot node)) (values heap node))) ;;; k-best-heap-container (defclass* k-best-heap-container (bounded-container-mixin heap-container) ((k :initform 1 :initarg :k :accessor k-best-number)) (:documentation "Stores the k *best* values where *best* is defined by sorter. This means that the item at the top of the heap is the *worst* item. So if you want the best items to be the largest items, make sure sorter is '<'.") (:default-initargs :sorter #'> :k 1)) (defmethod insert-item :around ((heap k-best-heap-container) item) (if (< (size heap) (k-best-number heap)) (call-next-method) (when (funcall (sorter heap) (funcall (key heap) (biggest-item heap)) (funcall (key heap) item)) ; item is better (delete-biggest-item heap) (call-next-method heap item)))) #+Test (defun k-best-heap-container-test () (let ((heap (make-container 'k-best-heap-container :k 3))) (loop for i in '(10 11 12 13 9 8 15 -1) do (insert-item heap i) (format t "HEAP = ~A~%" (collect-elements heap))))) #+Test (k-best-heap-container-test)cl-containers-20170403-git/dev/historical-notes.lisp000066400000000000000000000203321306646076300222470ustar00rootroot00000000000000(in-package #:containers) #| ;;; stack with a list (defclass* stack-using-list (abstract-stack contents-as-list-mixin) ((contents :initform nil :accessor contents ))) (defmethod first-item ((container abstract-stack)) (first (contents container))) (defmethod pop-item ((stack stack-using-list)) (pop (contents stack))) ;;; bag-list (defclass* bag-list (bag-container-abstract contents-as-list-mixin) ()) (defmethod delete-item ((container bag-list) item) (setf (contents container) (delete item (contents container))) item) ;;; bag-hash (defclass* bag-hash (bag-container-abstract contents-as-hashtable-mixin) ()) (defmethod delete-item ((container bag-hash) item) (remhash item (contents container)) item) (defmethod insert-item ((container contents-as-hashtable-mixin) item) (setf (gethash item (contents container)) item)) (defgeneric smallest-item (sorted-container-mixin)) (defgeneric biggest-item (sorted-container-mixin)) |# #| Container Notes u::abstract-container make-container size empty-p empty-container u::bounded-container-mixin total-size u::indexed-container-mixin (and associative-container-mixin) item-at item-at! u::iteratable-container-mixin iterate-container collect-elements (basic version using iterate-container) ? search-for-item (container item :key :test) ? first-match (container :key :test) u::findable-container-mixin ;;?? Needs key and test find-item (findable-container-mixin item) u::ordered-container-mixin (defgeneric first-item (ordered-container-mixin)) (defgeneric item-after (ordered-container-mixin item)) (defgeneric item-before (ordered-container-mixin item)) (defgeneric last-item (ordered-container-mixin)) insert-item insert-sequence insert-list u::sorted-container-mixin (defgeneric successor (sorted-container-mixin item)) (defgeneric predecessor (sorted-container-mixin item)) u::contents-as-hashtable-mixin collect-keys iterate-key-value u::abstract-queue dequeue enqueue == insert-item u::abstract-stack first-item (settable) pop-item push-item test (in bst, make part of searchable; make keyed part of searchable?) height (of a tree) delete-item delete-item-if iterate-key-value doesn't make sense for nested hash-tables, we should implement both nested and non-nested... get rid of empty, make everyone type empty-container or, better yet, empty! aided and unaided searching... I can search any iteratable container but I can search bst's fast. maybe find-item and search-for-item (the slower and more flexible one) hunt-for-item, lookup-item vs find-item ? append-item ? delete-last |# #| Todo ---- * Re-design class hierarchy * queue-on-container * create heap class and hide EKSL heap in it, then use this for heap based PQ * sets and bags need :test, :key in the constructor * the X-container adaptors have very similar implementation, make this a sub-class (adaptive-container-mixin) to handle most of the pattern. * sparse-array should use associative-container (nested hash tables) and be able to iterate container * arrays should allow for initial-contents * add associative-arrays * add initial-element-fn * sparse-array-container should use contents-as-hashtable-mixin (and have size the amount in use?) * restore regular associative-container and created nested-associative-container * doubly-linked-list * add methods for working with the end of an ordered-container (and a new class) * break ordered container into pieces corresponding to efficiency classes * delete-first, delete-last, append-item and so on * generic operations for standard lisp types? (container ops are destructive... makes this hard) ** fix / improve bags and add sets ** we should have stack-container and bag-container and so on. ** remove smallest-item and biggest-item (replace with first-item and last-item) ** dump generic-iteratable-container-mixin * rework observable stuff and add to eksl-utilities * copy-container * samep (good use of forward-iterators) * generic algoritms (e.g., sort, merge, find...)?? * instead of insert-list, insert-sequence, and so on... have insert-object and dispatch on it More esoteric data structures Fibonacci heaps (and other heaps) etc. Less esoteric data structures ?? bag-container / set-container using lists, hash-tables or other things. The problem is that the bag/set-container seens to require specialization on bag/set. The other problem is that a bag-container using a hash-table should implement a fast find-item rather than the iterative search-for-item. |# #| Do we want to add assertions and such (use a parameter or a mixin) Westy's slow-mixin Look at various Lisp list operations (e.g., count, replace, and so on) and see if they would make sense for any sorts of containers. Setf's |# #| From EKSL priority queue Copy-queue queue-length priority-queue-head-or-nil ; = front unless queue is empty -> nil priority-queue-delete priority-queue-find priority-queue-map-in-priority-order priority-queue-map-in-heap-order priority-queue-elements print-priority-queue-elements do-priority-queue reorder-priority-queue)) #+Ignore (defmacro declare-inline (function-names) (dolist (name function-names) `(declaim (inline ,name)))) (defmacro declaim-inline (function-name) `(declaim (inline ,function-name))) |# (in-package #:u) (defun test-container-class (container-class &rest args) (let ((c (apply #'make-container container-class args))) (test) )) (defun container )) (defun test-basic-container-operations (class) (let ((c (make-container class))) (insert-item c 1) (insert-item c 2) (insert-item c 3) (ensure (= (size c) 3)) (empty! c) (ensure (= (size c) 0)) (ensure (empty-p c)) (insert-list c '(2 3)) (ensure (= (size c) 2)))) (test-basic-container-operations 'dlist-container) (test-basic-container-operations 'priority-queue-heap) (mapc (lambda (c) (print c) (test-basic-container-operations c)) (DETERMINE-CONCRETE-CONTAINER-SUBCLASSES 'ordered-container-mixin)) (SET-CONTAINER BAG-CONTAINER STACK-CONTAINER PRIORITY-QUEUE-HEAP DLIST-CONTAINER BASIC-QUEUE LIST-CONTAINER ALIST-CONTAINER SPARSE-ARRAY-CONTAINER RING-BUFFER VECTOR-CONTAINER ARRAY-CONTAINER ABSTRACT-FORCE-SIMULATOR-DOMAIN::FORCE-FLOW-GRID MBR HEAP-CONTAINER BINARY-SEARCH-TREE RED-BLACK-TREE PRIORITY-QUEUE-ON-CONTAINER bag/set-container ASSOCIATIVE-CONTAINER KEYED-ASSOCIATIVE-CONTAINER) |# #| (setf a (make-container 'alist-container)) (setf (item-at a :a :b) 1 (item-at a :b :c) 2 (item-at a :c :d) 3 (item-at a :d :e) 4) (delete-item-at a :a :b) (iterate-key-value a (lambda (k v) (format t "~%~A ~A" k v))) (iterate-keys a (lambda (k) (format t "~%~A" k))) (setf a (make-container 'alist-container)) (setf (item-at a :a) 1 (item-at a :b) 2 (item-at a :c) 3 (item-at a :d) 4) (delete-item-at a :a) (iterate-key-value a (lambda (k v) (format t "~%~A ~A" k v))) (iterate-keys a (lambda (k) (format t "~%~A" k))) |# #| Perhaps useful for documentation (let ((c-1 (make-container 'associative-container)) (c-2 (make-container 'associative-container :initial-element 2)) (c-3 (make-container 'associative-container :initial-element (random 10))) (c-4 (make-container 'associative-container :initial-element-fn (lambda () (random 10))))) (loop for c in (list c-1 c-2 c-3 c-4) for name in (list "Basic Table" "Initial-element" "Random Element" "Element Function") do (format t "~%~%~A:" name) (setf (item-at c :a) 1) (format t "~%We get out what we put in.") (format t "~%(item-at c :a) ==> ~A" (item-at c :a)) (format t "~%What do we get when we don't put anything in?") (format t "~%(item-at c :b) ==> ~A" (item-at c :b)) (format t "~%We get the same thing each time ~ (even if we didn't add it ourselves).") (format t "~%(item-at c :b) ==> ~A" (item-at c :b)) (format t "~%What happens if we look somewhere else? ~ (why initial-element-fn exists).") (format t "~%(item-at c :c) ==> ~A" (item-at c :c)))) |#cl-containers-20170403-git/dev/immutable-containers.lisp000066400000000000000000000016471306646076300231120ustar00rootroot00000000000000 (in-package #:containers) (defclass* immutable-keys-mixin () "Keys may not be added or changed after the container is created." ((allow-mutation? nil ia)) (:export-p t) :export-slots) (defmethod item-at! :around ((container immutable-keys-mixin) value &rest indexes) (declare (dynamic-extent indexes)) (when (and (completely-created? container) (not (allow-mutation? container))) (unless (key-exists-p container indexes) (error 'key-does-not-exist-error))) (call-next-method) value) #| (lift:deftestsuite test-immutable-keys-mixin () ()) (lift:addtest (test-immutable-keys-mixin) foo (let ((c (make-container '(immutable-keys-mixin alist-container)))) (lift:ensure-error (setf (item-at c :a) 2)))) (lift:addtest (test-immutable-keys-mixin) bar (let ((c (make-container '(alist-container)))) (lift:ensure-error (setf (item-at c :a) 2)))) |#cl-containers-20170403-git/dev/iterator-api.lisp000066400000000000000000000030451306646076300213620ustar00rootroot00000000000000(in-package #:containers) (defgeneric make-iterator (iteratee &rest args &key iterator-class &allow-other-keys) (:documentation "")) (defgeneric print-iterator (iterator stream) (:documentation "")) (defgeneric finish (iterator) (:documentation "Tell Lisp that you are done with this iterator. Further calls to current-element, etc. will have unspecified behavior and may cause an error.")) (defgeneric move-p (iterator direction) (:documentation "")) (defgeneric element-passes-p (iterator) (:documentation "") (:method-combination and)) (defgeneric move (iterator direction) (:documentation "")) (defgeneric base-class-for-iteratee (container) (:documentation "")) (defgeneric class-for-contents-as (contents as) (:documentation "")) (defgeneric current-element (thing) (:documentation "")) (defgeneric current-element-p (iterator) (:documentation "")) (defgeneric setup-initial-container (object) (:documentation "")) (defgeneric advance (iterator) (:documentation "")) (defgeneric iterate-forward (iterator function) (:documentation "")) (defgeneric make-internal-iterator (object container) (:documentation "")) (defgeneric move-forward (iterator) (:documentation "")) (defgeneric move-forward-to-next-element (iterator) (:documentation "")) (defgeneric move-internal (iterator direction) (:documentation "")) (defgeneric next-element (iterator) (:documentation "")) (defgeneric open-file-for-iterator (object filename) (:documentation "")) (defgeneric reset (iterator) (:documentation ""))cl-containers-20170403-git/dev/iterators.lisp000066400000000000000000000300751306646076300210010ustar00rootroot00000000000000(in-package #:cl-containers) #| IF we were going to re-write, would we write collect / iterate in terms of iterators or vis verso?! reset size hard to do generally class hierarchy isn't quite right for generators yet this isn't quite the right command set forward, backward, both costs using for multi-container transforms, etc. ??does it start on the first item or off the end of the container... I'm confused about how to integrate starting off the end with filters, etc. if I call move-forward-p, then I have to check that the next-element passes. I could save the current element (side effects?) and move to the next with move-forward-p and then really move when we call move... Sounds tricky and ke a lot of bookkeeping. Suppose I start at the first element (if any). Then I need a way to know that I'm on an element. arrays other containers ordered, etc. random-number-generators |# #| element returns current-element and allows for side-effects current-element only does the access (used, for example, in unique-value-iterator-mixin |# (defconstant +iterator-before-beginning+ :pre) (defconstant +iterator-after-end+ :post) (metatilities:defcondition basic-iterator-condition () ((iterator nil ir)) (:export-p t) (:export-slots-p t)) (metatilities:defcondition no-current-element-error (basic-iterator-condition error) () (:export-p t) (:export-slots-p t)) (defclass* abstract-generator () ((iterator-position +iterator-before-beginning+ r))) (defmethod finish ((iterator abstract-generator)) (values)) (defclass* basic-iterator (abstract-generator) ((initial-container nil ir :initarg :container) (iterating-container nil r))) (defmethod initialize-instance :after ((object basic-iterator) &key &allow-other-keys) (setup-initial-container object)) (defmethod setup-initial-container ((object basic-iterator)) (setf (slot-value object 'iterating-container) (if (typep (initial-container object) 'uses-contents-mixin) (contents (initial-container object)) (initial-container object)))) (defmethod print-iterator ((iterator abstract-generator) stream) (declare (ignore stream)) (values)) (defmethod reset :before ((iterator abstract-generator)) (setf (slot-value iterator 'iterator-position) +iterator-before-beginning+)) (defmethod move-p ((iterator abstract-generator) direction) (declare (ignore direction)) (values nil)) (defmethod print-object ((object abstract-generator) stream) (print-unreadable-object (object stream :type t :identity t) (print-iterator object stream))) #+Ignore (defmethod size ((iterator basic-iterator)) ;; a decent general method (size (container iterator))) (defmethod print-iterator ((iterator basic-iterator) stream) (format stream "~D" (current-element-p iterator))) (defclass* forward-iterator (basic-iterator iteratable-container-mixin) ()) (defmethod iterate-container ((iterator forward-iterator) fn) (iterate-forward iterator fn)) (defmethod iterate-nodes ((iterator forward-iterator) fn) (iterate-forward iterator fn)) (defmethod empty-p ((object forward-iterator)) (not (move-forward-p object))) (defmethod element ((iterator abstract-generator)) (current-element iterator)) (defmethod next-element ((iterator abstract-generator)) (move-forward iterator) (current-element iterator)) (defmethod current-element-p ((iterator basic-iterator)) (null (iterator-position iterator))) (defmethod element :around ((iterator abstract-generator)) (unless (current-element-p iterator) (error 'no-current-element-error :iterator iterator)) (call-next-method)) (defmethod move :around ((iterator basic-iterator) direction) (cond ((iterator-position iterator) (setf (slot-value iterator 'iterator-position) nil)) (t (call-next-method))) (unless (move-p iterator direction) (setf (slot-value iterator 'iterator-position) +iterator-after-end+))) (defun move-forward-p (iterator) (move-p iterator :forward)) (defmethod move-forward ((iterator forward-iterator)) (move iterator :forward)) (defmethod iterate-forward ((iterator basic-iterator) function) (loop while (move-forward-p iterator) do (when (current-element-p iterator) (funcall function (element iterator))) (move-forward iterator))) ;;; transforming-iterator-mixin (defclass* transforming-iterator-mixin () ((transform nil ir) (transformed-element nil r) (compute-element? t r))) (defmethod current-element :around ((iterator transforming-iterator-mixin)) (cond ((compute-element? iterator) (setf (slot-value iterator 'compute-element?) nil (slot-value iterator 'transformed-element) (funcall (transform iterator) (call-next-method)))) (t (transformed-element iterator)))) (defmethod move :after ((iterator transforming-iterator-mixin) direction) (declare (ignorable direction)) (setf (slot-value iterator 'compute-element?) t)) ;;; filtered-iterator-mixin (defclass* basic-filtered-iterator-mixin () ()) (defmethod move :after ((iterator basic-filtered-iterator-mixin) (direction (eql :forward))) (move-forward-to-next-element iterator)) (defclass* filtered-iterator-mixin (basic-filtered-iterator-mixin) ((filter nil ir))) (defmethod element-passes-p and ((iterator filtered-iterator-mixin)) (funcall (filter iterator) (current-element iterator))) (defmethod initialize-instance :around ((object filtered-iterator-mixin) &key) (prog1 (call-next-method) (move-forward-to-next-element object))) (defmethod move-forward-to-next-element ((iterator basic-iterator)) (loop while (and (move-p iterator :forward) (or (not (current-element-p iterator)) (not (element-passes-p iterator)))) do (move iterator :forward))) ;;; unique-value-iterator-mixin (defclass* unique-value-iterator-mixin (basic-filtered-iterator-mixin test-container-mixin) ((visited nil ir))) (defmethod initialize-instance :after ((object unique-value-iterator-mixin) &key) (setf (slot-value object 'visited) (make-container 'simple-associative-container :test (test object)))) (defmethod element-passes-p and ((iterator unique-value-iterator-mixin)) (not (item-at (visited iterator) (current-element iterator)))) (defmethod element :around ((iterator unique-value-iterator-mixin)) (let ((element (call-next-method))) (setf (item-at-1 (visited iterator) element) t) element)) #| (defclass* test-iteration (filtered-iterator-mixin unique-value-iterator-mixin list-iterator) ()) (let ((l '(2 3 4 5 5 5 5 6 7))) (iterate-forward (make-instance 'test-iteration :pointer l :filter #'oddp ) #'print) (values)) |# ;;; circular iterators -- they just don't stop (defclass* circular-iterator-mixin () ()) (defmethod move-p ((iterator circular-iterator-mixin) (direction (eql :forward))) (unless (call-next-method) (reset iterator) ;;?? perhaps an ugly hack?! (move-forward iterator)) (values t)) #+Test (let ((i (make-iterator '(1 2 3) :circular t))) (loop repeat 10 do (move-forward i) (print (current-element i)))) #+Test (let ((i (make-iterator '(1 2 3) :circular t))) (loop repeat 10 do (print (next-element i)))) ;;; list-iterator (defclass* list-iterator (forward-iterator) ()) (defmethod reset ((iterator list-iterator)) (setup-initial-container iterator) iterator) (defmethod move ((iterator list-iterator) (direction (eql :forward))) (setf (slot-value iterator 'iterating-container) (rest (iterating-container iterator))) (values)) (defmethod current-element ((iterator list-iterator)) (first (iterating-container iterator))) (defmethod move-p ((iterator list-iterator) (direction (eql :forward))) (not (null (iterating-container iterator)))) ;;; arrays (defclass* array-iterator (forward-iterator) ((index 0 ir))) (defmethod reset ((iterator array-iterator)) (setf (slot-value iterator 'index) 0) iterator) (defmethod move ((iterator array-iterator) (direction (eql :forward))) (incf (slot-value iterator 'index)) (values)) (defmethod current-element-p ((iterator array-iterator)) (and (call-next-method) (< (index iterator) (size (iterating-container iterator))))) (defmethod current-element ((iterator array-iterator )) (row-major-aref (iterating-container iterator) (index iterator))) (defmethod move-p ((iterator array-iterator ) (direction (eql :forward))) (< (index iterator) (size (iterating-container iterator)))) ;;; hash-table-iterator (defclass* hash-table-iterator (list-iterator) ()) (defmethod initialize-instance :after ((object hash-table-iterator) &key) (reset object)) (defmethod reset ((iterator hash-table-iterator)) (setf (slot-value iterator 'iterating-container) (collect-elements (initial-container iterator))) iterator) ;;; make-iterator (defmethod make-iterator (iteratee &rest args &key (iterator-class nil) &allow-other-keys) (apply #'make-instance (or (metatilities:apply-if-exists 'determine-iterator-class 'cl-containers iteratee iterator-class args) iterator-class) :container iteratee args)) (defmethod make-iterator ((iteratee basic-iterator) &rest args &key &allow-other-keys) (when args (warn "make-iterator not using args with ~a, ~a" iteratee args)) iteratee) ;;; some generators (defun make-generator (&rest args &key (generator-class nil) &allow-other-keys) (apply #'make-instance (or (apply-if-exists 'determine-generator-class 'cl-containers generator-class args) generator-class) args)) ;;; sequences (defclass* basic-generator (forward-iterator) ()) (defclass* arithmetic-sequence-generator (basic-generator) ((start 0 ir) (by 1 ir) (element nil r))) (defmethod initialize-instance :after ((object arithmetic-sequence-generator) &key) (setf (slot-value object 'element) (start object))) (defmethod move ((iterator arithmetic-sequence-generator) (direction (eql :forward))) (incf (slot-value iterator 'element) (by iterator))) (defmethod move-p ((iterator arithmetic-sequence-generator) (direction (eql :forward))) (values t)) (defmethod current-element ((iterator arithmetic-sequence-generator)) (slot-value iterator 'element)) (defclass* finite-arithmetic-sequence-generator (arithmetic-sequence-generator) ((end 0 ir))) (defmethod move-p ((iterator finite-arithmetic-sequence-generator) (direction (eql :forward))) (<= (current-element iterator) (end iterator))) #| (collect-elements (make-generator :end 10 :start 5 :generator-class 'finite-arithmetic-sequence-generator)) (collect-elements (make-generator :end 10 :start 5)) (collect-elements (make-iterator '(1 2 3) :iterator-class 'list-iterator)) (collect-items (make-iterator '(1 2 3))) (move-forward-p ccl:!) (move-forward ccl:!) (current-element-p ccl:!) (current-element ccl:!) (compute-applicable-methods #'move-forward-p (list ccl:!)) (collect-elements (make-generator :end 10 :start 5 :transform #'u:square)) (subtypep 'finite-arithmetic-sequence-generator 'abstract-generator) (remove-redundant-classes '(finite-arithmetic-sequence-generator arithmetic-sequence-generator transforming-iterator-mixin abstract-generator)) |# ;;; map-containers ;;?? very consy (defun map-containers (fn &rest containers) (let ((iterators (mapcar #'make-iterator containers))) (loop while (every #'move-forward-p iterators) do (apply fn (mapcar #'current-element iterators)) (mapc #'move-forward iterators)))) (defun collect-containers (fn &rest containers) (let ((result nil)) (apply #'map-containers (lambda (&rest args) (push (apply fn args) result)) containers) (nreverse result))) (defmacro with-iterator ((var source &rest args) &body body) `(let (,var) (unwind-protect (progn (setf ,var (make-iterator ,source ,@args)) ,@body) (when ,var (finish ,var))))) cl-containers-20170403-git/dev/lists.lisp000066400000000000000000000723641306646076300201320ustar00rootroot00000000000000(in-package #:containers) ;;; List Container (defmethod insert-list ((container list-container) list) (setf (contents container) (append (contents container) list)) (values list)) (defmethod first-element ((container list-container)) (first-element (contents container))) (defmethod (setf first-element) (value (container list-container)) (setf (first-element (contents container)) value)) (defmethod delete-item ((container list-container) item) (setf (slot-value container 'contents) (delete item (contents container) :count 1 :test (test container))) (values item)) (defmethod find-item ((container list-container) item) (warn "find-item for list-containers is obsolete, use the semantically slower 'search-for-item' instead.") (search-for-item container item)) (defmethod delete-first ((container list-container)) (prog1 (first (contents container)) (setf (slot-value container 'contents) (rest (contents container))))) (defmethod nth-element ((container list-container) (index integer)) (nth index (contents container))) (defmethod item-at ((container list-container) &rest indexes) (declare (dynamic-extent indexes)) (elt (contents container) (first indexes))) (defmethod print-container ((container list-container) &optional (stream *standard-output*)) (prin1 (contents container) stream) container) (defmethod last-element ((container list-container)) (last-element (contents container))) (defmethod (setf last-element) (value (container list-container)) (setf (last-element (contents container)) value)) ;;; sorted-list-container (defclass* sorted-list-container (sorted-container-mixin list-container concrete-container) "A list container that keeps its items sorted as needed. This uses 'sort' so it best for small containers." ((dirty? nil r) (stable? nil ia)) (:export-slots stable?) (:export-p t)) (defmethod set-dirty-flag ((container sorted-list-container) flag) (setf (slot-value container 'dirty?) flag)) (defmethod clean-up ((container sorted-list-container)) (when (dirty? container) (set-dirty-flag container nil) (setf (contents container) (if (stable? container) (stable-sort (contents container) (sorter container) :key (key container)) (sort (contents container) (sorter container) :key (key container)))))) (defmethod insert-list ((container sorted-list-container) (list t)) (set-dirty-flag container t) (call-next-method)) (defmethod insert-item ((container sorted-list-container) (item t)) (set-dirty-flag container t) (call-next-method)) (defmethod delete-item ((container sorted-list-container) (item t)) (set-dirty-flag container t) (call-next-method)) (defmethod first-element ((container sorted-list-container)) (clean-up container) (call-next-method)) (defmethod (setf first-element) (value (container sorted-list-container)) (declare (ignore value)) (clean-up container) (call-next-method)) (defmethod delete-first ((container sorted-list-container)) (clean-up container) (call-next-method)) (defmethod item-at ((container sorted-list-container) &rest indexes) (declare (dynamic-extent indexes)) (clean-up container) (elt (contents container) (first indexes))) (defmethod print-container ((container sorted-list-container) &optional (stream *standard-output*)) (declare (ignore stream)) (clean-up container) (call-next-method)) (defmethod iterate-nodes ((container sorted-list-container) fn) (declare (ignore fn)) (clean-up container) (call-next-method)) (defmethod collect-elements ((container sorted-list-container) &key filter transform) (declare (ignore filter transform)) (clean-up container) (call-next-method)) (defmethod ensure-sorted ((container sorted-list-container)) (clean-up container) container) (defmethod force-sort ((container sorted-list-container)) (setf (slot-value container 'dirty?) t) container) ;;; dlist-container :: doubly-linked-list container (defclass* dlist-container-node (container-node-mixin) ((next-item nil ia) (previous-item nil ia) (element nil)) (:documentation "A double-linked list node")) (defmethod print-object ((node dlist-container-node) stream) (print-unreadable-object (node stream :type t :identity t) (format stream "~A" (element node)))) (defclass* dlist-container (ordered-container-mixin iteratable-container-mixin container-uses-nodes-mixin concrete-container) ;;?? nil is not a dlist-container-node so the type clause is bogus ((first-element nil ia #+(or) :type #+(or) dlist-container-node) (last-element nil ia #+(or) :type #+(or) dlist-container-node) (size 0 ia)) (:documentation "A double-linked list")) (defmethod make-node-for-container ((container dlist-container) (item t) &rest args) (declare (dynamic-extent args)) (apply #'make-instance 'dlist-container-node :element item args)) (defmethod empty! ((container dlist-container)) (setf (slot-value container 'size) 0) (setf (slot-value container 'first-element) nil (slot-value container 'last-element) nil)) (defmethod insert-item ((list dlist-container) (node dlist-container-node)) (insert-item-after list (last-element list) node)) (defmethod insert-item-after ((list dlist-container) node item) (insert-item-after list node (make-node-for-container list item))) (defmethod insert-item-after ((list dlist-container) node (new-node dlist-container-node)) (declare (ignore node)) (setf (first-element list) new-node (last-element list) new-node) (setf (size list) 1) list) (defmethod insert-item-after ((list dlist-container) (node dlist-container-node) item) (insert-item-after list node (make-node-for-container list item))) (defmethod insert-item-after ((list dlist-container) (node dlist-container-node) (new-node dlist-container-node)) (setf (next-item new-node) (next-item node)) (setf (previous-item new-node) node) (if (eq node (last-element list)) (setf (last-element list) new-node) (setf (previous-item (next-item node)) new-node)) (setf (next-item node) new-node) (incf (size list)) list) (defmethod insert-item-before ((list dlist-container) node item) (declare (ignore node)) (insert-item list item)) (defmethod insert-item-before ((list dlist-container) (node dlist-container-node) item) (insert-item-before list node (make-node-for-container list item))) (defmethod insert-item-before ((list dlist-container) (node dlist-container-node) (new-node dlist-container-node)) (setf (next-item new-node) node) (setf (previous-item new-node) (previous-item node)) (if (eq node (first-element list)) (setf (first-element list) new-node) (setf (next-item (previous-item node)) new-node)) (setf (previous-item node) new-node) (incf (size list)) list) (defmethod delete-item-after ((list dlist-container) (node dlist-container-node)) (cond ((not (equal (last-element list) node)) (let ((next (next-item node))) (if (eq next (last-element list)) (setf (last-element list) node) (setf (previous-item (next-item next)) node)) (setf (next-item node) (next-item next)) (decf (size list)) (values (element next) t))) (t (values nil nil)))) (defmethod delete-item-before ((list dlist-container) (node dlist-container-node)) (cond ((not (equal (first-element list) node)) (let ((previous (previous-item node))) (if (eq previous (first-element list)) (setf (first-element list) node) (setf (next-item (previous-item previous)) node)) (setf (previous-item node) (previous-item previous)) (decf (size list)) (values (element previous) t))) (t (values nil nil)))) (defmethod delete-item ((list dlist-container) item) (iterate-nodes list (lambda (node) (when (funcall (test list) (element node) item) (cond ((eq node (last-element list)) (cond ((eq node (first-element list)) (setf (first-element list) nil) (setf (last-element list) nil) (decf (size list)) (element node)) (t (delete-item-after list (previous-item node))))) (t (delete-item-before list (next-item node)))))))) (defmethod delete-item ((list dlist-container) (node dlist-container-node)) (delete-item list (element node))) (defmethod iterate-nodes ((list dlist-container) fn) (loop repeat (size list) with node = (first-element list) do (funcall fn node) (setf node (next-item node))) list) (defmethod item-at ((list dlist-container) &rest indexes) (declare (dynamic-extent indexes)) (if (>= (first indexes) (size list)) (error "index out of bounds.") (let ((item (first-element list))) (loop repeat (first indexes) do (setf item (next-item item))) item))) (defmethod replace-item ((list dlist-container) (node dlist-container-node) item &key (length 1) finish-item) (declare (ignore finish-item)) (replace-item list node (make-container 'dlist-container-node item) :length length)) (defmethod replace-item ((list dlist-container) (node dlist-container-node) (start-item dlist-container-node) &key (length 1) (finish-item start-item)) (let ((previous-item (previous-item node)) (start-to-finish (loop for counter from 0 with node = start-item do (if (eq node finish-item) (return counter) (setf node (next-item node)))))) (setf (previous-item start-item) previous-item) (if (not (equal node (first-element list))) (setf (next-item previous-item) start-item) (setf (first-element list) start-item)) (loop for i from 1 to length with next = node do (cond ((and (eq next (last-element list)) (/= i length)) (decf (size list) (- (1- i) start-to-finish)) (setf (next-item finish-item) (next-item next)) (setf (last-element list) finish-item) (return list)) ((= i length) (decf (size list) (- (1- i) start-to-finish)) (setf (next-item finish-item) (next-item next)) (if (eq next (last-element list)) (setf (last-element list) finish-item) (setf (previous-item (next-item next)) finish-item)) (return list)) (t (setf next (next-item next))))))) (defmethod successor ((container dlist-container) (node dlist-container-node)) (next-item node)) (defmethod predecessor ((container dlist-container) (node dlist-container-node)) (previous-item node)) ;;; sorted-dlist-container (defclass* sorted-dlist-container (sorted-container-mixin dlist-container) () (:documentation "A persistently sorted double-linked list") (:default-initargs :size 0) (:export-p t)) (defmethod iterate-nodes-about-node ((list sorted-list-container) (node dlist-container-node) left-fn right-fn) (iterate-left-nodes list node left-fn) (iterate-right-nodes list node right-fn)) (defmethod iterate-nodes-about-node ((list sorted-list-container) (item i-know-my-node-mixin) left-fn right-fn) (iterate-nodes-about-node list (my-node item) left-fn right-fn)) (defmethod iterate-nodes-about-node ((list sorted-list-container) (item t) left-fn right-fn) (let ((it (search-for-node* list item :test #'eq :key #'element))) (when it (iterate-nodes-about-node list it left-fn right-fn)))) (defmethod insert-item ((list sorted-dlist-container) (node dlist-container-node)) (insert-item-ordered list node)) (defmethod insert-item-ordered-about-node ((list sorted-dlist-container) (node dlist-container-node) (new-node dlist-container-node)) (when (= (size list) 0) (setf (first-element list) new-node (last-element list) new-node (size list) 1) (return-from insert-item-ordered-about-node list)) (with-slots (key sorter test) list (let ((new-key (funcall key (element new-node)))) (if (and (previous-item node) (funcall sorter new-key (funcall key (element (previous-item node))))) (iterate-left-nodes list node (lambda (n) (let ((current-key (funcall key (element n)))) (declare (dynamic-extent current-key)) (cond ((funcall test (element new-node) (element n)) (return-from insert-item-ordered-about-node list)) ((not (funcall sorter new-key current-key)) (insert-item-after list n new-node) (return-from insert-item-ordered-about-node list)))))) (iterate-right-nodes list node (lambda (n) (let ((current-key (funcall key (element n)))) (declare (dynamic-extent current-key)) (cond ((funcall test (element new-node) (element n)) (return-from insert-item-ordered-about-node list)) ((funcall sorter new-key current-key) (insert-item-before list n new-node) (return-from insert-item-ordered-about-node list))))))))) ;; If we make it here, then this is the last item of the list... (setf (next-item new-node) (next-item (last-element list)) (next-item (last-element list)) new-node (previous-item new-node) (last-element list) (last-element list) new-node) (incf (size list)) (values list)) (defmethod insert-item-ordered-about-node ((list sorted-dlist-container) (node t) (new-node dlist-container-node)) (if (= (size list) 0) (setf (first-element list) new-node (last-element list) new-node (size list) 1) (error "insert-item-ordered-about-node called with nil node and non-empty container"))) (defmethod insert-item-ordered-about-node ((list sorted-dlist-container) (node t) (new-node t)) (insert-item-ordered-about-node list node (make-node-for-container list new-node))) (defmethod insert-item-ordered ((list sorted-dlist-container) (new-node dlist-container-node)) (when (= (size list) 0) (setf (first-element list) new-node (last-element list) new-node (size list) 1) (return-from insert-item-ordered list)) (with-slots (key sorter test) list (let ((new-key (funcall key (element new-node)))) (iterate-nodes list (lambda (n) (let* ((current-key (funcall key (element n)))) (cond ((funcall test new-key current-key) (return-from insert-item-ordered list)) ((funcall sorter new-key current-key) (insert-item-before list n new-node) (return-from insert-item-ordered list)))))))) ;; If we make it here, then this is the last item of the list... (setf (next-item new-node) (next-item (last-element list)) (next-item (last-element list)) new-node (previous-item new-node) (last-element list) (last-element list) new-node) (incf (size list)) (values list)) (defmethod insert-item-ordered ((list sorted-dlist-container) (new-node t)) (insert-item-ordered list (make-node-for-container list new-node))) (defmethod delete-item ((list sorted-dlist-container) item) (with-slots (key sorter test) list (let ((item-key (funcall key item))) (iterate-nodes list #'(lambda (node) (let ((current-key (funcall key (element node)))) (when (funcall test current-key item-key) (cond ((eq node (last-element list)) (cond ((eq node (first-element list)) (setf (first-element list) nil) (setf (last-element list) nil) (decf (size list)) (element node)) (t (delete-item-after list (previous-item node))))) (t (delete-item-before list (next-item node))))) ;; Quick out if the item isn't actually in the container: (when (funcall sorter item-key current-key) (return-from delete-item list)))))))) (defmethod delete-item ((list sorted-dlist-container) (item i-know-my-node-mixin)) (let ((node (my-node item))) (declare (dynamic-extent node)) (cond ((eq node (last-element list)) (cond ((eq node (first-element list)) (setf (first-element list) nil) (setf (last-element list) nil) (decf (size list)) (element node)) (t (delete-item-after list (previous-item node))))) (t (when (null (next-item node)) (break)) (delete-item-before list (next-item node)))))) (defmethod force-sort ((list sorted-dlist-container)) list) (defmethod ensure-sorted ((list sorted-dlist-container)) list) (defmethod left-node-for-item ((list sorted-dlist-container) (item t)) (with-slots (key sorter test) list (let ((new-key (funcall key item))) (cond ((= (size list) 0) (values nil)) ((and (= (size list) 1) (not (funcall sorter new-key (funcall key (element (first-element list)))))) (values (first-element list))) (t (iterate-nodes list (lambda (n) (let* ((current-key (funcall key (element n)))) (declare (dynamic-extent current-key)) (when (or (funcall test new-key current-key) (funcall sorter new-key current-key)) (return-from left-node-for-item (previous-item n)))))) (values (last-element list))))))) (defmethod right-node-for-item ((list sorted-dlist-container) (item t)) (with-slots (key sorter test) list (let ((new-key (funcall key item))) (cond ((= (size list) 0) (values nil)) ((and (= (size list) 1) (funcall sorter new-key (funcall key (element (first-element list))))) (values (first-element list))) (t (iterate-nodes list (lambda (n) (let* ((current-key (funcall key (element n)))) (declare (dynamic-extent current-key)) (when (or (funcall test new-key current-key) (funcall sorter new-key current-key)) (return-from right-node-for-item n))))) (values nil)))))) (defmethod left-and-right-nodes-for-item ((list sorted-dlist-container) (item t)) (with-slots (key sorter test) list (let ((new-key (funcall key item))) (cond ((= (size list) 0) (values nil nil)) ((= (size list) 1) (if (funcall sorter new-key (funcall key (element (first-element list)))) (values nil (first-element list)) (values (first-element list) nil))) (t (iterate-nodes list (lambda (n) (let* ((current-key (funcall key (element n)))) (declare (dynamic-extent current-key)) (when (or (funcall test new-key current-key) (funcall sorter new-key current-key)) (return-from left-and-right-nodes-for-item (values (previous-item n) n)))))) (values (last-element list) nil)))))) (defmethod iterate-left-nodes ((list sorted-dlist-container) (item dlist-container-node) fn) (let ((neighbor (previous-item item))) (loop while neighbor do (funcall fn neighbor) (setf neighbor (previous-item neighbor))))) (defmethod iterate-left-nodes ((list sorted-dlist-container) (item i-know-my-node-mixin) fn) (iterate-left-nodes list (my-node item) fn)) (defmethod iterate-left-nodes ((list sorted-dlist-container) (item t) fn) (let ((it (search-for-node* list item :test #'eq :key #'element))) (when it (iterate-left-nodes list it fn)))) (defmethod iterate-right-nodes ((list sorted-dlist-container) (item dlist-container-node) fn) (let ((neighbor (next-item item))) (loop while neighbor do (funcall fn neighbor) (setf neighbor (next-item neighbor))))) (defmethod iterate-right-nodes ((list sorted-dlist-container) (item i-know-my-node-mixin) fn) (iterate-right-nodes list (my-node item) fn)) (defmethod iterate-right-nodes ((list sorted-dlist-container) (item t) fn) (let ((it (search-for-node* list item :test #'eq :key #'element))) (when it (iterate-right-nodes list it fn)))) (defmethod iterate-left ((list sorted-dlist-container) (item dlist-container-node) fn &optional (inclusive? nil)) (when inclusive? (funcall fn (element item))) (let ((neighbor (previous-item item))) (declare (dynamic-extent neighbor)) (loop while neighbor do (funcall fn (element neighbor)) (setf neighbor (previous-item neighbor))))) (defmethod iterate-left ((list sorted-dlist-container) (item i-know-my-node-mixin) fn &optional (inclusive? nil)) (iterate-left list (my-node item) fn inclusive?)) (defmethod iterate-left ((list sorted-dlist-container) (item t) fn &optional (inclusive? nil)) (let ((it (search-for-node* list item :test #'eq :key #'element))) (when it (iterate-left list it fn inclusive?)))) (defmethod iterate-right ((list sorted-dlist-container) (item dlist-container-node) fn &optional (inclusive? nil)) (when inclusive? (funcall fn (element item))) (let ((neighbor (next-item item))) (declare (dynamic-extent neighbor)) (loop while neighbor do (funcall fn (element neighbor)) (setf neighbor (next-item neighbor))))) (defmethod iterate-right ((list sorted-dlist-container) (item i-know-my-node-mixin) fn &optional (inclusive? nil)) (iterate-right list (my-node item) fn inclusive?)) (defmethod iterate-right ((list sorted-dlist-container) (item t) fn &optional (inclusive? nil)) (let ((it (search-for-node* list item :test #'eq :key #'element))) (when it (iterate-right list it fn inclusive?)))) (defmethod sort-update-left ((list sorted-dlist-container) (node dlist-container-node)) (with-slots (sorter key test) list (let ((node-key (funcall key (element node))) (next-neighbor (previous-item node))) (declare (dynamic-extent node-key next-neighbor)) (loop while (and next-neighbor (funcall sorter node-key (funcall key (element next-neighbor)))) do (setf (next-item next-neighbor) (next-item node) (previous-item node) (previous-item next-neighbor)) (when (not (eq next-neighbor (first-element list))) (setf (next-item (previous-item next-neighbor)) node)) (if (not (eq node (last-element list))) (setf (previous-item (next-item node)) next-neighbor) (setf (last-element list) next-neighbor)) (setf (next-item node) next-neighbor (previous-item next-neighbor) node) (setf next-neighbor (previous-item node))) (when (not next-neighbor) (setf (first-element list) node))))) (defmethod sort-update-right ((list sorted-dlist-container) (node dlist-container-node)) (with-slots (sorter key test) list (let ((node-key (funcall key (element node))) (next-neighbor (next-item node))) (declare (dynamic-extent node-key next-neighbor)) (loop while (and next-neighbor (not (funcall sorter node-key (funcall key (element next-neighbor))))) do (setf (previous-item next-neighbor) (previous-item node) (next-item node) (next-item next-neighbor)) (when (not (eq next-neighbor (last-element list))) (setf (previous-item (next-item next-neighbor)) node)) (if (not (eq node (first-element list))) (setf (next-item (previous-item next-neighbor)) next-neighbor) (setf (first-element list) next-neighbor)) (setf (previous-item node) next-neighbor (next-item next-neighbor) node) (setf next-neighbor (next-item node))) (when (not next-neighbor) (setf (last-element list) node))))) ;; The idea here is that the key of the item probably has changed, and we ;; need to find the happy place in the list for the item... (defmethod update-item ((list sorted-dlist-container) (node dlist-container-node)) (with-slots (sorter test key) list (if (and (previous-item node) (funcall sorter (funcall key (element node)) (funcall key (element (previous-item node))))) (sort-update-left list node) (sort-update-right list node))) (values list)) (defmethod update-item ((list sorted-dlist-container) (item i-know-my-node-mixin)) (update-item list (my-node item))) (defmethod update-item ((list sorted-dlist-container) item) (let ((it (search-for-node* list item :test #'eq :key #'element))) (when it (update-item list it)))) #+TESTING (progn (defclass* my-test-item () ((value nil iar))) (defun make-my-test-item (value) (make-instance 'my-test-item :value value)) (defmethod print-object ((item my-test-item) stream) (format stream "~A" (value item)))) #+TESTING (deftestsuite test-sorted-dlist-container (containers) ((the-list (make-container 'sorted-dlist-container :sorter #'< :key #'value :test #'=)) (value-1 (make-my-test-item 1)) (value-5 (make-my-test-item 5)) (value-3 (make-my-test-item 3)) (value-7 (make-my-test-item 7)) (value--3 (make-my-test-item -3)) (value-2 (make-my-test-item 2)))) #+NOT-REALLY-A-TEST (addtest (test-sorted-dlist-container) (ensure (progn (insert-item the-list value-1) (insert-item the-list value-5) (insert-item the-list value-3) (iterate-elements the-list #'print) (insert-item the-list value-7) (insert-item the-list value--3) (insert-item the-list value-2) (print "--------------------") (iterate-elements the-list #'print) (setf (value value-3) 0) (update-item the-list value-3) (print "--------------------") (iterate-elements the-list #'print) (delete-item the-list value-7) (print "--------------------") (iterate-elements the-list #'print) (delete-item the-list value--3) (print "--------------------") (iterate-elements the-list #'print) (delete-item the-list value-2) (print "--------------------") (iterate-elements the-list #'print) t))) #+RUN-IT (run-tests :suite 'test-sorted-dlist-container) #+MY-TEST (let ((the-list (make-container 'sorted-dlist-container :sorter #'< :key #'value :test #'=)) (value-1 (make-my-test-item 1)) (value-5 (make-my-test-item 5)) (value-3 (make-my-test-item 3)) (value-7 (make-my-test-item 7)) (value--3 (make-my-test-item -3)) (value-2 (make-my-test-item 2))) (insert-item the-list value-1) (insert-item the-list value-5) (insert-item the-list value-3) (iterate-elements the-list #'print) (insert-item the-list value-7) (insert-item the-list value--3) (insert-item the-list value-2) (print "--------------------") (iterate-elements the-list #'print) (setf (value value-3) 9) (update-item the-list value-3) (print "--------------------") (iterate-elements the-list #'print) (delete-item the-list value-7) (print "--------------------") (iterate-elements the-list #'print) (delete-item the-list value--3) (print "--------------------") (iterate-elements the-list #'print) (delete-item the-list value-2) (print "--------------------") (iterate-elements the-list #'print))cl-containers-20170403-git/dev/miscellaneous.lisp000066400000000000000000000233631306646076300216320ustar00rootroot00000000000000(in-package #:containers) (defun merge-elements (container merge-fn initial-fn &key (key 'identity) (test 'equal) (argument 'identity) (return :both) (filter (constantly t))) (%merge-helper container #'iterate-elements merge-fn initial-fn key test argument return filter)) (defun merge-nodes (container merge-fn initial-fn &key (key 'identity) (test 'equal) (argument 'identity) (return :both) (filter (constantly t))) (%merge-helper container #'iterate-nodes merge-fn initial-fn key test argument return filter)) (defun %merge-helper (container iterator merge-fn initial-fn key test argument return filter) (let ((result (make-container 'associative-container :test test))) (funcall iterator container (lambda (element) (when (funcall filter element) (let ((key-value (funcall key element)) (argument-value (funcall argument element))) (multiple-value-bind (item found?) (item-at result key-value) (setf (item-at result key-value) (if found? (funcall merge-fn item argument-value) (funcall initial-fn argument-value)))))))) (case return (:both (collect-key-value result :transform (lambda (k v) (list k v)))) (:keys (collect-keys result)) (:values (collect-elements result))))) (defun element-counts (container &key (test 'equal) (key 'identity) (sort nil) (sort-on :counts) (return :both) (weight (constantly 1)) (filter (constantly t))) (%container-counts container #'merge-elements test key sort sort-on return weight filter)) #+Test (element-counts '((a 1) (b 2) (c 1) (d 1) (e 2)) :key #'second :return :counts :sort #'< :sort-on :counts) (defun node-counts (container &key (test 'equal) (key 'identity) (sort nil) (sort-on :counts) (return :both) (weight (constantly 1)) (filter (constantly t))) (%container-counts container #'merge-nodes test key sort sort-on return weight filter)) (defun %container-counts (container merger test key sort sort-on return weight filter) (assert (member return '(:both :keys :counts))) (let ((result (funcall merger container (lambda (a b) (incf a (funcall weight b))) weight :key key :test test :return (if sort :both return) :filter filter))) (setf result (if sort (ecase sort-on (:counts (sort result sort :key #'second)) (:values (sort result sort :key #'first))) result)) (cond ((or (eq return :both) (not sort)) result) ((eq return :keys) (mapcar #'first result)) ((eq return :counts) (mapcar #'second result))))) #+Ignore (defun map-window-over-list (list window-size function) (loop for i from 0 to (- (length list) window-size) as window = (subseq list 0 window-size) then (nconc (rest window) (list (first current))) as current = (nthcdr window-size list) then (rest current) do (funcall function window))) #+Ignore (defun map-window-over-sequence (sequence window-size function) (let* ((size (length sequence)) (temp (make-array size :initial-contents sequence))) (loop for index from 0 to (- size window-size) do (funcall function (make-array window-size :displaced-to temp :displaced-index-offset index))))) #+Ignore ;;?? This suffers from shared structure if you just try to collect ;; the windows? Should we have another version that copies the window ;; before calling the function? (defun collect-window-over-list (list window-size function) (loop for i from 0 to (- (length list) window-size) as window = (subseq list 0 window-size) then (nconc (rest window) (list (first current))) as current = (nthcdr window-size list) then (rest current) collect (funcall function window))) (defun map-window-over-elements (container window-size window-step function &key duplicate-ends?) "Moves a windows of size `window-size` across the elements of `container`, stepping by `window-step` each time. At each step, it applies function `fn` to the elements in the current window \(as a list\)." (map-window-over-elements-helper container 'iterate-elements window-size window-step function duplicate-ends?)) (defun map-window-over-nodes (container window-size window-step function &key duplicate-ends?) "Moves a windows of size `window-size` across the elements of `container`, stepping by `window-step` each time. At each step, it applies function `fn` to the elements in the current window \(as a list\)." (map-window-over-elements-helper container 'iterate-nodes window-size window-step function duplicate-ends?)) (defun collect-window-over-elements (container window-size window-step &key (transform 'identity) duplicate-ends?) "Moves a windows of size `window-size` across the elements of `container`, stepping by `window-step` each time. At each step, it applies function `fn` to the elements in the current window \(as a list\)." (let ((result nil)) (map-window-over-elements-helper container 'iterate-elements window-size window-step (lambda (w) (push (funcall transform w) result)) duplicate-ends?) (nreverse result))) (defun collect-window-over-nodes (container window-size window-step &key (transform 'identity) duplicate-ends?) "Moves a windows of size `window-size` across the elements of `container`, stepping by `window-step` each time. At each step, it applies function `fn` to the elements in the current window \(as a list\)." (let ((result nil)) (map-window-over-elements-helper container 'iterate-nodes window-size window-step (lambda (w) (push (funcall transform w) result)) duplicate-ends?) (nreverse result))) (defun map-window-over-elements-helper (container iterator window-size window-step function duplicate-ends?) (let ((window nil) (state :initial) (count window-size)) (unless (empty-p container) (when duplicate-ends? (setf window (make-list window-size :initial-element (nth-element container 0)) state :process)) (block do-it (funcall iterator container (lambda (element) (when (eq state :initial) (push element window) (when (zerop (decf count)) (setf window (nreverse window)) (setf state :process))) (when (eq state :fill) (setf window (nconc (rest window) (list element))) (when (zerop (decf count)) (setf state :process))) (when (eq state :process) (setf state :fill count window-step) (funcall function window))))) (when duplicate-ends? (let ((final-element (first (last window)))) (dotimes (i (1- window-size)) (setf window (nconc (rest window) (list final-element))) (when (zerop (decf count)) (funcall function window) (setf count window-step))))))) (values container)) (defun map-pairs (container fn) (let ((size (size container))) (dotimes (i size) (dotimes (j size) (unless (>= i j) (funcall fn (nth-element container i) (nth-element container j))))))) #+Old (defun map-pairs (container fn) (u:iterate-over-indexes (list (size container) (size container)) (lambda (indexes) (let ((index-1 (first indexes)) (index-2 (second indexes))) (unless (>= index-1 index-2) (funcall fn (nth-element container index-1) (nth-element container index-2))))))) ;;?? (defun collect-pairs (elements) (let ((result nil)) (map-pairs elements (lambda (a b) (push (sort (list a b) #'string-lessp) result))) result)) (defmethod unique-elements ((container iteratable-container-mixin) &key (key 'identity)) (%unique-elements container 'merge-elements key)) (defmethod unique-elements ((container list) &key (key 'identity)) (%unique-elements container 'merge-elements key)) (defmethod unique-nodes ((container iteratable-container-mixin) &key (key 'identity)) (%unique-elements container 'merge-nodes key)) (defmethod unique-nodes ((container list) &key (key 'identity)) (%unique-elements container 'merge-nodes key)) (defun %unique-elements (container iterator key) (collect-elements (funcall iterator container (lambda (old new) (declare (ignore old)) (values new)) (lambda (new) (values new)) :key key :return :values))) #+Test (progn (time (remove-duplicates (collect-items (interaction-graph (ds :p-4-4000m)) :transform (lambda (v) (aref "BTT" (position (aref (symbol-name (id (element v))) 0) "BCT")))))) (time (u::unique-nodes (interaction-graph (ds :p-4-4000m)) :key (lambda (v) (aref "BTT" (position (aref (symbol-name (id (element v))) 0) "BCT")))))) cl-containers-20170403-git/dev/more-containers.lisp000066400000000000000000000017601306646076300220710ustar00rootroot00000000000000(in-package #:containers) ;;; persistent-sorted-list-container (defclass* persistent-sorted-list-container (sorted-container-mixin list-container concrete-container) "A list container that keeps its items sorted as needed. This uses pushnew-ordered." () (:export-p t)) (defmethod insert-list ((container persistent-sorted-list-container) (list t)) (loop for item in list do (insert-item container item))) (defmethod insert-item ((container persistent-sorted-list-container) (item t)) (pushnew-ordered item (slot-value container 'contents) (sorter container) :test (test container) :key (key container)) (values item)) (defmethod update-item ((container persistent-sorted-list-container) (item t)) (delete-item container item) (insert-item container item)) (defmethod ensure-sorted ((container persistent-sorted-list-container)) container) (defmethod force-sort ((container persistent-sorted-list-container)) container)cl-containers-20170403-git/dev/notes.text000066400000000000000000000014751306646076300201340ustar00rootroot00000000000000(in-package containers) what the hell happened to eksl-priority-queue? I wonder if something like (collect-elements ... :sort ...) would be handy it might be faster than (sort (collect-elements ...) ...) Remove / deprecate: make-array-container ok? - make-heap-container ok? - make-k-best-heap-container make-ring-buffer make-sorted-queue can node-empty-p be empty-p instead? copying (define-debugging-class debug-container () ()) :make-load-form abstract-container bst-node quad-tree-node priority-queue-heap (define-debugging-class debug-quad-tree (debug-container) ()) ok - awhen ok make-ht-for-container ==> make-container-for-contents ok - make-bst-node; removed, not called ok - make-quad-tree-node, only called by make-node-for-container ok - make-heap-node, only called by make-node-for-container cl-containers-20170403-git/dev/package-container.lisp000066400000000000000000000037021306646076300223350ustar00rootroot00000000000000(in-package #:containers) (defclass* package-container (iteratable-container-mixin abstract-container) ((packages nil ir) (exported-symbols-only-p t ia) ; :external (present-symbols-only-p t ia) ; :internal or :external )) (defmethod (setf packages) ((value symbol) (container package-container)) (setf (packages container) (list value))) (defmethod (setf packages) ((value cons) (container package-container)) (assert (every-element-p value (lambda (e) (find-package e)))) (setf (slot-value container 'packages) value)) (defmethod iterate-elements ((container package-container) fn) (block iterator (with-package-iterator (x (packages container) :internal :external :inherited) (loop (multiple-value-bind (more? symbol type) (x) (unless more? (return-from iterator)) (when (or (and (exported-symbols-only-p container) (eq type :external)) (and (not (exported-symbols-only-p container)) (present-symbols-only-p container) (eq type :internal)) (and (not (present-symbols-only-p container)) (not (exported-symbols-only-p container)) (eq type :inherited))) (funcall fn symbol))))))) (defmethod size ((container package-container)) ;; it's gonna cons (count-using #'iterate-elements nil container)) #+test (iterate-elements (make-container 'package-container :packages (list :p2dis) :present-symbols-only-p t :exported-symbols-only-p nil) #'print) (defun bound-symbols-in-package (package) (iterate-elements (make-container 'package-container :packages (list package) :present-symbols-only-p t :exported-symbols-only-p nil) (lambda (s) (when (and (boundp s) (symbol-value s)) (print s))))) #+Test (bound-symbols-in-package 'p2dis) cl-containers-20170403-git/dev/package.lisp000066400000000000000000000233071306646076300203600ustar00rootroot00000000000000(in-package #:common-lisp-user) (defpackage #:metabang.cl-containers (:use #:common-lisp) (:nicknames #:cl-containers #:containers) (:documentation "A library of container classes and algorithms for Common Lisp.") (:import-from #:metatilities #:deprecated #:defclass* #:defcondition #:ensure-list #:length-at-most-p #:length-at-least-p #:length-1-list-p #:maparray #:samep #:set-equal #:apply-if-exists #:funcall-if-exists #:*samep-test* #:parent #:element #:argmax #:argmin #:best-item #:filter #:size #:root #:next-element #:total-size #:element-type #:class-precedence-list #:class-direct-subclasses #:get-class #:finalize-class-if-necessary #:muffle-redefinition-warnings) (:export #:basic-queue #:ring-buffer #:vector-container #:bounded-vector-container #:flexible-vector-container #:bag-container #:set-container #:list-container #:sorted-list-container #:dlist-container #:dlist-container-node #:stack-container #:binary-search-tree #:red-black-tree #:quad-tree #:rooted-tree-container #:many-child-node #:many-unordered-child-node #:many-ordered-child-node #:parent-node-mixin #:contents-as-array-mixin #:contents-as-hashtable-mixin #:contents-as-list-mixin #:test-container-mixin #:priority-queue-on-container #:priority-queue-heap #:array-container #:sparse-array-container #:simple-associative-container #:associative-container #:alist-container #:biassociative-container-mixin #:associative-container-mixin #:keyed-associative-container #:heap-container #:abstract-queue #:k-best-heap-container #:stable-associative-container #:iteratable-container-mixin #:key-value-iteratable-container-mixin #:set-container #:bag-container #:union-find-container #:package-container #:list-iterator ) ;; Basic container operations (:export insert-item insert-new-item insert-list insert-sequence delete-list delete-item delete-item-if delete-node delete-element size empty-p empty! find-item find-node find-successor-node find-element search-for-key search-for-item search-for-node search-for-node* search-for-match search-for-element predecessor successor copy-container container->list container->array total-size ; bounded-container-mixin iteratable-p key-value-iteratable-p ;;?? deprecated iterate-container ; iteratable-container-mixin collect-items ; iteratable-container-mixin iterate-nodes iterate-elements collect-elements ; iteratable-container-mixin collect-nodes collect-key-value ; contents-as-hashtable-mixin collect-keys iterate-children ; many-child-nodes #:reduce-container #:reduce-elements #:reduce-nodes #:reduce-key-value biggest-item ; sorted-container-mixin smallest-item ; sorted-container-mixin first-item first-element last-item last-element current-item element-type ; typed-container-mixin initial-element initial-element-fn initial-contents delete-first delete-last append-item append-new-item delete-biggest-item ; heap-container k-best-number ; k-best-heap-container make-container print-container remove-items-if count-elements count-elements-if count-using collect-using iterate-elements-stably iterate-key-value-stably collect-elements-stably #:collect-key-value-stably make-node-for-container ;; Specialized container operations enqueue ; queues dequeue pop-item ; stacks push-item insert-item-at ; vector-containers delete-item-at inorder-walk ; Binary-Search-Trees preorder-walk postorder-walk insert-item-after ; dlist-container insert-item-before delete-item-after delete-item-before replace-item next-item previous-item initial-element ; Associative containers item-at item-at-1 item-at! item-at-1! dimensions iterate-key-value some-item-p ; Methods should be added for every-item-p ; more general containers some-element-p every-element-p some-key-value-p every-key-value-p reverse-find find-value find-key-value collect-keys iterate-keys element ; nodes parent children root contents find-child-node notify-element-of-child-status ; quad-tree ensure-sorted ; sorted-list-container force-sort update-item search-for-matching-node #:sample-element #:sample-item #:sample-elements #:sample-unique-elements #:safe-sample-unique-elements #:sort-elements #:sort-keys #:iterate-container-about-node #:insert-item-ordered-about-node #:insert-item-ordered #:left-node-for-item #:right-node-for-item #:left-and-right-nodes-for-item #:iterate-left-nodes #:iterate-right-nodes #:iterate-left #:iterate-right #:add-index #:delete-index #:insert-record #:delete-record #:update-record #:update-index #:table-named #:lookup-record #:*container-print-representation* #:*container-print-length* #:*container-print-association-string* #:*container-print-association-separator* #:nth-element #:nth-item #:best-item #:argmin #:argmax #:best-node #:best-element #:iterate-value-key #:map-containers #:collect-containers #:element-position #:key-exists-p) (:export #:current-element #:current-element-p #:element #:move-p #:move #:move-forward #:move-forward-p #:make-iterator #:make-generator #:iterate-with #:forward-iterator #:unique-value-iterator-mixin #:filtered-iterator-mixin #:filter #:reverse-container #:finish #:with-iterator #:iterate-forward #:weight #:unique-elements #:unique-nodes #:map-window-over-elements #:map-window-over-nodes #:collect-window-over-elements #:collect-window-over-nodes #:merge-elements #:merge-nodes #:element-counts #:node-counts #:map-pairs #:collect-pairs) ;; union find stuff, maybe not the best names... (:export #:representative #:find-set #:graft-nodes #:representative-node) (:export #:packages #:present-symbols-only-p #:exported-symbols-only-p) (:export #:existing-subclass #:include-class-dependencies #:add-parameter->dynamic-class #:determine-dynamic-class ;;?? #+(or) #:add-dynamic-class-for-parameters #:remove-parameter->dynamic-class #:empty-add-parameter->dynamic-class #:empty-all-add-parameter->dynamic-class #:parameter->dynamic-class #:find-existing-subclass #:find-or-create-class) ) cl-containers-20170403-git/dev/quad-tree.lisp000066400000000000000000000117521306646076300206550ustar00rootroot00000000000000(in-package #:containers) ;;; quad-tree (defclass* quad-tree (initial-contents-mixin classified-container-mixin findable-container-mixin iteratable-container-mixin container-uses-nodes-mixin rooted-tree-container concrete-container) ((size 0)) :automatic-accessors :automatic-initargs (:default-initargs :key 'identity :test 'eq)) (defclass* four-child-node (parent-node-mixin) ((top-left-child :initform nil :accessor top-left-child) (top-right-child :initform nil :accessor top-right-child) (bottom-left-child :initform nil :accessor bottom-left-child) (bottom-right-child :initform nil :accessor bottom-right-child))) (defclass* quad-tree-node (four-child-node) ((tree :initform nil :initarg :tree :accessor tree))) (defmethod make-node-for-container ((tree quad-tree) (item t) &key) (if item (make-instance 'quad-tree-node :element item :tree tree) nil)) (defmethod node-empty-p ((node quad-tree-node)) (null (element node))) (defmethod print-object ((o quad-tree-node) stream) (print-unreadable-object (o stream :type t) (format stream "~A" (element o)))) (defgeneric notify-element-of-child-status (element status) (:documentation "This is called to allow the element to know its status as a child. Useful for quad tree elements, where an element's position relative to its parent could be relevant to the element. Status is one of: :TOP-LEFT, :TOP-RIGHT, :BOTTOM-LEFT, :BOTTOM-RIGHT or :ROOT") (:method ((element t) (status t)) (values nil))) (defmethod insert-item ((tree quad-tree) (item quad-tree-node)) (loop with key = (key tree) with y = (make-node-for-container tree nil) with classifier = (classifier tree) and x = (root tree) and key-item = (funcall key (element item)) while (not (node-empty-p x)) do (progn (setf y x) (case (funcall classifier key-item (funcall key (element x))) (:TOP-LEFT (setf x (top-left-child x))) (:TOP-RIGHT (setf x (top-right-child x))) (:BOTTOM-LEFT (setf x (bottom-left-child x))) (:BOTTOM-RIGHT (setf x (bottom-right-child x))))) finally (progn (setf (parent item) y (tree item) tree) (if (node-empty-p y) (progn (notify-element-of-child-status (element item) :ROOT) (setf (root tree) item)) (case (funcall classifier key-item (funcall key (element y))) (:TOP-LEFT (notify-element-of-child-status (element item) :TOP-LEFT) (setf (top-left-child y) item)) (:TOP-RIGHT (notify-element-of-child-status (element item) :TOP-RIGHT) (setf (top-right-child y) item)) (:BOTTOM-LEFT (notify-element-of-child-status (element item) :BOTTOM-LEFT) (setf (bottom-left-child y) item)) (:BOTTOM-RIGHT (notify-element-of-child-status (element item) :BOTTOM-RIGHT) (setf (bottom-right-child y) item)))))) (incf (size tree)) (values tree)) (defmethod empty-p ((tree quad-tree)) (node-empty-p (root tree))) (defmethod empty! ((tree quad-tree)) (setf (root tree) (make-node-for-container tree nil)) (setf (size tree) 0) (values tree)) ;; find-item needs to operate a bit differently -- it must find the ;; node in the tree that minimizes the test (e.g. minimal overlap); ;; therefore, it keeps searching until it finds a node that doesn't ;; pass the test of the container, and returns its parent. (defmethod find-item ((tree quad-tree) (item quad-tree-node)) (let ((last-node nil) (current (root tree)) (test (test tree))) (loop with key = (key tree) with classifier = (classifier tree) and key-item = (funcall key (element item)) while (and (not (node-empty-p current)) (funcall test (element item) (element current))) do (setf last-node current) (case (funcall classifier key-item (funcall key (element current))) (:TOP-LEFT (setf current (top-left-child current))) (:TOP-RIGHT (setf current (top-right-child current))) (:BOTTOM-LEFT (setf current (bottom-left-child current))) (:BOTTOM-RIGHT (setf current (bottom-right-child current))) (otherwise (setf current nil)))) (if (and (not (node-empty-p last-node)) (funcall test (element item) (element last-node))) (values last-node) (values nil)))) cl-containers-20170403-git/dev/queues.lisp000066400000000000000000000145311306646076300202730ustar00rootroot00000000000000;;;-*- Mode: Lisp; Package: containers -*- (in-package #:containers) ;;; Abstract Queue interface ;;; ;;; supports: enqueue (insert-item), dequeue (delete-first), empty!, ;;; size, empty-p, first-element (defclass* abstract-queue (initial-contents-mixin ordered-container-mixin) ()) (defmethod enqueue ((queue abstract-queue) item) (insert-item queue item)) (defmethod dequeue ((queue abstract-queue)) (delete-first queue)) (defmethod empty! ((q abstract-queue)) ;; Dequeue items until the queue is empty. Inefficient, but always works. (do () ((empty-p q) q) (delete-first q)) (values)) (defmethod first-element :before ((q abstract-queue)) (error-if-queue-empty q "Tried to examine first-element from an empty queue.")) (defmethod delete-first :before ((q abstract-queue)) (error-if-queue-empty q "Tried to dequeue from an empty queue.")) (defmethod error-if-queue-empty ((q abstract-queue) &optional (message "Cannot work with an empty queue") &rest rest) (when (empty-p q) (error message rest))) ;;; Priority Queues on 'arbitrary' containers ;;; ;;; The underlying container must support: insert-item, first-element ;;; delete-item, empty-p, empty!, size, find-item, ;;; delete-item and delete-item-if (defclass* priority-queue-on-container (iteratable-container-mixin sorted-container-mixin findable-container-mixin concrete-container abstract-queue) ((container nil r)) (:default-initargs :container-type 'binary-search-tree)) (defmethod initialize-instance :around ((object priority-queue-on-container) &rest args &key container-type &allow-other-keys) (remf args :container-type) (remf args :initial-contents) (setf (slot-value object 'container) (apply #'make-container container-type args)) (call-next-method)) (defmethod insert-item ((q priority-queue-on-container) item) (insert-item (container q) item)) (defmethod delete-first ((q priority-queue-on-container)) (let ((m (first-node (container q)))) (delete-node (container q) m) (element m))) (defmethod empty-p ((q priority-queue-on-container)) (empty-p (container q))) (defmethod empty! ((q priority-queue-on-container)) (empty! (container q)) (values)) (defmethod size ((q priority-queue-on-container)) (size (container q))) (defmethod first-element ((q priority-queue-on-container)) (first-element (container q))) (defmethod (setf first-element) (value (q priority-queue-on-container)) (setf (first-element (container q)) value)) (defmethod find-item ((q priority-queue-on-container) (item t)) (let ((node (find-item (container q) item))) (when node (element node)))) (defmethod find-node ((q priority-queue-on-container) (item t)) (find-node (container q) item)) (defmethod find-element ((q priority-queue-on-container) (item t)) (find-element (container q) item)) (defmethod delete-item ((q priority-queue-on-container) (item t)) (delete-item (container q) item)) (defmethod delete-node ((q priority-queue-on-container) (item t)) (delete-node (container q) item)) (defmethod delete-element ((q priority-queue-on-container) (item t)) (delete-element (container q) item)) (defmethod delete-item-if (test (q priority-queue-on-container)) (delete-item-if test (container q))) (defmethod iterate-nodes ((q priority-queue-on-container) fn) (iterate-nodes (container q) fn)) (defmethod iterate-elements ((q priority-queue-on-container) fn) (iterate-elements (container q) fn)) ;;; Standard no frills queue (defclass* basic-queue (abstract-queue iteratable-container-mixin concrete-container) ((queue nil :accessor queue-queue) (indexer nil :accessor queue-header)) (:documentation "A simple FIFO queue implemented as a list with extra bookkeeping for efficiency.")) ;; Some semantically helpful functions (defun front-of-queue (queue) (car (queue-header queue))) (defun front-of-queue! (queue new) (setf (car (queue-header queue)) new)) (defsetf front-of-queue front-of-queue!) (defun tail-of-queue (queue) (cdr (queue-header queue))) (defun tail-of-queue! (queue new) (setf (cdr (queue-header queue)) new)) (defsetf tail-of-queue tail-of-queue!) (eval-when (:compile-toplevel) (proclaim '(inline front-of-queue front-of-queue!)) (proclaim '(inline tail-of-queue tail-of-queue!))) (defmethod insert-item ((q basic-queue) (item t)) "Add an item to the queue." (let ((new-item (list item))) (cond ((empty-p q) (setf (queue-queue q) new-item (queue-header q) (cons (queue-queue q) (queue-queue q)))) (t (setf (cdr (tail-of-queue q)) new-item (tail-of-queue q) new-item)))) q) (defmethod delete-first ((q basic-queue)) (let ((result (front-of-queue q))) (setf (front-of-queue q) (cdr result) result (first result)) ;; reset things when I'm empty (when (null (front-of-queue q)) (empty! q)) result)) (defmethod empty-p ((q basic-queue)) (null (queue-header q))) (defmethod iterate-nodes ((q basic-queue) fn) (let ((start (front-of-queue q))) (mapc fn start)) (values q)) (defmethod size ((q basic-queue)) ;;??slow (if (empty-p q) 0 (length (front-of-queue q)))) (defmethod first-element ((q basic-queue)) "Returns the first item in a queue without changing the queue." (car (front-of-queue q))) (defmethod (setf first-element) (value (q basic-queue)) "Returns the first item in a queue without changing the queue." (setf (car (front-of-queue q)) value)) (defmethod empty! ((q basic-queue)) "Empty a queue of all contents." (setf (queue-queue q) nil (queue-header q) nil) (values)) (defmethod delete-item ((queue basic-queue) item) (unless (empty-p queue) (cond ((eq item (first-element queue)) (delete-first queue)) ((eq item (car (tail-of-queue queue))) ;; expensive special case... (setf (queue-queue queue) (remove item (queue-queue queue)) (front-of-queue queue) (queue-queue queue) (tail-of-queue queue) (last (front-of-queue queue)))) (t (setf (queue-queue queue) (delete item (queue-queue queue))))))) cl-containers-20170403-git/dev/r-tree.lisp000066400000000000000000001247111306646076300201640ustar00rootroot00000000000000(in-package :eksl-utilities) #| R-Trees allow dynamic insertion and deletion of multi-dimensional spatial structures. The structures are indexed hierarchically in nodes of some predefined size. Each node contains a tight minimum bounding n-dimensional rectangle over its descedants. Using pruning techniques, the r-tree can be searched for fast nearest-neighbor queries. The interface adheres to the eksl containers library. For Example: (defparameter *r-tree* (make-container 'r-tree :max-node-size 5 :dimensions 4)) creates an r-tree with branching factor 5 that expects insertion of 4-dimensional items. (loop for i from 0 to 1000 do (insert-item *r-tree* (make-list 4 :initial-element i))) inserts the points '(i i i i) for i from 0 to 1000 into the r-tree. By default, a list of n numbers is assumed to be a point in n-dimensional space. Furthermore, the minimum bounding rectangle is assumed to be the point itself. The insert-item method also accepts an item of type r-tree-item. This allows one to create arbitrary spatial items that can be bound by an n-dimensional minimum-bounding-rectangle. When using insert-item with objects of than points, one must explicitly create an r-tree-item and specify its MBR. (nearest-neighbors *r-tree* '(100 100 100 100) 3) finds the 3 nearest neighbors of the point (100 100 100) Sometimes it's important to associate a label with a spatial-object. In this case, the r-tree-labelled-item should be used as follows: (insert-item *r-tree* (make-container 'r-tree-labelled-item spatial-object label :mbr *the-mbr-for-spatial-object* :test *the-equality-test*)) In the case of simple points, this can be reduced to: (insert-item *r-tree* (make-container 'r-tree-labelled-item '(x0 x1 ... xn) the-label)) Nearest neighbor queries on r-trees with labelled items return (point label) pairs instead of just points. |# (export '(r-tree-root-node r-tree-max-node-size r-tree-min-node-size r-tree-dimensions r-tree-depth node-splitting-fn nearest-neighbors insert-item delete-item)) ;;; r-tree (defclass* r-tree (test-container-mixin container-uses-nodes-mixin) ((root-node :accessor r-tree-root-node :initarg :root-node :initform nil :type r-tree-node :documentation "The root node of the r-tree") (max-node-size :accessor r-tree-max-node-size :initarg :max-node-size :type fixnum :documentation "The maximum branching factor of the r-tree") (min-node-size :accessor r-tree-min-node-size :initarg :min-node-size :type fixnum :documentation "The minimum branching factor of the r-tree. Defaults to min(2, floor(max-node-size/2))") (node-splitting-fn :accessor node-splitting-fn :initarg :node-splitting-fn :type function :documentation "The function used to split nodes") (r-tree-dimensions :accessor r-tree-dimensions :initarg :dimensions :type fixnum) (r-tree-size :accessor size :initarg r-tree-size :initform 0) (test #'equal)) (:documentation "R-Trees are dynamic data structures that allow quick insertion, deletion and searching of spatial data objects in multiple dimensions. max-node-size refers to the number of records a node can keep before it needs to be split. min-node-size, likewise, is the minimum number of records required in a node.") :copy-slots) ;;; make-container :: 'r-tree -> ... -> r-tree (defmethod make-container ((class (eql 'r-tree)) &rest args) (apply #'make-r-tree args)) ;;; make-r-tree :: fixnum -> fixnum -> r-tree (defun make-r-tree (&key (max-node-size 5) (dimensions 2) (min-node-size (max (floor (/ max-node-size 2)) 2)) (node-splitting-fn #'r-tree-quadratic-split)) (make-instance 'r-tree :max-node-size max-node-size :min-node-size min-node-size :dimensions dimensions :node-splitting-fn node-splitting-fn)) (defmethod print-object ((r-tree r-tree) stream) (print-unreadable-object (r-tree stream :type t :identity t) (format stream "~A ~A ~A" (r-tree-max-node-size r-tree) (r-tree-min-node-size r-tree) (r-tree-dimensions r-tree)))) (defmethod print-r-tree ((r-tree r-tree) stream) (if (r-tree-root-node r-tree) (format stream "~A" (r-tree-root-node r-tree)) (format stream "()"))) ;;; r-tree-depth :: r-tree -> fixnum #+WAIT (defmethod r-tree-depth ((r-tree r-tree)) (1- (ceiling (log (size r-tree) (r-tree-min-node-size r-tree))))) (defmethod r-tree-depth ((r-tree r-tree)) (aif (r-tree-root-node r-tree) (r-tree-node-depth it) 0)) ;;; r-tree-node ;;?? GWK make this a mixin and fix it (defclass* r-tree-node (vector-container) ((parent-node :accessor r-tree-parent-node :initform nil :initarg :parent-node) (parent-record :accessor r-tree-parent-record :initform nil :initarg :parent-record)) (:documentation "R-Tree nodes contain a number of records") :copy-slots) (defmethod initialize-instance :after ((node r-tree-node) &key records) (mapc (curry #'insert-item node) records)) (defgeneric make-r-tree-node-like (node &key) (:documentation "An interface for making an r-tree-node like the parameter")) (defmethod mbr-for-r-tree-node ((node r-tree-node)) (apply #'add-mbrs (collect-items node :transform #'mbr))) (defmethod r-tree-internal-node? ((r-tree r-tree-node)) nil) (defmethod r-tree-node-depth ((node r-tree-node) &optional (depth 1)) (r-tree-node-depth (r-tree-next-node (first-item node)) (1+ depth))) ;;; r-tree-root-node? :: r-tree-node -> boolean (defmethod r-tree-root-node? ((node r-tree-node)) (null (r-tree-parent-node node))) ;;; r-tree-leaf-node (defclass* r-tree-leaf-node (r-tree-node) () (:documentation "r-tree-leaf-nodes contain only r-tree-items")) (defmethod make-container ((class (eql 'r-tree-leaf-node)) &rest args) (apply #'make-r-tree-leaf-node args)) (defun make-r-tree-leaf-node (&key (records nil) (parent-node nil) (parent-record nil)) (make-instance 'r-tree-leaf-node :records records :parent-node parent-node :parent-record parent-record)) (defmethod make-r-tree-node-like ((node r-tree-leaf-node) &key (parent-node nil) (parent-record nil)) (make-container 'r-tree-leaf-node :parent-node parent-node :parent-record parent-record)) (defmethod print-object ((node r-tree-leaf-node) stream) (format stream "(~{ ~A~} )~%" (collect-elements node))) (defmethod r-tree-node-depth ((node r-tree-leaf-node) &optional (depth 1)) depth) ;;; r-tree-internal-node (defclass* r-tree-internal-node (r-tree-node) () (:documentation "An internal node")) (defmethod make-container ((class (eql 'r-tree-internal-node)) &rest args) (apply #'make-r-tree-internal-node args)) (defun make-r-tree-internal-node (&key (records nil) (parent-node nil) (parent-record nil)) (make-instance 'r-tree-internal-node :records records :parent-node parent-node :parent-record parent-record)) (defmethod make-r-tree-node-like ((node r-tree-internal-node) &key (parent-node nil) (parent-record nil)) (make-container 'r-tree-internal-node :parent-node parent-node :parent-record parent-record)) (defmethod r-tree-internal-node? ((node r-tree-internal-node)) t) (defmethod print-object ((node r-tree-internal-node) stream) (format stream "(~{~A~})" (mapcar #'r-tree-next-node (collect-elements node)))) ;;; mbr (defclass* mbr (array-container) () (:documentation "mbr is a minimum-bounding-rectangle in n-dimensions. The data structure is an array-container with two rows, the first rows is the minimum bound; the second is the maximum bound.")) (defmethod make-container ((class (eql 'mbr)) &rest args) (apply #'make-mbr args)) (defun make-mbr (&key (minimum nil) (maximum nil) (dimensions (list 2 (length minimum)))) (make-instance 'mbr :minimum minimum :maximum maximum :dimensions dimensions)) (defmethod initialize-instance :after ((mbr mbr) &key (minimum nil) (maximum nil)) (loop for i from 0 to (1- (/ (size mbr) 2)) for min in minimum for max in maximum do (item-at! mbr min 0 i) (item-at! mbr max 1 i))) (defmethod min-point ((mbr mbr) (dimension number)) (item-at mbr 0 dimension)) (defmethod max-point ((mbr mbr) (dimension number)) (item-at mbr 1 dimension)) ;;; iterate-mbrs :: mbr -> mbr -> fn -> t (defmethod iterate-mbrs ((mbr1 mbr) (mbr2 mbr) fn) (loop for i from 0 to (1- (/ (size mbr1) 2)) do (funcall fn (item-at mbr1 0 i) (item-at mbr1 1 i) (item-at mbr2 0 i) (item-at mbr2 1 i)))) ;;; mbr-dimension-increase :: mbr -> mbr -> fixnum ;;; this method measures the total amount in dimension 'mbr1' needs to be ;;; increased to enclose 'mbr2' completely. (defmethod mbr-size-increase ((mbr1 mbr) (mbr2 mbr)) (loop for i from 0 to (1- (/ (size mbr1) 2)) sum (+ (max 0 (- (item-at mbr1 0 i) (item-at mbr2 0 i))) (max 0 (- (item-at mbr2 1 i) (item-at mbr1 1 i)))))) ;;; mbr-area-increase :: mbr -> mbr -> fixnum ;;; reports the total area mbr1 would be increased so that it completely ;;; encloses mbr2 (defmethod mbr-area-increase ((mbr1 mbr) (mbr2 mbr)) (- (mbr-area (add-mbrs mbr1 mbr2)) (mbr-area mbr1))) ;;; mbr-area :: mbr -> fixnum (defmethod mbr-area ((mbr mbr)) (loop for i from 0 to (1- (/ (size mbr) 2)) with total-area = 1 do (setf total-area (* total-area (- (item-at mbr 1 i) (item-at mbr 0 i)))) finally (return total-area))) ;;; add-mbr :: mbr -> mbr -> mbr-mixin (defmethod add-mbrs ((mbr mbr) &rest mbrs) (let ((result (make-container 'mbr :dimensions (list 2 (/ (size mbr) 2)))) (mbrs (push mbr mbrs))) (loop for i from 0 to (1- (/ (size mbr) 2)) do (item-at! result (reduce #'min (mapcar (curry-after #'item-at 0 i) mbrs)) 0 i) (item-at! result (reduce #'max (mapcar (curry-after #'item-at 1 i) mbrs)) 1 i)) result)) ;;; overlap-mbr? :: mbr -> mbr -> boolean ;;; if mbr1 overlaps mbr2, then return true, otherwise return false ;;; overlap means that mbr1 completely contains mbr2 (defmethod overlap-mbr? ((mbr1 mbr) (mbr2 mbr)) (iterate-mbrs mbr1 mbr2 #'(lambda (min1 max1 min2 max2) (when (or (< min2 min1) (> max2 max1)) (return-from overlap-mbr? nil)))) t) ;;; record-mixin (defclass* record-mixin (copyable-mixin) ((mbr :accessor mbr :initarg :mbr :type mbr)) (:documentation "r-tree records and r-tree-items are both records, so we need to abstract out their equivalence.") :copy-slots) ;;; r-tree-record (defclass* r-tree-record (record-mixin container-node-mixin) ((next :accessor r-tree-next-node :initarg :next)) (:documentation "An r-tree record contains a pointer to the nodes below it and the minimum-bounding-rectangle of those nodes.") :copy-slots) (defmethod make-container ((class (eql 'r-tree-record)) &rest args) (apply #'make-r-tree-record args)) (defun make-r-tree-record (&rest args) (apply #'make-instance 'r-tree-record args)) (defmethod insert-item :after ((node r-tree-node) (item r-tree-record)) (setf (r-tree-parent-node (r-tree-next-node item)) node) (setf (r-tree-parent-record (r-tree-next-node item)) item)) ;;; label-mixin (defclass* label-mixin (copyable-mixin) ((label :accessor label :initarg :label)) (:documentation "provides a label slot") :copy-slots) ;;; r-tree-item (defclass* r-tree-item (record-mixin) ((spatial-object :accessor spatial-object :initarg :spatial-object :type t) (test :accessor r-tree-item-test :initarg :test :type function)) (:documentation "An r-tree item is a spatial-object with and its minimum-bounding-rectangle.") :copy-slots) (defmethod make-container ((class (eql 'r-tree-item)) &rest args) (apply #'make-r-tree-item args)) (defmethod initialize-instance :after ((item r-tree-item) &key) (unless (and (slot-boundp item 'mbr) (mbr item)) (setf (mbr item) (make-container 'mbr :minimum (spatial-object item) :maximum (spatial-object item))))) (defun make-r-tree-item (spatial-object &key (mbr nil) (test #'equal)) (make-instance 'r-tree-item :spatial-object spatial-object :test test :mbr mbr)) (defmethod print-object ((item r-tree-item) stream) (print-unreadable-object (item stream :type t :identity t) (format stream "~A" (spatial-object item)))) ;;; r-tree-labelled-item (defclass* r-tree-labelled-item (r-tree-item label-mixin) () (:documentation "When using r-trees for nearest-neighbor classification it is often necessary to label each spatial object. This item provides a slot for such a label.") :copy-slots) (defmethod make-container ((class (eql 'r-tree-labelled-item)) &rest args) (apply #'make-r-tree-labelled-item args)) (defun make-r-tree-labelled-item (spatial-object label &key (mbr nil) (test #'equal)) (make-instance 'r-tree-labelled-item :spatial-object spatial-object :label label :test test :mbr mbr)) ;;; insert-item :: r-tree -> (fixnum) -> r-tree (defmethod insert-item ((r-tree r-tree) (item list)) (insert-item r-tree (make-container 'r-tree-item item))) ;;; insert-item :: r-tree -> record record-mixin -> r-tree ;;; insert-item* inserts the record in the r-tree, but we also need to record ;;; the the size increase, hence the incf (defmethod insert-item ((r-tree r-tree) (record record-mixin)) (incf (size r-tree)) (insert-item* r-tree record)) ;;; insert-item* :: r-tree -> record-mixin -> r-tree (defmethod insert-item* ((r-tree r-tree) (record record-mixin)) (let ((node (choose-r-tree-node r-tree record))) (insert-item node record) (multiple-value-call #'adjust-r-tree r-tree (split-r-tree-node r-tree node))) r-tree) ;;; delete-item :: r-tree -> (t) -> r-tree (defmethod delete-item ((r-tree r-tree) (item list)) (delete-item r-tree (make-container 'r-tree-item item))) ;;; delete-item :: r-tree -> r-tree-item -> r-tree (defmethod delete-item ((r-tree r-tree) (item r-tree-item)) (multiple-value-bind (node record) (find-leaf-node r-tree item) (when node (delete-item node record) (decf (size r-tree)) (condense-r-tree r-tree node) (when (and (= (size (r-tree-root-node r-tree)) 1) (r-tree-internal-node? (r-tree-root-node r-tree))) (setf (r-tree-root-node r-tree) (r-tree-next-node (first-item (r-tree-root-node r-tree)))) (setf (r-tree-parent-node (r-tree-root-node r-tree)) nil) (setf (r-tree-parent-record (r-tree-root-node r-tree)) nil)))) r-tree) ;;; find-leaf-node :: r-tree -> r-tree-item -> r-tree-leaf-node (defmethod find-leaf-node ((r-tree r-tree) (item r-tree-item)) (awhen (r-tree-root-node r-tree) (find-leaf-node it item))) ;;; find-leaf-node :: r-tree-internal-node -> r-tree-item -> r-tree-leaf-node (defmethod find-leaf-node ((node r-tree-internal-node) (item r-tree-item)) (iterate-container node #'(lambda (record) (when (overlap-mbr? (mbr record) (mbr item)) (multiple-value-bind (n r) (find-leaf-node (r-tree-next-node record) item) (when n (return-from find-leaf-node (values n r))))))) nil) #+OLD (defmethod find-leaf-node ((node r-tree-internal-node) (item r-tree-item)) (iterate-container node #'(lambda (record) (when (overlap-mbr? (mbr record) (mbr item)) (return-from find-leaf-node (find-leaf-node (r-tree-next-node record) item))))) nil) ;;; find-leaf-node :: r-tree-leaf-node -> r-tree-item -> r-tree-leaf-node (defmethod find-leaf-node ((node r-tree-leaf-node) (item r-tree-item)) (iterate-container node #'(lambda (record) (when (and (overlap-mbr? (mbr record) (mbr item)) (funcall (r-tree-item-test item) (spatial-object record) (spatial-object item))) (return-from find-leaf-node (values node record))))) nil) ;;; condense-r-tree :: r-tree -> r-tree-node -> (t) -> (defmethod condense-r-tree ((r-tree r-tree) (node r-tree-node) &optional (records nil)) (if (r-tree-root-node? node) (progn (format t "~%CONDENSE-R-TREE: RECORDS = ~{~A~%~}~%" records) (mapc (curry #'insert-item* r-tree) records)) (let ((parent (r-tree-parent-node node)) (record (r-tree-parent-record node))) (cond ((< (size node) (r-tree-min-node-size r-tree)) (delete-item parent record) (if (r-tree-internal-node? node) (setf records (nconc (collect-elements node) records)) (setf records (nconc records (collect-elements node))))) (t (setf (mbr record) (mbr-for-r-tree-node node)))) (condense-r-tree r-tree parent records)))) ;;; choose-r-tree-node :: r-tree -> r-tree-item -> r-tree-leaf-node ;;; Invoked from the top of the tree, calls choose-leaf with the root node (defmethod choose-r-tree-node ((r-tree r-tree) (item r-tree-item)) (aif (r-tree-root-node r-tree) (choose-r-tree-node it item) (setf (r-tree-root-node r-tree) (make-container 'r-tree-leaf-node)))) ;;; choose-r-tree-node :: r-tree -> r-tree-record -> r-tree-internal-node ;;; This finds (defmethod choose-r-tree-node ((r-tree r-tree) (record r-tree-record)) (let ((tree-depth (r-tree-depth r-tree))) (labels ((choose-r-tree-node* (node record current-depth record-depth) (if (= (- tree-depth current-depth) record-depth) node (choose-r-tree-node* (r-tree-next-node (choose-best-fit node record)) record (1+ current-depth) record-depth)))) (choose-r-tree-node* (r-tree-root-node r-tree) record 1 (r-tree-node-depth (r-tree-next-node record)))))) ;;; choose-r-tree-node :: r-tree-leaf-node -> r-tree-item -> r-tree-leaf-node (defmethod choose-r-tree-node ((node r-tree-leaf-node) (item r-tree-item)) (declare (ignore item)) node) ;;; choose-r-tree-node :: r-tree-internal-node -> r-tree-item -> r-tree-leaf-node (defmethod choose-r-tree-node ((node r-tree-internal-node) (item r-tree-item)) (choose-r-tree-node (r-tree-next-node (choose-best-fit node item)) item)) ;;; choose-best-fit :: r-tree-internal-node -> record-mixin -> r-tree-node ;;; choose-best-fit finds the node record that requires the least expansion ;;; of it's minimum-bounding-rectangle to insert the record. When ties ;;; occur, the record with the least area is favored. If the areas are ;;; identical, then choose arbitrarily. (defmethod choose-best-fit ((node r-tree-internal-node) (record record-mixin)) (loop for i from 1 to (1- (size node)) with best-fit = (first-item node) with best-fit-area = (mbr-area (mbr best-fit)) with best-fit-increase = (mbr-area-increase (mbr best-fit) (mbr record)) do (awhen (item-at node i) (let ((increase (mbr-area-increase (mbr it) (mbr record))) (area (mbr-area (mbr it)))) (when (or (< increase best-fit-increase) (and (= increase best-fit-increase) (> best-fit-area area))) (setf best-fit-increase increase) (setf best-fit it) (setf best-fit-area area)))) finally (return best-fit))) ;;; split-r-tree-node :: r-tree -> r-tree-node -> r-tree-node r-tree-node (defmethod split-r-tree-node ((r-tree r-tree) (node r-tree-node)) (if (> (size node) (r-tree-max-node-size r-tree)) (funcall (node-splitting-fn r-tree) r-tree node) node)) ;;; r-tree-quadratic-split :: r-tree -> r-tree-node -> r-tree-node r-tree-node (defmethod r-tree-quadratic-split ((r-tree r-tree) (node r-tree-node)) (let ((left (make-r-tree-node-like node :parent-node (r-tree-parent-node node) :parent-record (r-tree-parent-record node))) (right (make-r-tree-node-like node :parent-node (r-tree-parent-node node) :parent-record (r-tree-parent-record node)))) (multiple-value-bind (rec1 rec2) (pick-node-seeds node) (delete-item node rec1) (delete-item node rec2) (insert-item left rec1) (insert-item right rec2)) (pick-remaining-nodes r-tree node left right))) ;;; pick-node-seeds :: r-tree-node -> r-tree-record r-tree-record ;;; return the pair of records r1 and r2 that maximize: ;;; area(mbr(r1),mbr(r2)) - area(mbr(r1)) - area(mbr(r2)) (defmethod pick-node-seeds ((node r-tree-node)) (flet ((area-fn (rec1 rec2) (- (mbr-area (add-mbrs (mbr rec1) (mbr rec2))) (mbr-area (mbr rec1)) (mbr-area (mbr rec2))))) (loop for i from 0 to (1- (size node)) with seed1 = (first-item node) with seed2 = (item-at node 1) with area = (area-fn seed1 seed2) do (loop for j from 1 to (1- (size node)) with record1 = (item-at node i) do (let* ((record2 (item-at node j)) (val (area-fn record1 record2))) (when (> val area) (setf area val) (setf seed1 record1) (setf seed2 record2)))) finally (return (values seed1 seed2))))) ;;; pick-and-insert-next-node :: r-tree-node -> r-tree-node -> r-tree-node (defmethod pick-and-insert-next-node ((node r-tree-node) (left r-tree-node) (right r-tree-node)) (loop for i from 1 to (1- (size node)) with mbr-left = (mbr-for-r-tree-node left) with mbr-right = (mbr-for-r-tree-node right) with record = (first-item node) with left-increase = (mbr-area-increase mbr-left (mbr record)) with right-increase = (mbr-area-increase mbr-right (mbr record)) with max-diff = (abs (- left-increase right-increase)) do (let* ((nextrecord (item-at node i)) (left-increase* (mbr-area-increase mbr-left (mbr nextrecord))) (right-increase* (mbr-area-increase mbr-right (mbr nextrecord))) (val (abs (- left-increase right-increase)))) (when (> val max-diff) (setf max-diff val) (setf left-increase left-increase*) (setf right-increase right-increase*) (setf record nextrecord))) finally (progn (delete-item node record) (if (< left-increase right-increase) (insert-item left record) (insert-item right record))))) ;;; pick-remaining-node :: r-tree -> r-tree-node -> r-tree-node -> ;;; r-tree-node -> r-tree-node r-tree-node (defmethod pick-remaining-nodes ((r-tree r-tree) (node r-tree-node) (left r-tree-node) (right r-tree-node)) (cond ((finished-quadratic-split? r-tree node left right) (values left right)) (t (pick-and-insert-next-node node left right) (pick-remaining-nodes r-tree node left right)))) ;;; finished-quadratic-split? :: r-tree -> r-tree-node -> r-tree-node -> ;;; r-tree-node -> boolean (defmethod finished-quadratic-split? ((r-tree r-tree) (node r-tree-node) (left r-tree-node) (right r-tree-node)) (cond ((empty-p node) t) ((= (+ (size node) (size left)) (r-tree-min-node-size r-tree)) (iterate-container node (curry #'insert-item left)) (empty! node) t) ((= (+ (size node) (size right)) (r-tree-min-node-size r-tree)) (iterate-container node (curry #'insert-item right)) (empty! node) t) (t nil))) ;;; adjust-r-tree :: r-tree -> r-tree-node -> r-tree-node -> r-tree (defmethod adjust-r-tree ((r-tree r-tree) (left r-tree-node) &optional right) (if (r-tree-root-node? left) (if right (let* ((lrecord (make-container 'r-tree-record :next left :mbr (mbr-for-r-tree-node left))) (rrecord (make-container 'r-tree-record :next right :mbr (mbr-for-r-tree-node right))) (newroot (make-container 'r-tree-internal-node :records (list lrecord rrecord)))) (setf (r-tree-parent-node left) newroot) (setf (r-tree-parent-record left) lrecord) (setf (r-tree-parent-node right) newroot) (setf (r-tree-parent-record right) rrecord) (setf (r-tree-root-node r-tree) newroot) r-tree) r-tree) (let ((parent (r-tree-parent-node left)) (record (r-tree-parent-record left))) (setf (mbr record) (mbr-for-r-tree-node left)) (setf (r-tree-next-node record) left) (when right (insert-item parent (make-container 'r-tree-record :next right :mbr (mbr-for-r-tree-node right)))) (multiple-value-call #'adjust-r-tree r-tree (split-r-tree-node r-tree parent))))) ;;; ;;; NEAREST-NEIGHBOR ;;; (defparameter *nnscount* 0) (defparameter *promise-pruning* t) ;;; nearest-neighbor-node-mixin (defclass* nearest-neighbor-node-mixin (copyable-mixin) ((neighbor-distance :accessor neighbor-distance :initarg :neighbor-distance)) (:documentation "Base class of nearest-neighbor nodes and promises") :copy-slots) ;;; promise (defclass* promise (nearest-neighbor-node-mixin) () (:documentation "Promises are placed holders in the kbest heap")) (defun make-promise (distance) (make-instance 'promise :neighbor-distance distance)) (defmethod make-container ((class (eql 'promise)) &rest args) (apply #'make-promise args)) (defmethod print-object ((n promise) stream) (print-unreadable-object (n stream :type t :identity t) (format stream "~A" (neighbor-distance n)))) ;;; promise-record (defclass* promise-record (r-tree-record) ((promise :accessor promise :initarg :promise)) (:documentation "Promise records are used when the MinMaxDist pruning technique is used. A promised record simply adds a slot to the record that stores a pointer to a promise.") :copy-slots) (defmethod make-promise-record ((record r-tree-record) promise) (make-instance 'promise-record :next (r-tree-next-node record) :mbr (mbr record) :promise promise)) (defmethod make-container ((class (eql 'promise-record)) &rest args) (apply #'make-promise-record args)) (defmethod promise-record? ((pr promise-record)) t) (defmethod promise-record? ((obj t)) nil) ;;; nearest-neighbor-node (defclass* nearest-neighbor-node (nearest-neighbor-node-mixin) ((spatial-object :accessor spatial-object :initarg :spatial-object :initform nil) (mbr :accessor mbr :initarg :mbr)) (:documentation "nearest-neighbor-node objects store branch and bound search information when doing a recursive descent of an r-tree.") :copy-slots) (defmethod make-container ((class (eql 'nearest-neighbor-node)) &rest args) (apply #'make-nearest-neighbor-node args)) (defun make-nearest-neighbor-node (&rest args) (apply #'make-instance 'nearest-neighbor-node args)) (defmethod r-tree-item->nearest-neighbor-node ((item r-tree-item) distance) (make-container 'nearest-neighbor-node :mbr (mbr item) :spatial-object (spatial-object item) :neighbor-distance distance)) (defmethod nearest-neighbor-node-return-value ((node nearest-neighbor-node)) (spatial-object node)) (defmethod print-object ((n nearest-neighbor-node) stream) (print-unreadable-object (n stream :type t :identity t) (format stream "~A ~A" (neighbor-distance n) (spatial-object n)))) ;;; nearest-neighbor-node (defclass* labelled-nearest-neighbor-node (nearest-neighbor-node label-mixin) () (:documentation "An analagous nearest-neighbor-node class for labelled items.")) (defmethod make-container ((class (eql 'labelled-nearest-neighbor-node)) &rest args) (apply #'make-labelled-nearest-neighbor-node args)) (defun make-labelled-nearest-neighbor-node (&rest args) (apply #'make-instance 'labelled-nearest-neighbor-node args)) (defmethod r-tree-item->nearest-neighbor-node ((item r-tree-labelled-item) distance) (make-container 'labelled-nearest-neighbor-node :mbr (mbr item) :spatial-object (spatial-object item) :label (label item) :neighbor-distance distance)) (defmethod nearest-neighbor-node-return-value ((node labelled-nearest-neighbor-node)) (list (spatial-object node) (label node))) ;;; nearest-neighbor-node-sorter :: nearest-nighbor-node -> ;;; nearest-neighbor-node -> boolean (defmethod nearest-neighbor-sorter ((nn1 nearest-neighbor-node-mixin) (nn2 nearest-neighbor-node-mixin)) (> (neighbor-distance nn1) (neighbor-distance nn2))) ;;; nearest-neighbors :: (t) -> fixnum -> (t) (defmethod nearest-neighbors ((r-tree r-tree) (item list) k &key (promise-pruning t)) (nearest-neighbors r-tree (make-container 'r-tree-item item) k :promise-pruning promise-pruning)) ;;; nearest-neighbors :: r-tree -> r-tree-item -> fixnum -> (t) ;;; Some explanation on the 'sort' call here: ;;; Since heaps are just vectors, and collect-items iterates through ;;; the vector, we won't get the nearest-neighbor items in their sorted order. ;;; We could write a new collect-items method for heaps, but that would require ;;; not side afffecting the current heap, so we'd have to copy each element ;;; out and put it in a new heap (so the heap-node objects don't change) and ;;; then pop the biggest item off the top. This seems a bit too much work ;;; for something we don't guarentee of collect-items anyway, so using ;;; sort is a workable and clean solution (defmethod nearest-neighbors ((r-tree r-tree) (item r-tree-item) k &key (promise-pruning t)) (setf *promise-pruning* promise-pruning) (setf *nnscount* 0) (aif (r-tree-root-node r-tree) (let ((neighbors (make-container 'heap-container :sorter #'nearest-neighbor-sorter))) (nearest-neighbor-search it item neighbors k) (values (collect-items neighbors :transform #'nearest-neighbor-node-return-value) *nnscount*)) (values nil 0))) #+WAIT (defmethod nearest-neighbors ((r-tree r-tree) (item r-tree-item) k &key (promise-pruning t)) (setf *promise-pruning* promise-pruning) (setf *nnscount* 0) (aif (r-tree-root-node r-tree) (let ((neighbors (make-container 'heap-container :sorter #'nearest-neighbor-sorter))) (nearest-neighbor-search it item neighbors k) (values (sort (collect-items neighbors :transform #'nearest-neighbor-node-return-value) #'< :key (curry #'euclidean-distance* (spatial-object item))) *nnscount*)) (values nil 0))) ;;; minimum-distance-metric :: r-tree-item -> mbr -> fixnum (defmethod minimum-distance-metric ((item r-tree-item) (mbr mbr)) (loop for i from 0 to (1- (/ (size mbr) 2)) for p in (spatial-object item) sum (let* ((min (min-point mbr i)) (max (max-point mbr i))) (cond ((< p min) (euclidean-distance* p min)) ((> p max) (euclidean-distance* p max)) (t 0.0))))) ;;; minimum-distance-metric :: r-tree-item -> r-tree-record -> fixnum (defmethod minimum-distance-metric ((item r-tree-item) (record r-tree-record)) (minimum-distance-metric item (mbr record))) ;;; min-maximum-distance-metric :: r-tree-item -> r-tree-record -> fixnum (defmethod min-maximum-distance-metric ((item r-tree-item) (record r-tree-record)) (min-maximum-distance-metric item (mbr record))) ;;; min-maximum-distance-metric :: r-tree-item -> mbr -> fixnum (defmethod min-maximum-distance-metric ((item r-tree-item) (mbr mbr)) (flet ((closest-hyperplane (p min max) (if (<= p (/ (+ min max) 2.0)) min max)) (furthest-hyperplane (p min max) (if (>= p (/ (+ min max) 2.0)) min max))) (loop for i from 0 to (1- (/ (size mbr) 2)) for p in (spatial-object item) with s = (loop for i from 0 to (1- (/ (size mbr) 2)) for p in (spatial-object item) sum (expt (- p (furthest-hyperplane p (min-point mbr i) (max-point mbr i))) 2)) minimize (+ (- s (expt (- p (furthest-hyperplane p (min-point mbr i) (max-point mbr i))) 2)) (expt (- p (closest-hyperplane p (min-point mbr i) (max-point mbr i))) 2))))) ;;; euclidean-distance :: r-tree-item -> r-tree-item -> float (defmethod euclidean-distance ((item r-tree-item) (item2 r-tree-item)) (sqrt (euclidean-distance* item item2))) ;;; euclidean-distance :: (float) -> (float) -> float (defmethod euclidean-distance ((pt-0 list) (pt-1 list)) (sqrt (euclidean-distance* pt-0 pt-1))) ;;; euclidean-distance* :: number -> number -> float (defmethod euclidean-distance* ((pt-0 number) (pt-1 number)) (expt (- pt-1 pt-0) 2)) ;;; euclidean-distance :: number -> number -> float (defmethod euclidean-distance ((pt-0 number) (pt-1 number)) (sqrt (euclidean-distance* pt-0 pt-1))) ;;; euclidean-distance* :: r-tree-item -> r-tree-item -> float ;;; Just like euclidean-distance but without the square root (defmethod euclidean-distance* ((item r-tree-item) (item2 r-tree-item)) (euclidean-distance* (spatial-object item) (spatial-object item2))) ;;; euclidean-distance* :: (fixnum) -> (fixnum) -> float ;;; Just like euclidean-distance but without the square root (defmethod euclidean-distance* ((pt-0 list) (pt-1 list)) (loop for x in pt-0 for y in pt-1 sum (expt (- x y) 2))) ;;; euclidean-distance* :: r-tree-item -> (fixnum) -> float (defmethod euclidean-distance* ((item r-tree-item) (item2 list)) (euclidean-distance* (spatial-object item) item2)) (defmethod euclidean-distance* ((item list) (item2 r-tree-item)) (euclidean-distance* item (spatial-object item2))) ;;; sort-branch-list :: (r-tree-records) -> r-tree-item -> fn -> (r-tree-records) (defmethod sort-branch-list ((records list) (item r-tree-item) &key (key (curry #'minimum-distance-metric item))) (sort records #'< :key key)) ;;; nearest-neighbor-search :: r-tree-leaf-node -> r-tree-item -> ;;; heap-container -> number -> nil ;;; When we reach a leaf node, we add the spatial object is it is better than ;;; our worst nearest-neighbor estimates so far, or if we don't have enough ;;; nearest-neighbor estimates yet. (defmethod nearest-neighbor-search ((node r-tree-leaf-node) (item r-tree-item) (neighbors heap-container) k) (incf *nnscount*) (flet ((add-item (item distance) (insert-item neighbors (r-tree-item->nearest-neighbor-node item distance)))) (iterate-container node #'(lambda (item2) (let ((distance (euclidean-distance* item item2))) (cond ((< (size neighbors) k) (add-item item2 distance)) ((<= distance (neighbor-distance (biggest-item neighbors))) (delete-biggest-item neighbors) (add-item item2 distance)) (t nil)))))) nil) ;;; nearest-neighbor-search :: r-tree-internal-node -> r-tree-item -> ;;; heap-container -> number -> nil (defmethod nearest-neighbor-search ((node r-tree-internal-node) (item r-tree-item) (neighbors heap-container) k) (incf *nnscount*) (labels ((helper (records) (when records (let ((record (first records))) (when (and (promise-record? record) (heap-node-index (promise record))) (delete-item neighbors (promise record))) (when (or (< (size neighbors) k) (< (minimum-distance-metric item record) (neighbor-distance (biggest-item neighbors)))) (nearest-neighbor-search (r-tree-next-node record) item neighbors k)) (helper (rest records)))))) (if *promise-pruning* (helper (apply-promise-pruning (sort-branch-list (collect-elements node) item) item neighbors k)) (helper (sort-branch-list (collect-elements node) item))))) ;;; apply-promise-pruning (defmethod apply-promise-pruning ((records list) (item r-tree-item) (neighbors heap-container) k) (cons (first records) (mapcar #'(lambda (record) (let ((minmax (min-maximum-distance-metric item record))) (cond ((or (< (size neighbors) k) (< minmax (neighbor-distance (biggest-item neighbors)))) (unless (< (size neighbors) k) (delete-biggest-item neighbors)) (multiple-value-bind (heap promise) (insert-item neighbors (make-container 'promise minmax)) (declare (ignore heap)) (make-container 'promise-record record promise))) (t record)))) (rest records)))) #| OLD STUFF FOR ORIGINAL 1995 ALGORITHM... ;;; nearest-neighbor-search :: r-tree-internal-node -> r-tree-item -> ;;; heap-container -> number -> nil ;;; ---------------------------------------------------------------------------\ #+OLD (defmethod nearest-neighbor-search ((node r-tree-internal-node) (item r-tree-item) (neighbors heap-container)) (labels ((helper (records) (when records (let ((rec (first records)) (others (rest records))) (nearest-neighbor-search (r-tree-next-node rec) item neighbors k) (helper (prune-up-branch-list others item neighbors k)))))) (helper (prune-down-branch-list (sort-branch-list (collect-elements node) item) item neighbors k)))) ;;; prune-down-branch-list :: (r-tree-record) -> r-tree-item -> ;;; heap-container -> number -> (r-tree-record) (defmethod prune-down-branch-list ((records list) (item r-tree-item) (neighbors heap-container) k) (cond ((/= k (size neighbors)) records) (t (prune-down-branches records item neighbors)))) ;;; prune-up-branch-list :: (r-tree-record) -> r-tree-item -> ;;; heap-container -> number -> (r-tree-record) (defmethod prune-up-branch-list ((records list) (item r-tree-item) (neighbors heap-container) k) (cond ((/= k (size neighbors)) records) (t (prune-up-branches records item neighbors)))) ;;; prune-down-branches :: (r-tree-record) -> r-tree-item -> heap-container -> ;;; (r-tree-record) ;;; prune records from our list that have min-distance greater than ;;; min-max-distance of some other record, if that min-distance is greater ;;; than the distance of the farthest node (defmethod prune-down-branches ((records list) (item r-tree-item) (neighbors heap-container)) (let ((min-minmax (apply #'min (mapcar (curry #'min-maximum-distance-metric item) records)))) (delete-if #'(lambda (record) (let ((min (minimum-distance-metric item record))) (and (> min min-minmax) (> min (neighbor-distance (biggest-item neighbors)))))) records))) ;;; prune-up-branches :: (r-tree-record) -> r-tree-item -> heap-container -> ;;; (r-tree-record) (defmethod prune-up-branches ((records list) (item r-tree-item) (neighbors heap-container)) (let ((min-dist (neighbor-distance (biggest-item neighbors)))) (delete-if-not #'(lambda (record) (< (minimum-distance-metric item record) min-dist)) records))) |# cl-containers-20170403-git/dev/ring-buffers.lisp000066400000000000000000000064001306646076300213510ustar00rootroot00000000000000(in-package #:containers) ;;; Ring Buffers ;;; ;;; Code adapted from ANSI Common Lisp by Paul Graham (chapter 7) ;;; ;;; A ring buffer is a bounded queue. It supports: ;;; item-at (setf item-at) ;;; insert-item, dequeue, empty!, empty-p, size, total-size, first-element (defclass* ring-buffer (abstract-queue bounded-container-mixin iteratable-container-mixin concrete-container) ((contents :initarg :contents :reader contents) (buffer-start :initform 0 :reader buffer-start) (buffer-end :initform 0 :reader buffer-end) (total-size :initarg :total-size :reader total-size))) (defun make-ring-buffer (size) (make-instance 'ring-buffer :contents (make-array size) :total-size size)) (defmethod make-container ((class (eql 'ring-buffer)) &rest args) (let ((total-size (getf args :total-size 1))) (remf args :total-size) (make-ring-buffer total-size))) ;;?? the (first indexes) is odd... (defmethod item-at ((container ring-buffer) &rest indexes) (declare (dynamic-extent indexes)) (svref (contents container) (mod (first indexes) (total-size container)))) (defmethod item-at! ((container ring-buffer) value &rest indexes) (declare (dynamic-extent indexes)) (setf (svref (contents container) (mod (first indexes) (total-size container))) value)) (defmethod increment-end ((container ring-buffer)) (with-slots (buffer-end buffer-start) container (when (and (>= buffer-end (total-size container)) (= (mod buffer-end (total-size container)) buffer-start)) (incf buffer-start)) (incf buffer-end))) (defmethod next-item ((container ring-buffer)) (increment-end container) (current-item container)) (defmethod current-item ((container ring-buffer)) (item-at container (buffer-end container))) (defmethod insert-item ((container ring-buffer) item) (prog1 (setf (item-at container (buffer-end container)) item) (increment-end container))) (defmethod delete-first ((container ring-buffer)) (with-slots (buffer-start) container (prog1 (item-at container buffer-start) (incf buffer-start)))) (defmethod empty! ((container ring-buffer)) (with-slots (buffer-end buffer-start) container (setf buffer-start 0 buffer-end 0)) (values)) #+Ignore (defmethod total-size ((container ring-buffer)) (total-size container)) (defmethod size ((container ring-buffer)) (- (buffer-end container) (buffer-start container))) (defmethod first-element ((container ring-buffer)) (item-at container (buffer-start container))) (defmethod (setf first-element) (value (container ring-buffer)) (setf (item-at container (buffer-start container)) value)) (defmethod iterate-nodes ((container ring-buffer) fn) (loop for index from (buffer-start container) to (1- (buffer-end container)) do (funcall fn (item-at container index)))) #+No ;; screws with the buffer pointers (defmethod iterate-nodes ((container ring-buffer) fn) (loop repeat (total-size container) with item = (current-item container) do (funcall fn item) (setf item (next-item container)))) cl-containers-20170403-git/dev/stacks.lisp000066400000000000000000000035221306646076300202520ustar00rootroot00000000000000(in-package #:containers) ;;; Abstract Stack interface ;;; ;;; Basic and much loved first-in-last-out container. ;;; ;;; Supports: ;;; insert-item, size, empty-p, empty!, first-element, ;;; pop-item, push-item (= insert-item) (defclass* abstract-stack (initial-contents-mixin iteratable-container-mixin ordered-container-mixin) ()) (defmethod (setf first-element) (value (stack abstract-stack)) ;;?? should this fail when stack is empty (pop-item stack) (insert-item stack value)) (defmethod push-item ((stack abstract-stack) item) (insert-item stack item)) ;;; Stack (defclass* stack-container (uses-contents-mixin abstract-stack concrete-container) ((contents :unbound r) (container-type nil ir)) (:default-initargs :container-type 'list-container)) (defmethod make-container-for-contents ((container stack-container) &rest args) (apply #'make-container (container-type container) args)) (defmethod first-element ((container stack-container)) (first-element (contents container))) (defmethod (setf first-element) (value (container stack-container)) (setf (first-element (contents container)) value)) (defmethod pop-item ((container stack-container)) (delete-first (contents container))) (defmethod insert-item ((container stack-container) item) (insert-item (contents container) item)) (defmethod size ((container stack-container)) (size (contents container))) (defmethod empty-p ((container stack-container)) (empty-p (contents container))) (defmethod empty! ((container stack-container)) (empty! (contents container)) (values)) (defmethod search-for-item ((container stack-container) item &key (test 'eq) (key 'identity)) (search-for-item (contents container) item :test test :key key))cl-containers-20170403-git/dev/table-container.lisp000066400000000000000000000217571306646076300220430ustar00rootroot00000000000000(in-package #:containers) (export '(add-index delete-index insert-record delete-record update-record update-index table-named table-names lookup-record find-record-if column-names table-container empty-tables!)) #+Ignore (declaim (optimize (debug 3))) ;;; biassociative-container ;;; ;;; only good for 1-1 maps at this point (defclass* biassociative-container (concrete-container key-value-iteratable-container-mixin initial-element-mixin biassociative-container-mixin test-container-mixin ) ((contents-> :unbound r) (contents<- :unbound r)) (:default-initargs :test #'eq)) (defmethod initialize-instance :after ((object biassociative-container) &key test) (setf (slot-value object 'contents->) (make-container 'simple-associative-container :test test) (slot-value object 'contents<-) (make-container 'simple-associative-container :test test))) (defmethod size ((container biassociative-container)) (size (contents-> container))) (defmethod empty! ((container biassociative-container)) (empty! (contents-> container)) (empty! (contents<- container)) (values)) (defmethod iterate-elements ((container biassociative-container) fn) (iterate-elements (contents-> container) fn)) (defmethod iterate-keys ((container biassociative-container) fn) (iterate-elements (contents<- container) fn)) (defmethod iterate-key-value ((container biassociative-container) function) (iterate-key-value (contents-> container) function)) (defmethod iterate-value-key ((container biassociative-container) function) (iterate-key-value (contents<- container) function)) (defmethod item-at ((container biassociative-container) &rest indexes) (declare (dynamic-extent indexes)) (item-at-1 (contents-> container) (first indexes))) (defmethod item-at! ((container biassociative-container) value &rest indexes) (setf (item-at-1 (contents-> container) (first indexes)) value (item-at-1 (contents<- container) value) (first indexes))) (defmethod key-at ((container biassociative-container) value) (item-at-1 (contents<- container) value)) #+Test (let ((c (make-container 'biassociative-container))) (setf (item-at c :a) 1) (setf (item-at c :b) 2) (iterate-keys c #'print) (iterate-elements c #'print) (print (key-at c 2)) (print (key-at c 1))) ;;; table-container (defclass* table-container (key-value-iteratable-container-mixin concrete-container) ((unique-counter 0 r) (contents :unbound r) (indexes :unbound r) (index :unbound a) (prototype :unbound ir) (update-queue :unbound r) (primary-key :unbound r))) (defmethod print-object ((container table-container) stream) (print-unreadable-object (container stream :type t :identity t) (format stream "~A ~D" (class-name (prototype container)) (size container)))) (defmethod initialize-instance :after ((object table-container) &key) (setf (slot-value object 'contents) (make-container 'biassociative-container) (slot-value object 'indexes) (make-container 'alist-container) (slot-value object 'update-queue) (make-container 'basic-queue))) (defclass* table-index () ((table nil ir) (key nil ir) (kind nil ir) (test 'eq ir) (index nil r))) (defmethod initialize-instance :after ((object table-index) &key test) (setf (slot-value object 'index) (make-container 'simple-associative-container :test test))) (defgeneric add-index (table name index-kind function test) (:documentation "")) (defgeneric delete-index (table name) (:documentation "")) (defgeneric insert-record (table object) (:documentation "")) (defgeneric delete-record (table object) (:documentation "")) (defgeneric update-index (index) (:documentation "")) (defgeneric save-pending-updates (table) (:documentation "")) (defmethod add-index ((object table-container) (name symbol) (index-kind symbol) key test) (setf (item-at (indexes object) name) (make-instance 'table-index :table object :kind index-kind :key key :test test)) (when (eq index-kind :primary-key) (setf (slot-value object 'primary-key) name)) (update-index (item-at (indexes object) name))) (defmethod delete-index ((object table-container) (name symbol)) (delete-item-at (indexes object) name)) (defmethod update-index ((index table-index)) (let ((index-data (index index)) (index-key (key index))) (iterate-key-value (contents (table index)) (lambda (key element) ;;?? not right (setf (item-at index-data (funcall index-key element)) key))))) (defmethod update-index-for-object (index object object-id) (setf (item-at (index index) (funcall (key index) object)) object-id)) (defmethod update-indexes-for-object (table object) (let ((object-id (key-at (contents table) object))) (iterate-elements (indexes table) (lambda (index) (update-index-for-object index object object-id))))) (defmethod insert-record ((table table-container) object) (setf (item-at (contents table) (incf (slot-value table 'unique-counter))) object) (update-indexes-for-object table object)) (defmethod find-record ((table table-container) (index-name symbol) value) (item-at (contents table) (item-at (index (item-at (indexes table) index-name)) value))) (defmethod lookup-record ((table table-container) value &optional (error? nil)) (cond ((find-record table (primary-key table) value)) ((not error?) (values nil)) (t (error 'record-not-found-error :table table :value value)))) (defmethod find-record-if ((table table-container) predicate &optional (error? nil)) (cond ((block searcher (iterate-elements table (lambda (element) (when (funcall predicate element) (return-from searcher element)))))) ((not error?) (values nil)) (t ;;?? this is a bit wonky (error 'record-not-found-error :table table :value predicate)))) (defmethod size ((container table-container)) (size (contents container))) (defmethod iterate-container ((container table-container) fn) (iterate-elements (contents container) fn)) #+Test (defclass* foo (u:numbered-instances-mixin) ((value nil ia))) #+Test (let ((c (make-container 'table-container))) (add-index c 'id 'u:object-number) (add-index c 'value 'value) (insert-record c (make-instance 'foo :value 1)) (insert-record c (make-instance 'foo :value 2)) (insert-record c (make-instance 'foo :value 3)) c) (defmethod column-names ((container table-container)) (mopu:slot-names (prototype container))) (defmethod empty! ((container table-container)) (empty! (contents container)) (empty! (update-queue container)) (setf (slot-value container 'unique-counter) 0)) ;;; "database" (defclass* database-mixin () ((database-tables :unbound r)) :export-slots (:export-p t)) (defmethod initialize-instance :after ((object database-mixin) &key) (setf (slot-value object 'database-tables) (make-container 'alist-container :initial-element-fn (lambda () (make-container 'associative-container))))) (defmethod table-named ((database database-mixin) (table symbol)) (item-at (database-tables database) table)) (defmethod (setf table-named) ((value table-container) (database database-mixin) (table symbol)) (setf (item-at (database-tables database) table) value)) (defgeneric table-names (database) (:documentation "Returns a list of the names of the tables in a database.") (:method ((database database-mixin)) (collect-keys (database-tables database)))) (defmethod empty! ((database database-mixin)) (empty! (database-tables database))) (defmethod empty-tables! ((database database-mixin)) (iterate-elements (database-tables database) #'empty!)) ;;; a bit wonky (defun apply-filter-to-database (database filter) (iterate-elements (database-tables database) (lambda (table) (unless (member 'filtered-container-mixin (mopu:superclasses table) :key #'class-name) (change-class table (find-matching-container-class (list (type-of table) 'filtered-container-mixin)))) (setf (element-filter table) filter)))) #+Test (iterate-elements (database-tables (ib::information-broker)) (lambda (table) (change-class table 'table-container))) (defun print-schema (database) (iterate-key-value (database-tables database) (lambda (name table) (format t "~%~A~% ~{~A~^, ~}" name (column-names table))))) cl-containers-20170403-git/dev/trees.lisp000066400000000000000000001024611306646076300201060ustar00rootroot00000000000000(in-package #:containers) ;;; generic tree classes ;;; tree-container (defclass* abstract-tree-container (abstract-container) ()) ;;; rooted-tree-container :: (defclass* rooted-tree-container (abstract-tree-container) ((root nil ia)) (:documentation "Base class of all trees with roots.")) (defclass* many-child-node (container-node-mixin iteratable-container-mixin) ()) (defmethod iterate-children ((node many-child-node) fn) (iterate-nodes node fn)) (defmethod has-children-p ((node many-child-node)) (iterate-children node (lambda (v) (declare (ignore v)) (return-from has-children-p t))) (values nil)) (defmethod find-child-node ((node many-child-node) child &key (test #'eq) (key #'identity)) (find child (children node) :test test :key key)) (defclass* many-ordered-child-node (many-child-node vector-container-mixin) () (:documentation "A node with many ordered children is a vector")) (defmethod children ((node many-ordered-child-node)) (collect-elements node)) (defclass* many-unordered-child-node (many-child-node contents-as-list-mixin) ((contents nil ia)) (:documentation "Children are unordered")) ;;; Binary-Search-Trees ;; we sort keys of the nodes using sorter; we test equality with test. (defclass* binary-search-tree (container-uses-nodes-mixin initial-contents-mixin sorted-container-mixin findable-container-mixin iteratable-container-mixin rooted-tree-container concrete-container) ((tree-size 0 iar)) (:default-initargs :key 'identity :test 'eq :sorter '<)) (defclass* bst-node (two-child-node) ((tree nil ia))) (defmethod make-node-for-container ((tree binary-search-tree) (item t) &key) (if item (make-instance 'bst-node :element item) nil)) (defmethod node-empty-p ((node bst-node)) (null node)) (defmethod node-empty-p ((node (eql nil))) t) (defmethod print-object ((o bst-node) stream) (print-unreadable-object (o stream :type t) (format stream "~A" (element o)))) ;;; Standard container operations for BST's (defmethod size ((tree binary-search-tree)) (tree-size tree)) (defmethod size ((node bst-node)) (let ((count 0)) (walk-tree node #'(lambda (item) (declare (ignore item)) (incf count))) count)) (defmethod empty-p ((tree binary-search-tree)) (node-empty-p (root tree))) (defmethod empty! ((tree binary-search-tree)) (setf (root tree) (make-node-for-container tree nil)) (setf (tree-size tree) 0) (values)) ;;; Search, max, min, etc. (defmethod find-item ((tree binary-search-tree) (item bst-node)) (let* ((key (key tree)) (test (test tree)) (sorter (sorter tree)) (key-item (funcall key (element item))) (current (root tree)) (not-found? nil)) (loop while (and (not (node-empty-p current)) (setf not-found? (not (funcall test key-item (funcall key (element current)))))) do (if (funcall sorter key-item (funcall key (element current))) (setf current (left-child current)) (setf current (right-child current)))) (if (and (not (node-empty-p current)) (not not-found?)) current nil))) (defmethod find-successor-item ((tree binary-search-tree) (item bst-node)) "Find the item equal to or the next greater than item" (with-slots (key test sorter) tree (let ((key-item (funcall key (element item)))) (labels ((node-equal-p (current) (funcall test key-item (funcall key (element current)))) (compare-lt (current) (funcall sorter key-item (funcall key (element current)))) (final-node (prior) (if (compare-lt prior) prior (let ((s (successor tree prior))) (if (node-empty-p s) nil s)))) (find-successor (current prior) (cond ((node-empty-p current) (when prior (final-node prior))) ((node-equal-p current) current) ((compare-lt current) (find-successor (left-child current) current)) (t (find-successor (right-child current) current))))) (find-successor (root tree) nil))))) (defmethod find-node ((tree binary-search-tree) (item t)) (find-item tree (make-node-for-container tree item))) (defmethod find-successor-node ((tree binary-search-tree) (item t)) (find-successor-item tree (make-node-for-container tree item))) (defmethod first-element ((node bst-node)) (element (first-node node))) (defmethod first-node ((node bst-node)) (let ((current node)) (loop while (not (node-empty-p (left-child current))) do (setf current (left-child current))) current)) (defmethod (setf first-element) (value (node bst-node)) (let ((current node)) (loop while (not (node-empty-p (left-child current))) do (setf current (left-child current))) (setf (element current) value))) (defmethod first-element ((tree binary-search-tree)) (first-element (root tree))) (defmethod first-node ((tree binary-search-tree)) (first-node (root tree))) (defmethod (setf first-element) (value (tree binary-search-tree)) (setf (first-element (root tree)) value)) (defmethod last-element ((node bst-node)) (element (last-node node))) (defmethod last-node ((node bst-node)) (let ((current node)) (loop while (not (node-empty-p (right-child current))) do (setf current (right-child current))) current)) (defmethod last-node ((tree binary-search-tree)) (last-node (root tree))) (defmethod last-element ((tree binary-search-tree)) (last-element (root tree))) (defmethod (setf last-element) (value (node bst-node)) (let ((current node)) (loop while (not (node-empty-p (right-child current))) do (setf current (right-child current))) (setf (element current) value))) (defmethod (setf last-element) (value (tree binary-search-tree)) (setf (last-element (root tree)) value)) (defmethod successor ((tree binary-search-tree) (node bst-node)) (if (not (node-empty-p (right-child node))) (first-node (right-child node)) (let ((y (parent node))) (loop while (and (not (node-empty-p y)) (eq node (right-child y))) do (setf node y y (parent y))) y))) (defmethod predecessor ((tree binary-search-tree) (node bst-node)) (if (not (node-empty-p (left-child node))) (last-node (left-child node)) (let ((y (parent node))) (loop while (and (not (node-empty-p y)) (eq node (left-child y))) do (setf node y y (parent y))) y))) ;;; Insertion and deletion (defmethod insert-item ((tree binary-search-tree) (item bst-node)) (loop with key = (key tree) with y = (make-node-for-container tree nil) ; with test = (test tree) with sorter = (sorter tree) and x = (root tree) and key-item = (funcall key (element item)) while (not (node-empty-p x)) do (progn ;(format t "~A ~A~%" x y) (setf y x) (if (funcall sorter key-item (funcall key (element x))) (setf x (left-child x)) (setf x (right-child x)))) finally (progn (setf (parent item) y (tree item) tree) (incf (tree-size tree)) (if (node-empty-p y) (setf (root tree) item) (if (funcall sorter key-item (funcall key (element y))) (setf (left-child y) item) (setf (right-child y) item))))) tree) (defmethod delete-node ((tree binary-search-tree) (node bst-node)) (let* ((y (if (or (node-empty-p (left-child node)) (node-empty-p (right-child node))) node (successor tree node))) (x (if (left-child y) (left-child y) (right-child y)))) (when x (setf (parent x) (parent y))) (if (node-empty-p (parent y)) (setf (root tree) x) (if (equal y (left-child (parent y))) (setf (left-child (parent y)) x) (setf (right-child (parent y)) x))) (if (not (equal y node)) (setf (element node) (element y))) y)) (defmethod delete-node :after ((tree binary-search-tree) (node bst-node)) (decf (tree-size tree))) (defmethod delete-item ((tree binary-search-tree) (node bst-node)) (delete-node tree node)) (defmethod delete-item ((tree binary-search-tree) (item t)) (let ((found (find-node tree item))) (if found (delete-node tree found) tree))) (defmethod delete-item-if (test (tree binary-search-tree)) "Iterate over the nodes of the tree, deleting them if they match test." ;; As a first implementation, we use an inorder-walk to collect ;; matching nodes into a list and then delete them one at a time. (let ((to-delete nil)) (walk-tree-nodes (root tree) #'(lambda (node) (when (funcall test (element node)) (push node to-delete))) :inorder) (loop for node in to-delete do (delete-item tree node)))) (defmethod iterate-nodes ((tree binary-search-tree) fn) (inorder-walk-nodes tree fn)) ;;; Tree walking (defmethod inorder-walk ((tree binary-search-tree) walk-fn) (walk-tree (root tree) walk-fn :inorder)) (defmethod preorder-walk ((tree binary-search-tree) walk-fn) (walk-tree (root tree) walk-fn :preorder)) (defmethod postorder-walk ((tree binary-search-tree) walk-fn) (walk-tree (root tree) walk-fn :postorder)) (defmethod inorder-walk-nodes ((tree binary-search-tree) walk-fn) (walk-tree-nodes (root tree) walk-fn :inorder)) (defmethod preorder-walk-nodes ((tree binary-search-tree) walk-fn) (walk-tree-nodes (root tree) walk-fn :preorder)) (defmethod postorder-walk-nodes ((tree binary-search-tree) walk-fn) (walk-tree-nodes (root tree) walk-fn :postorder)) (defmethod walk-tree ((node bst-node) walk-fn &optional (mode :inorder)) (walk-tree-nodes node (lambda (x) (funcall walk-fn (element x))) mode)) (defmethod walk-tree ((node (eql nil)) walk-fn &optional (mode :inorder)) "Special case..." (declare (ignore mode walk-fn))) (defmethod walk-tree-nodes ((node bst-node) walk-fn &optional (mode :inorder)) (when (eq mode :preorder) (funcall walk-fn node)) (walk-tree-nodes (left-child node) walk-fn mode) (when (eq mode :inorder) (funcall walk-fn node)) (walk-tree-nodes (right-child node) walk-fn mode) (when (eq mode :postorder) (funcall walk-fn node))) (defmethod walk-tree-nodes ((node (eql nil)) walk-fn &optional (mode :inorder)) "Special case..." (declare (ignore walk-fn mode))) ;;; Red-Black Trees ;;; ;;; A Red-black tree is a binary search tree whose nodes have a color ;;; the insert and delete operations preserve certain properties of this ;;; color that ensure that the tree stays balanced and therefore that all ;;; operations are O( lg n ) ;;; ;;; Note that we use *rbt-empty-node* (instead of nil) to signal an empty ;;; node. This makes delete-item cleaner but means that you need to be careful ;;; in the rest of the code to use node-empty-p instead of just assuming that ;;; a node will be nil. (defconstant +rbt-color-black+ 0) (defconstant +rbt-color-red+ 1) (defclass rbt-empty-node (red-black-node) () (:documentation "Subclass the empty node so that it's possible to quickly determine if a node is empty using TYPEP.")) (defclass* red-black-tree (binary-search-tree) ((empty-node :type red-black-node :initarg :empty-node :reader empty-node)) (:default-initargs :key #'identity :test #'eq :sorter #'<)) (defmethod initialize-instance :after ((object red-black-tree) &key) (let ((e (make-instance 'rbt-empty-node :right-child nil :left-child nil :element nil :tree object :empty-p t))) (setf (slot-value object 'empty-node) e) (setf (slot-value object 'root) e))) (defclass* red-black-node (bst-node) ((color :initform +rbt-color-black+ :initarg :rbt-color :accessor rbt-color) (right-child :initarg :right-child) ; add initargs (left-child :initarg :left-child))) (defmethod initialize-instance :after ((node red-black-node) &key parent left-child right-child empty-p) (let ((e (if empty-p ;; This is the initialisation of the empty node itself node ;; ELSE: Find the empty node in the tree (empty-node (tree node))))) (setf (slot-value node 'parent) (or parent e)) (setf (slot-value node 'left-child) (or left-child e)) (setf (slot-value node 'right-child) (or right-child e)))) (defmethod node-empty-p ((node red-black-node)) (typep node 'rbt-empty-node)) (defmethod make-node-for-container ((tree red-black-tree) (item t) &key) (if item (make-instance 'red-black-node :element item :tree tree) (empty-node tree))) (defmethod print-object ((o red-black-node) stream) (format stream "#" (if (= (rbt-color o) +rbt-color-black+) "B" "R") (element o))) (defmethod rotate-left ((tree binary-search-tree) (x two-child-node)) (assert (not (eq (right-child x) (empty-node tree)))) (let ((y (right-child x))) ;; turn y's left subtree into x's right subtree (setf (right-child x) (left-child y)) (when (not (node-empty-p (left-child y))) (setf (parent (left-child y)) x)) ;; Link's x's parent to y (setf (parent y) (parent x)) (if (node-empty-p (parent x)) (setf (root tree) y) (if (eq x (left-child (parent x))) (setf (left-child (parent x)) y) (setf (right-child (parent x)) y))) ;; put x on y's left (setf (left-child y) x (parent x) y))) (defmethod rotate-right ((tree binary-search-tree) (x two-child-node)) (assert (not (eq (left-child x) (empty-node tree)))) (let ((y (left-child x))) ;; turn y's right subtree into x's left subtree (setf (left-child x) (right-child y)) (when (not (node-empty-p (right-child y))) (setf (parent (right-child y)) x)) ;; Link's x's parent to y (setf (parent y) (parent x)) (if (node-empty-p (parent x)) (setf (root tree) y) (if (eq x (right-child (parent x))) (setf (right-child (parent x)) y) (setf (left-child (parent x)) y))) ;; put x on y's left (setf (right-child y) x (parent x) y))) (defmethod insert-item :after ((tree red-black-tree) (item bst-node)) (assert item) (setf (rbt-color item) +rbt-color-red+) (let ((y nil)) (loop while (and (not (eq item (root tree))) (= (rbt-color (parent item)) +rbt-color-red+)) do (if (eq (parent item) (left-child (parent (parent item)))) (progn (setf y (right-child (parent (parent item)))) (if (= (rbt-color y) +rbt-color-red+) (progn (setf (rbt-color (parent item)) +rbt-color-black+ (rbt-color y) +rbt-color-black+ (rbt-color (parent (parent item))) +rbt-color-red+ item (parent (parent item)))) ;; ELSE (progn (when (eq item (right-child (parent item))) (setf item (parent item)) (rotate-left tree item)) (setf (rbt-color (parent item)) +rbt-color-black+ (rbt-color (parent (parent item))) +rbt-color-red+) (rotate-right tree (parent (parent item)))))) ;; ELSE (progn (setf y (left-child (parent (parent item)))) (if (= (rbt-color y) +rbt-color-red+) (progn (setf (rbt-color (parent item)) +rbt-color-black+ (rbt-color y) +rbt-color-black+ (rbt-color (parent (parent item))) +rbt-color-red+ item (parent (parent item)))) ;; ELSE (progn (when (eq item (left-child (parent item))) (setf item (parent item)) (rotate-right tree item)) (setf (rbt-color (parent item)) +rbt-color-black+ (rbt-color (parent (parent item))) +rbt-color-red+) (rotate-left tree (parent (parent item)))))))) (setf (rbt-color (root tree)) +rbt-color-black+))) (defmethod delete-node ((tree red-black-tree) (item red-black-node)) (let ((e (empty-node tree)) (y nil) (x nil)) (if (or (eq (left-child item) e) (eq (right-child item) e)) (setf y item) (setf y (successor tree item))) (if (eq (left-child y) e) (setf x (right-child y)) (setf x (left-child y))) (setf (parent x) (parent y)) (if (eq (parent y) e) (setf (root tree) x) (if (eq y (left-child (parent y))) (setf (left-child (parent y)) x) (setf (right-child (parent y)) x))) (when (not (eq y item)) (setf (element item) (element y))) (when (= (rbt-color y) +rbt-color-black+) ;(break) (rb-delete-fixup tree x)) y)) (defmethod rb-delete-fixup ((tree red-black-tree) (x red-black-node)) (let ((w nil)) (loop while (and (not (eq x (root tree))) (eq (rbt-color x) +rbt-color-black+)) do ; (format t "~&RBDF: ~A " x) (if (eq x (left-child (parent x))) (progn (setf w (right-child (parent x))) ; (format t "RC ~A " w) (if (= (rbt-color w) +rbt-color-red+) (progn (setf (rbt-color w) +rbt-color-black+ (rbt-color (parent x)) +rbt-color-red+) (rotate-left tree (parent x)) (setf w (right-child (parent x))))) (if (and (eq (rbt-color (left-child w)) +rbt-color-black+) (eq (rbt-color (right-child w)) +rbt-color-black+)) (progn (setf (rbt-color w) +rbt-color-red+) (setf x (parent x))) (progn (if (= (rbt-color (right-child w)) +rbt-color-black+) (progn (setf (rbt-color (left-child w)) +rbt-color-black+ (rbt-color w) +rbt-color-red+) (rotate-right tree w) (setf w (right-child (parent x))))) (setf (rbt-color w) (rbt-color (parent x)) (rbt-color (parent x)) +rbt-color-black+ (rbt-color (right-child w)) +rbt-color-black+) (rotate-left tree (parent x)) (setf x (root tree))))) ;; ELSE (progn (setf w (left-child (parent x))) ;(format t "LC ~A " w) ;(break) (if (= (rbt-color w) +rbt-color-red+) (progn (setf (rbt-color w) +rbt-color-black+ (rbt-color (parent x)) +rbt-color-red+) (rotate-right tree (parent x)) (setf w (left-child (parent x))))) (if (and (eq (rbt-color (right-child w)) +rbt-color-black+) (eq (rbt-color (left-child w)) +rbt-color-black+)) (progn (setf (rbt-color w) +rbt-color-red+) (setf x (parent x))) (progn (if (= (rbt-color (left-child w)) +rbt-color-black+) (progn (setf (rbt-color (right-child w)) +rbt-color-black+ (rbt-color w) +rbt-color-red+) (rotate-left tree w) (setf w (left-child (parent x))) ;(break) )) (setf (rbt-color w) (rbt-color (parent x)) (rbt-color (parent x)) +rbt-color-black+ (rbt-color (left-child w)) +rbt-color-black+) (rotate-right tree (parent x)) (setf x (root tree))))))) (setf (rbt-color x) +rbt-color-black+))) ;;; Misc (defmethod walk-tree-nodes ((node rbt-empty-node) walk-fn &optional (mode :inorder)) "Special case..." (declare (ignore walk-fn mode))) (defmethod walk-tree ((node rbt-empty-node) walk-fn &optional (mode :inorder)) "Special case..." (declare (ignore walk-fn mode))) (defmethod height ((node two-child-node)) (let ((result 0)) (loop while node do (incf result) (setf node (parent node))) result)) (defmethod height ((tree binary-search-tree)) (let ((result 0)) (walk-tree-nodes (root tree) #'(lambda (n) (let ((h (height n))) (when (> h result) (setf result h))))) result)) ;;; Splay Tree ;;; ;;; A splay tree implementation based on openmcl implementation ;;; and Goodrich and Tamassia "Algorithm Design" (defmethod item-at ((tree binary-search-tree) &rest indexes) (declare (dynamic-extent indexes)) (do* ((test (test tree)) (sorter (sorter tree)) (node (root tree))) ((or (null node) (node-empty-p node))) (let ((key-of-node (funcall (key tree) (element node)))) (if (funcall test (first indexes) key-of-node) (return node) (if (funcall sorter (first indexes) key-of-node) (setq node (left-child node)) (setq node (right-child node))))))) (defmethod update-element ((tree binary-search-tree) (value t) &rest indexes) (declare (dynamic-extent indexes)) (let ((node (item-at tree (first indexes)))) (if node (setf (element node) value) (warn "Tree does not contain node with index ~A" (first indexes))) node)) #+test (update-element (let ((tree (make-instance 'binary-search-tree :test #'= :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(1 one))) (insert-item tree (make-bst-node '(2 two))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four)))) 'five 2) (defgeneric bst-node-is-left-child (node) (:documentation "Is this node the left child of its parent?") (:method ((node bst-node)) (let ((parent (parent node))) (and (equal node (left-child parent))))) (:method (item) (declare (ignore item)))) (defgeneric bst-node-is-right-child (node) (:documentation "Is this node the right child of its parent?") (:method ((node bst-node)) (let ((parent (parent node))) (and (equal node (right-child parent))))) (:method (item) (declare (ignore item)))) (defgeneric bst-node-set-right-child (node new-right) (:documentation "Set new-right as the right child of node") (:method ((node bst-node) (new-right bst-node)) (when (setf (right-child node) new-right) (setf (parent new-right) node))) (:method ((node bst-node) item) (declare (ignore item)) (setf (right-child node) nil))) #+test (bst-node-set-right-child (make-bst-node "node") nil) (defgeneric bst-node-set-left-child (node new-left) (:documentation "Set new-left as the left child of node") (:method ((node bst-node) (new-left bst-node)) (when (setf (left-child node) new-left) (setf (parent new-left) node))) (:method ((node bst-node) item) (declare (ignore item)) (setf (left-child node) nil))) #+test (bst-node-set-left-child (make-bst-node "foo") nil) (defgeneric bst-node-replace-child (node old-node new-node) (:documentation "Replace the child of this node.") (:method ((node bst-node) (old-node bst-node) (new-node bst-node)) (if (equal old-node (left-child node)) (bst-node-set-left-child node new-node) (bst-node-set-right-child node new-node)))) (defclass* splay-tree (binary-search-tree) () (:default-initargs :key 'identity :test 'eq :sorter '<)) (defgeneric splay-tree-rotate (tree node) (:documentation "rotate the node (and maybe the parent) until the node is the root of the tree") (:method ((tree binary-search-tree) (node bst-node)) (when (and node (null (equal node (root tree)))) (let* ((parent (parent node)) (grandparent (if parent (parent parent))) (was-left (bst-node-is-left-child node))) (if grandparent (bst-node-replace-child grandparent parent node) (setf (root tree) node (parent node) nil)) (if was-left (progn (bst-node-set-left-child parent (right-child node)) (bst-node-set-right-child node parent)) (progn (bst-node-set-right-child parent (left-child node)) (bst-node-set-left-child node parent)))))) (:method ((tree binary-search-tree) item) (declare (ignore item)))) (defgeneric splay-tree-splay (tree node) (:documentation "Preform the splay operation on the tree about this node rotating the node until it becomes the root") (:method ((tree binary-search-tree) item) (declare (ignore item))) (:method ((tree binary-search-tree) (node bst-node)) (do* () ((equal node (root tree))) (let* ((parent (parent node)) (grandparent (parent parent))) (cond ((null grandparent) (splay-tree-rotate tree node)) ; node is now root ((eq (bst-node-is-left-child node) (bst-node-is-left-child parent)) (splay-tree-rotate tree parent) (splay-tree-rotate tree node)) (t (splay-tree-rotate tree node) (splay-tree-rotate tree node))))))) (defmethod insert-item :after ((tree splay-tree) (node bst-node)) (splay-tree-splay tree node)) #+test (let ((tree (make-instance 'splay-tree :test #'equal :key #'first :sorter #'string-lessp))) (insert-item tree (make-bst-node '("s" south))) (insert-item tree (make-bst-node '("n" north))) (insert-item tree (make-bst-node '("e" east))) (insert-item tree (make-bst-node '("w" west)))) #+test (let ((tree (make-instance 'splay-tree :test #'= :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(1 one))) (insert-item tree (make-bst-node '(2 two))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four)))) (defmethod item-at ((tree splay-tree) &rest indexes) (declare (dynamic-extent indexes)) (do* ((test (test tree)) (sorter (sorter tree)) (node (root tree))) ((null node)) (let ((key-of-node (funcall (key tree) (element node)))) (if (funcall test (first indexes) key-of-node) (progn (splay-tree-splay tree node) (return node)) (if (funcall sorter (first indexes) key-of-node) (setq node (left-child node)) (setq node (right-child node))))))) (defmethod update-element ((tree splay-tree) (value t) &rest indexes) (declare (dynamic-extent indexes)) (let ((node (item-at tree (first indexes)))) (if node (setf (element node) value) (warn "Tree does not contain node with index ~A" (first indexes))) node)) #+test (update-element (let ((tree (make-instance 'splay-tree :test #'equal :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(1 one))) (insert-item tree (make-bst-node '(2 two))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four)))) 'five 4) (defmethod find-item ((tree splay-tree) (node bst-node)) (do* ((test (test tree)) (sorter (sorter tree)) (key (key tree)) (current (root tree))) ((null current)) (let ((key-of-current (funcall key (element current))) (element-of-current (element current))) (if (and (funcall test (funcall key (element node)) key-of-current) (funcall test (element node) element-of-current)) (progn (splay-tree-splay tree current) (return current)) (if (funcall sorter (funcall key (element node)) key-of-current) (setq current (left-child current)) (setq current (right-child current))))))) #+test (find-item (let ((tree (make-instance 'splay-tree :test #'equal :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(1 one))) (insert-item tree (make-bst-node '(2 two))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four)))) '(3 three)) #+test (find-item (let ((tree (make-instance 'splay-tree :test #'equal :key #'first :sorter #'string-lessp))) (insert-item tree (make-bst-node '("s" south))) (insert-item tree (make-bst-node '("n" north))) (insert-item tree (make-bst-node '("e" east))) (insert-item tree (make-bst-node '("w" west)))) '("s" south)) (defgeneric right-most-child (node) (:documentation "Walk down the right side of the tree until a leaf node is found, then return that node") (:method ((node bst-node)) (if (right-child node) (right-most-child (right-child node)) node))) ;;; must call find-item first to ensure proper amortized ;;; analysis - jjm (defmethod delete-node ((tree splay-tree) (node bst-node)) (if (find-item tree node) (let* ((old-root (root tree)) (new-root (right-most-child (left-child old-root))) (new-root-parent (parent new-root))) (bst-node-set-right-child (parent new-root) nil) (bst-node-set-left-child new-root (left-child old-root)) (bst-node-set-right-child new-root (right-child old-root)) (setf (parent new-root) nil (root tree) new-root) (splay-tree-splay tree new-root-parent) old-root) (warn "Item ~A not found in splay-tree" node))) (defmethod delete-item ((tree splay-tree) (item t)) (delete-node tree (make-node-for-container tree item))) #+test (let ((tree (make-instance 'splay-tree :test #'equal :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four))) (insert-item tree (make-bst-node '(5 five))) (insert-item tree (make-bst-node '(6 six))) (insert-item tree (make-bst-node '(7 seven))) (insert-item tree (make-bst-node '(8 eight))) (insert-item tree (make-bst-node '(10 ten))) (insert-item tree (make-bst-node '(11 eleven))) ;;(item-at tree 7) ;;(item-at tree 6) ;;(item-at tree 5) ;;(item-at tree 4) (item-at tree 3) (item-at tree 10) (item-at tree 8) (delete-item tree '(8 eight)) tree) (defmethod delete-item-at ((tree splay-tree) &rest indexes) (declare (dynamic-extent indexes)) (delete-item tree (item-at tree (first indexes)))) #+test (let ((tree (make-instance 'splay-tree :test #'equal :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four))) (insert-item tree (make-bst-node '(5 five))) (insert-item tree (make-bst-node '(6 six))) (insert-item tree (make-bst-node '(7 seven))) (insert-item tree (make-bst-node '(8 eight))) (insert-item tree (make-bst-node '(10 ten))) (insert-item tree (make-bst-node '(11 eleven))) ;;(item-at tree 7) ;;(item-at tree 6) ;;(item-at tree 5) ;;(item-at tree 4) (item-at tree 3) (item-at tree 10) (item-at tree 8) (delete-item-at tree 8) tree) #+test (let ((tree (make-instance 'splay-tree :test #'= :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(1 one))) (insert-item tree (make-bst-node '(2 two))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four)))) #+test (item-at (let ((tree (make-instance 'splay-tree :test #'= :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(1 one))) (insert-item tree (make-bst-node '(2 two))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four)))) 1) #+test (walk-tree (root (let ((tree (make-instance 'splay-tree :test #'= :key #'first :sorter #'<))) (insert-item tree (make-bst-node '(1 one))) (insert-item tree (make-bst-node '(2 two))) (insert-item tree (make-bst-node '(3 three))) (insert-item tree (make-bst-node '(4 four))) (item-at tree 4) tree)) #'(lambda (node) (format t "~%~A" node))) ;;; end splay tree ;;; *************************************************************************** ;;; * End of File * ;;; *************************************************************************** cl-containers-20170403-git/dev/union-find-container.lisp000066400000000000000000000033501306646076300230070ustar00rootroot00000000000000(in-package #:containers) ;;; Simple union-find data structure (defclass* union-find-node (parent-node-mixin container-node-mixin) ((rank 0 ir))) (defmethod initialize-instance :after ((object union-find-node) &key) ;; how kinky (setf (parent object) object)) (defmethod print-object ((o union-find-node) stream) (print-unreadable-object (o stream :type nil :identity t) (format stream "UFN: ~A, ~D" (element o) (rank o)))) (defmethod make-set (item) (make-instance 'union-find-node :element item)) (defmethod graft-nodes (node1 node2) (link-nodes (find-set node1) (find-set node2))) (defmethod find-set (item) (if (eq (parent item) item) item (setf (parent item) (find-set (parent item))))) (defmethod link-nodes (node1 node2) (if (> (rank node1) (rank node2)) (setf (parent node2) node1) (progn (setf (parent node1) node2) (when (= (rank node1) (rank node2)) (incf (slot-value node2 'rank)))))) ;;; union find (defclass* union-find-container (contents-as-hashtable-mixin) ()) (defmethod insert-item ((container union-find-container) item) (setf (item-at-1 (contents container) item) (make-instance 'union-find-node :element item)) item) (defmethod representative ((container union-find-container) item) (element (representative-node container item))) (defmethod representative-node ((container union-find-container) item) (find-set (item-at-1 (contents container) item))) #+Test (let ((a (make-set 'a)) (b (make-set 'b)) (c (make-set 'c)) (d (make-set 'd)) (e (make-set 'e)) (f (make-set 'f)) (g (make-set 'g))) (graft-nodes g c) (graft-nodes f e) (graft-nodes e d) (graft-nodes d c) (graft-nodes c b) (graft-nodes b a) f) cl-containers-20170403-git/dev/utilities-integration.lisp000066400000000000000000000003371306646076300233170ustar00rootroot00000000000000(in-package #:metatilities) (eval-when (:compile-toplevel) (export-exported-symbols '#:cl-containers '#:metatilities)) (make-load-form* containers:abstract-container) (make-load-form* containers:container-node-mixin) cl-containers-20170403-git/dev/vectors.lisp000066400000000000000000000123631306646076300204520ustar00rootroot00000000000000 (in-package #:containers) ;;; vector-container-mixin (defclass* vector-container-mixin (contents-as-array-mixin initial-contents-mixin ordered-container-mixin typed-container-mixin abstract-container) ((contents))) (defmethod item-at ((container vector-container-mixin) &rest indices) (declare (dynamic-extent indices)) (aref (contents container) (first indices))) (defmethod item-at! ((container vector-container-mixin) value &rest indices) (declare (dynamic-extent indices)) (setf (aref (contents container) (first indices)) value)) (defmethod nth-element ((container vector-container-mixin) (index integer)) (aref (contents container) index)) (defmethod first-element ((container vector-container-mixin)) (item-at container 0)) (defmethod (setf first-element) (value (container vector-container-mixin)) (setf (item-at container 0) value)) (defmethod last-element ((v vector-container-mixin)) (item-at v (1- (size v)))) (defmethod (setf last-element) (value (v vector-container-mixin)) (setf (item-at v (1- (size v))) value)) ;;; basic-vector-container (defclass* basic-vector-container (vector-container-mixin) ()) ;;; bounded-vector-container (defclass* bounded-vector-container (basic-vector-container concrete-container) ()) (defmethod initialize-instance :around ((object bounded-vector-container) &rest args &key size initial-size) (remf args :size) (apply #'call-next-method object :initial-size (or size initial-size) args)) ;;; vector-container ;; implements size, empty-p, empty!, ;; insert-item, delete-item, ;; insert-item-at, delete-item-at, ;; item-at, iterate-container, delete-first, delete-last ;; first-element, search-for-item, search-for-match (defclass* vector-container (basic-vector-container concrete-container) ()) (defmethod insert-item ((container vector-container) item) (vector-push-extend item (contents container)) container) (defmethod insert-item-at ((container vector-container) item index) (resize-vector container (max (1+ (size container)) (1+ index))) (replace (contents container) (contents container) :start1 (+ 1 index) :start2 index :end2 (- (size container) 1)) (setf (aref (contents container) index) item) container) (defmethod delete-item-at ((container vector-container) &rest indexes) (declare (dynamic-extent indexes)) (let ((index (car indexes))) (replace (contents container) (contents container) :start2 (+ 1 index) :start1 index) (decf (fill-pointer (contents container)))) container) (defmethod delete-item ((container vector-container) item) ;;; removes the first instance of item in the-vector (let ((position (position item (contents container)))) (when position (delete-item-at container position)) container)) #+Wrong ;;?? This doesn't keep the adjustable property on all lisps (defmethod delete-item ((container vector-container) item) ;;; removes the first instance of item in the-vector (setf (contents container) (delete item (contents container) :count 1))) #+Wrong ;;?? This is fast but doesn't respect the ordered-container contract (defmethod delete-item ((container vector-container) item) (let ((position (position item (contents container)))) (when position (rotatef (aref (contents container) position) (aref (contents container) (1- (length (contents container))))) (setf (fill-pointer (contents container)) (1- (length (contents container))))) container)) (defmethod delete-first ((v vector-container)) (prog1 (item-at v 0) (delete-item-at v 0))) (defmethod delete-last ((v vector-container)) (let ((index (1- (size v)))) (prog1 (item-at v index) (delete-item-at v index)))) (defmethod size ((v vector-container)) (length (contents v))) ;;; flexible-vector-container (defclass* flexible-vector-container (vector-container) ()) (defmethod item-at! :before ((container flexible-vector-container) value &rest indices) (declare (ignore value) (dynamic-extent indices)) (resize-vector container (1+ (first indices)))) #+Vector-Test (let ((vec (make-container 'vector-container))) (size vec) (empty-p vec) (insert-item vec 'a) (size vec) (item-at vec 0) (insert-item-at vec 'b 0) (empty-p vec) (delete-item vec 'b) (size vec) (delete-item-at vec 0)) ;;; utilities (defun resize-vector (vector new-size) (unless (= (size vector) new-size) (setf (contents vector) (adjust-array (contents vector) (max (size vector) new-size) :element-type (array-element-type (contents vector)) :fill-pointer (array-has-fill-pointer-p (contents vector)))))) (defmethod samep ((container-1 vector-container-mixin) (container-2 vector-container-mixin)) (let ((*samep-test* #'equalp)) (samep (contents container-1) (contents container-2))))cl-containers-20170403-git/dev/weighted-sampling.lisp000066400000000000000000000055541306646076300224010ustar00rootroot00000000000000 (in-package #:containers) #| This is the dynamic version... could make a faster static version too. One that you set up and then sample repeatedly. More like a random 'element' generator. |# (eval-when (:compile-toplevel :load-toplevel :execute) (export '(weighted-sampling-container weight))) (defclass* weighted-sampling-container (priority-queue-on-container) ((total-weight 0d0 a) (random-number-generator :unbound ir)) (:default-initargs :random-number-generator variates:*random-generator*)) (defmethod initialize-instance :around ((object weighted-sampling-container) &rest args &key random-number-generator) (when random-number-generator (setf (slot-value object 'random-number-generator) random-number-generator)) (remf args :random-number-generator) (apply #'call-next-method object args)) (defmethod element-weight ((container weighted-sampling-container) thing) (funcall (key container) thing)) #+Wait (defmethod element-weight ((container weighted-sampling-container) (thing container-node-mixin)) (element-weight container (element thing))) (defmethod insert-item :after ((container weighted-sampling-container) thing) (incf (total-weight container) (element-weight container thing))) (defmethod delete-item :after ((container weighted-sampling-container) thing) (decf (total-weight container) (element-weight container thing))) (defmethod delete-node :after ((container weighted-sampling-container) (node container-node-mixin)) (decf (total-weight container) (element-weight container (element node)))) (defmethod delete-first ((container weighted-sampling-container)) (delete-item container (variates:next-element container))) (defmethod variates:next-element ((container weighted-sampling-container)) (let* ((target-weight (variates:uniform-random (random-number-generator container) 0d0 (total-weight container))) (current-weight 0d0) (element (block find-element (iterate-elements container (lambda (item) (when (>= (incf current-weight (element-weight container item)) target-weight) (return-from find-element item))))))) (values element))) #+Test (u:timeit (:report t) (loop repeat 100 collect (let ((q (make-container 'weighted-sampling-container :initial-contents '(1 5 2 2 10)))) (dequeue q)))) #+Test (u:timeit (:report t) (let ((q (make-container 'weighted-sampling-container :initial-contents '(1 5 2 2 10)))) (loop repeat 100 collect (variates:next-element q)))) cl-containers-20170403-git/doc/000077500000000000000000000000001306646076300160565ustar00rootroot00000000000000cl-containers-20170403-git/doc/acm_proc_article-sp.cls000066400000000000000000001322531306646076300224750ustar00rootroot00000000000000% ACM_PROC_ARTICLE-SP.CLS - VERSION 2.6SP % COMPATIBLE WITH THE "ACM_PROC_ARTICLE.CLS" V2.5 % Gerald Murray October 2nd., 2002 % % ---- Start of 'updates' ---- % % Allowance made to switch default fonts between those systems using % METAFONT and those using 'Type 1' or 'Truetype' fonts. % See LINE NUMBER 266 for details. % Also provided for enumerated/annotated Corollaries 'surrounded' by % enumerated Theorems (line 838). % Gerry November 11th. 1999 % % Made the Permission Statement / Conference Info / Copyright Info % 'user definable' in the source .tex file OR automatic if % not specified. % This 'sp' version does NOT produce the permission block. % % Major change in January 2000 was to include a "blank line" in between % new paragraphs. This involved major changes to the, then, acmproc-sp.cls 1.0SP % file, precipitating a 'new' name: "acm_proc_article-sp.cls" V2.01SP. % % Georgia fixed bug in sub-sub-section numbering in paragraphs (July 29th. 2002) % JS/GM fix to vertical spacing before Proofs (July 30th. 2002) % % Footnotes inside table cells using \minipage (Oct. 2002) % % ---- End of 'updates' ---- % \def\fileversion{V2.6SP} % for ACM's tracking purposes \def\filedate{October 2, 2002} % Gerry Murray's tracking data \def\docdate {Wednesday 2nd. October 2002} % Gerry Murray (with deltas to doc} \usepackage{epsfig} \usepackage{amssymb} \usepackage{amsmath} \usepackage{amsfonts} % % ACM_PROC_ARTICLE-SP DOCUMENT STYLE % G.K.M. Tobin August-October 1999 % adapted from ARTICLE document style by Ken Traub, Olin Shivers % also using elements of esub2acm.cls % LATEST REVISION V2.6SP - OCTOBER 2002 % ARTICLE DOCUMENT STYLE -- Released 16 March 1988 % for LaTeX version 2.09 % Copyright (C) 1988 by Leslie Lamport % % %%% ACM_PROC_ARTICLE-SP is a document style for producing two-column camera-ready pages for %%% ACM conferences, according to ACM specifications. The main features of %%% this style are: %%% %%% 1) Two columns. %%% 2) Side and top margins of 4.5pc, bottom margin of 6pc, column gutter of %%% 2pc, hence columns are 20pc wide and 55.5pc tall. (6pc =3D 1in, approx) %%% 3) First page has title information, and an extra 6pc of space at the %%% bottom of the first column for the ACM copyright notice. %%% 4) Text is 9pt on 10pt baselines; titles (except main) are 9pt bold. %%% %%% %%% There are a few restrictions you must observe: %%% %%% 1) You cannot change the font size; ACM wants you to use 9pt. %%% 3) You must start your paper with the \maketitle command. Prior to the %%% \maketitle you must have \title and \author commands. If you have a %%% \date command it will be ignored; no date appears on the paper, since %%% the proceedings will have a date on the front cover. %%% 4) Marginal paragraphs, tables of contents, lists of figures and tables, %%% and page headings are all forbidden. %%% 5) The `figure' environment will produce a figure one column wide; if you %%% want one that is two columns wide, use `figure*'. %%% % %%% Copyright Space: %%% This style automatically leaves 1" blank space at the bottom of page 1/ %%% column 1. This space can optionally be filled with some text using the %%% \toappear{...} command. If used, this command must be BEFORE the \maketitle %%% command. If this command is defined AND [preprint] is on, then the %%% space is filled with the {...} text (at the bottom); otherwise, it is %%% blank. If you use \toappearbox{...} instead of \toappear{...} then a %%% box will be drawn around the text (if [preprint] is on). %%% %%% A typical usage looks like this: %%% \toappear{To appear in the Ninth AES Conference on Medievil Lithuanian %%% Embalming Technique, June 1991, Alfaretta, Georgia.} %%% This will be included in the preprint, and left out of the conference %%% version. %%% %%% WARNING: %%% Some dvi-ps converters heuristically allow chars to drift from their %%% true positions a few pixels. This may be noticeable with the 9pt sans-serif %%% bold font used for section headers. %%% You may turn this hackery off via the -e option: %%% dvips -e 0 foo.dvi >foo.ps %%% \typeout{Document Class 'acm_proc_article-sp' <2nd. October '02>. Modified by G.K.M. Tobin} \typeout{Based in part upon document Style `acmconf' <22 May 89>. Hacked 4/91 by} \typeout{shivers@cs.cmu.edu, 4/93 by theobald@cs.mcgill.ca} \typeout{Excerpts were taken from (Journal Style) 'esub2acm.cls'.} \typeout{****** Bugs/comments/suggestions to Gerry Murray -- murray@hq.acm.org ******} \oddsidemargin 4.5pc \evensidemargin 4.5pc \advance\oddsidemargin by -1in % Correct for LaTeX gratuitousness \advance\evensidemargin by -1in % Correct for LaTeX gratuitousness \marginparwidth 0pt % Margin pars are not allowed. \marginparsep 11pt % Horizontal space between outer margin and % marginal note % Top of page: \topmargin 4.5pc % Nominal distance from top of page to top of % box containing running head. \advance\topmargin by -1in % Correct for LaTeX gratuitousness \headheight 0pt % Height of box containing running head. \headsep 0pt % Space between running head and text. % Bottom of page: \footskip 30pt % Distance from baseline of box containing foot % to baseline of last line of text. \@ifundefined{footheight}{\newdimen\footheight}{}% this is for LaTeX2e \footheight 12pt % Height of box containing running foot. %% Must redefine the top margin so there's room for headers and %% page numbers if you are using the preprint option. Footers %% are OK as is. Olin. \advance\topmargin by -37pt % Leave 37pt above text for headers \headheight 12pt % Height of box containing running head. \headsep 25pt % Space between running head and text. \textheight 666pt % 9 1/4 column height \textwidth 42pc % Width of text line. % For two-column mode: \columnsep 2pc % Space between columns \columnseprule 0pt % Width of rule between columns. \hfuzz 1pt % Allow some variation in column width, otherwise it's % too hard to typeset in narrow columns. \footnotesep 5.6pt % Height of strut placed at the beginning of every % footnote =3D height of normal \footnotesize strut, % so no extra space between footnotes. \skip\footins 8.1pt plus 4pt minus 2pt % Space between last line of text and % top of first footnote. \floatsep 11pt plus 2pt minus 2pt % Space between adjacent floats moved % to top or bottom of text page. \textfloatsep 18pt plus 2pt minus 4pt % Space between main text and floats % at top or bottom of page. \intextsep 11pt plus 2pt minus 2pt % Space between in-text figures and % text. \@ifundefined{@maxsep}{\newdimen\@maxsep}{}% this is for LaTeX2e \@maxsep 18pt % The maximum of \floatsep, % \textfloatsep and \intextsep (minus % the stretch and shrink). \dblfloatsep 11pt plus 2pt minus 2pt % Same as \floatsep for double-column % figures in two-column mode. \dbltextfloatsep 18pt plus 2pt minus 4pt% \textfloatsep for double-column % floats. \@ifundefined{@dblmaxsep}{\newdimen\@dblmaxsep}{}% this is for LaTeX2e \@dblmaxsep 18pt % The maximum of \dblfloatsep and % \dbltexfloatsep. \@fptop 0pt plus 1fil % Stretch at top of float page/column. (Must be % 0pt plus ...) \@fpsep 8pt plus 2fil % Space between floats on float page/column. \@fpbot 0pt plus 1fil % Stretch at bottom of float page/column. (Must be % 0pt plus ... ) \@dblfptop 0pt plus 1fil % Stretch at top of float page. (Must be 0pt plus ...) \@dblfpsep 8pt plus 2fil % Space between floats on float page. \@dblfpbot 0pt plus 1fil % Stretch at bottom of float page. (Must be % 0pt plus ... ) \marginparpush 5pt % Minimum vertical separation between two marginal % notes. \parskip 0pt % Extra vertical space between paragraphs. % Set to 0pt outside sections, to keep section heads % uniformly spaced. The value of parskip is set % to leading value _within_ sections. % 12 Jan 2000 gkmt \parindent 0pt % Width of paragraph indentation. \partopsep 2pt plus 1pt minus 1pt% Extra vertical space, in addition to % \parskip and \topsep, added when user % leaves blank line before environment. \@lowpenalty 51 % Produced by \nopagebreak[1] or \nolinebreak[1] \@medpenalty 151 % Produced by \nopagebreak[2] or \nolinebreak[2] \@highpenalty 301 % Produced by \nopagebreak[3] or \nolinebreak[3] \@beginparpenalty -\@lowpenalty % Before a list or paragraph environment. \@endparpenalty -\@lowpenalty % After a list or paragraph environment. \@itempenalty -\@lowpenalty % Between list items. \@namedef{ds@10pt}{\@latexerr{The `10pt' option is not allowed in the `acmconf' document style.}\@eha} \@namedef{ds@11pt}{\@latexerr{The `11pt' option is not allowed in the `acmconf' document style.}\@eha} \@namedef{ds@12pt}{\@latexerr{The `12pt' option is not allowed in the `acmconf' document style.}\@eha} \@options \lineskip 2pt % \lineskip is 1pt for all font sizes. \normallineskip 2pt \def\baselinestretch{1} \abovedisplayskip 9pt plus2pt minus4.5pt% \belowdisplayskip \abovedisplayskip \abovedisplayshortskip \z@ plus3pt% \belowdisplayshortskip 5.4pt plus3pt minus3pt% \let\@listi\@listI % Setting of \@listi added 9 Jun 87 \def\small{\@setsize\small{9pt}\viiipt\@viiipt \abovedisplayskip 7.6pt plus 3pt minus 4pt% \belowdisplayskip \abovedisplayskip \abovedisplayshortskip \z@ plus2pt% \belowdisplayshortskip 3.6pt plus2pt minus 2pt \def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 \topsep 4pt plus 2pt minus 2pt\parsep 2pt plus 1pt minus 1pt \itemsep \parsep}} \def\footnotesize{\@setsize\footnotesize{9pt}\ixpt\@ixpt \abovedisplayskip 6.4pt plus 2pt minus 4pt% \belowdisplayskip \abovedisplayskip \abovedisplayshortskip \z@ plus 1pt% \belowdisplayshortskip 2.7pt plus 1pt minus 2pt \def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 \topsep 3pt plus 1pt minus 1pt\parsep 2pt plus 1pt minus 1pt \itemsep \parsep}} \newcount\aucount \newcount\originalaucount \newdimen\auwidth \auwidth=\textwidth \newdimen\auskip \newcount\auskipcount \newdimen\auskip \global\auskip=1pc \newdimen\allauboxes \allauboxes=\auwidth \newtoks\addauthors \newcount\addauflag \global\addauflag=0 %Haven't shown additional authors yet \newtoks\subtitletext \gdef\subtitle#1{\subtitletext={#1}} \gdef\additionalauthors#1{\addauthors={#1}} \gdef\numberofauthors#1{\global\aucount=#1 \ifnum\aucount>3\global\originalaucount=\aucount \global\aucount=3\fi %g} \global\auskipcount=\aucount\global\advance\auskipcount by 1 \global\multiply\auskipcount by 2 \global\multiply\auskip by \auskipcount \global\advance\auwidth by -\auskip \global\divide\auwidth by \aucount} % \and was modified to count the number of authors. GKMT 12 Aug 1999 \def\alignauthor{% % \begin{tabular} \end{tabular}% \begin{tabular}[t]{p{\auwidth}}\centering}% % *** NOTE *** NOTE *** NOTE *** NOTE *** % If you have 'font problems' then you may need % to change these, e.g. 'arialb' instead of "arialbd". % Gerry Murray 11/11/1999 % *** OR ** comment out block A and activate block B or vice versa. % ********************************************** % % -- Start of block A -- (Type 1 or Truetype fonts) %\newfont{\secfnt}{timesbd at 12pt} % was timenrb originally - now is timesbd %\newfont{\secit}{timesbi at 12pt} %13 Jan 00 gkmt %\newfont{\subsecfnt}{timesi at 11pt} % was timenrri originally - now is timesi %\newfont{\subsecit}{timesbi at 11pt} % 13 Jan 00 gkmt -- was times changed to timesbi gm 2/4/2000 % % because "normal" is italic, "italic" is Roman %\newfont{\ttlfnt}{arialbd at 18pt} % was arialb originally - now is arialbd %\newfont{\ttlit}{arialbi at 18pt} % 13 Jan 00 gkmt %\newfont{\subttlfnt}{arial at 14pt} % was arialr originally - now is arial %\newfont{\subttlit}{ariali at 14pt} % 13 Jan 00 gkmt %\newfont{\subttlbf}{arialbd at 14pt} % 13 Jan 00 gkmt %\newfont{\aufnt}{arial at 12pt} % was arialr originally - now is arial %\newfont{\auit}{ariali at 12pt} % 13 Jan 00 gkmt %\newfont{\affaddr}{arial at 10pt} % was arialr originally - now is arial %\newfont{\affaddrit}{ariali at 10pt} %13 Jan 00 gkmt %\newfont{\eaddfnt}{arial at 12pt} % was arialr originally - now is arial %\newfont{\ixpt}{times at 9pt} % was timenrr originally - now is times %\newfont{\confname}{timesi at 8pt} % was timenrri - now is timesi %\newfont{\crnotice}{times at 8pt} % was timenrr originally - now is times %\newfont{\ninept}{times at 9pt} % was timenrr originally - now is times % ********************************************* % -- End of block A -- % % % -- Start of block B -- METAFONT % +++++++++++++++++++++++++++++++++++++++++++++ % Next (default) block for those using Metafont % Gerry Murray 11/11/1999 % *** THIS BLOCK FOR THOSE USING METAFONT ***** % ********************************************* \newfont{\secfnt}{ptmb at 12pt} \newfont{\secit}{ptmbi at 12pt} %13 Jan 00 gkmt \newfont{\subsecfnt}{ptmri at 11pt} \newfont{\subsecit}{ptmbi at 11pt} % 13 Jan 00 gkmt -- was ptmr changed to ptmbi gm 2/4/2000 % because "normal" is italic, "italic" is Roman \newfont{\ttlfnt}{phvb at 18pt} \newfont{\ttlit}{phvbo at 18pt} % GM 2/4/2000 \newfont{\subttlfnt}{phvr at 14pt} \newfont{\subttlit}{phvro at 14pt} % GM 2/4/2000 \newfont{\subttlbf}{phvb at 14pt} % 13 Jan 00 gkmt \newfont{\aufnt}{phvr at 12pt} \newfont{\auit}{phvro at 12pt} % GM 2/4/2000 \newfont{\affaddr}{phvr at 10pt} \newfont{\affaddrit}{phvro at 10pt} % GM 2/4/2000 \newfont{\eaddfnt}{phvr at 12pt} \newfont{\ixpt}{ptmr at 9pt} \newfont{\confname}{ptmri at 8pt} \newfont{\crnotice}{ptmr at 8pt} \newfont{\ninept}{ptmr at 9pt} % +++++++++++++++++++++++++++++++++++++++++++++ % -- End of block B -- \def\email#1{{{\eaddfnt{\vskip 4pt#1}}}} \def\addauthorsection{\ifnum\originalaucount>3 \section{Additional Authors}\the\addauthors \fi} \newcount\savesection \newcount\sectioncntr \global\sectioncntr=1 \setcounter{secnumdepth}{3} \def\appendix{\par \section*{APPENDIX} \setcounter{section}{0} \setcounter{subsection}{0} \def\thesection{\Alph{section}} } \leftmargini 22.5pt \leftmarginii 19.8pt % > \labelsep + width of '(m)' \leftmarginiii 16.8pt % > \labelsep + width of 'vii.' \leftmarginiv 15.3pt % > \labelsep + width of 'M.' \leftmarginv 9pt \leftmarginvi 9pt \leftmargin\leftmargini \labelsep 4.5pt \labelwidth\leftmargini\advance\labelwidth-\labelsep \def\@listI{\leftmargin\leftmargini \parsep 3.6pt plus 2pt minus 1pt% \topsep 7.2pt plus 2pt minus 4pt% \itemsep 3.6pt plus 2pt minus 1pt} \let\@listi\@listI \@listi \def\@listii{\leftmargin\leftmarginii \labelwidth\leftmarginii\advance\labelwidth-\labelsep \topsep 3.6pt plus 2pt minus 1pt \parsep 1.8pt plus 0.9pt minus 0.9pt \itemsep \parsep} \def\@listiii{\leftmargin\leftmarginiii \labelwidth\leftmarginiii\advance\labelwidth-\labelsep \topsep 1.8pt plus 0.9pt minus 0.9pt \parsep \z@ \partopsep 1pt plus 0pt minus 1pt \itemsep \topsep} \def\@listiv{\leftmargin\leftmarginiv \labelwidth\leftmarginiv\advance\labelwidth-\labelsep} \def\@listv{\leftmargin\leftmarginv \labelwidth\leftmarginv\advance\labelwidth-\labelsep} \def\@listvi{\leftmargin\leftmarginvi \labelwidth\leftmarginvi\advance\labelwidth-\labelsep} \def\labelenumi{\theenumi.} \def\theenumi{\arabic{enumi}} \def\labelenumii{(\theenumii)} \def\theenumii{\alph{enumii}} \def\p@enumii{\theenumi} \def\labelenumiii{\theenumiii.} \def\theenumiii{\roman{enumiii}} \def\p@enumiii{\theenumi(\theenumii)} \def\labelenumiv{\theenumiv.} \def\theenumiv{\Alph{enumiv}} \def\p@enumiv{\p@enumiii\theenumiii} \def\labelitemi{$\bullet$} \def\labelitemii{\bf --} \def\labelitemiii{$\ast$} \def\labelitemiv{$\cdot$} \def\verse{\let\\=\@centercr \list{}{\itemsep\z@ \itemindent -1.5em\listparindent \itemindent \rightmargin\leftmargin\advance\leftmargin 1.5em}\item[]} \let\endverse\endlist \def\quotation{\list{}{\listparindent 1.5em \itemindent\listparindent \rightmargin\leftmargin \parsep 0pt plus 1pt}\item[]} \let\endquotation=\endlist \def\quote{\list{}{\rightmargin\leftmargin}\item[]} \let\endquote=\endlist \def\descriptionlabel#1{\hspace\labelsep \bf #1} \def\description{\list{}{\labelwidth\z@ \itemindent-\leftmargin \let\makelabel\descriptionlabel}} \let\enddescription\endlist \def\theequation{\arabic{equation}} \arraycolsep 4.5pt % Half the space between columns in an array environment. \tabcolsep 5.4pt % Half the space between columns in a tabular environment. \arrayrulewidth .4pt % Width of rules in array and tabular environment. \doublerulesep 1.8pt % Space between adjacent rules in array or tabular env. \tabbingsep \labelsep % Space used by the \' command. (See LaTeX manual.) \skip\@mpfootins =\skip\footins \fboxsep =2.7pt % Space left between box and text by \fbox and \framebox. \fboxrule =.4pt % Width of rules in box made by \fbox and \framebox. \def\thepart{\Roman{part}} % Roman numeral part numbers. \def\thesection {\arabic{section}} \def\thesubsection {\thesection.\arabic{subsection}} %\def\thesubsubsection {\thesubsection.\arabic{subsubsection}} % GM 7/30/2002 %\def\theparagraph {\thesubsubsection.\arabic{paragraph}} % GM 7/30/2002 \def\thesubparagraph {\theparagraph.\arabic{subparagraph}} \def\@pnumwidth{1.55em} \def\@tocrmarg {2.55em} \def\@dotsep{4.5} \setcounter{tocdepth}{3} \def\tableofcontents{\@latexerr{\tableofcontents: Tables of contents are not allowed in the `acmconf' document style.}\@eha} \def\l@part#1#2{\addpenalty{\@secpenalty} \addvspace{2.25em plus 1pt} % space above part line \begingroup \@tempdima 3em % width of box holding part number, used by \parindent \z@ \rightskip \@pnumwidth %% \numberline \parfillskip -\@pnumwidth {\large \bf % set line in \large boldface \leavevmode % TeX command to enter horizontal mode. #1\hfil \hbox to\@pnumwidth{\hss #2}}\par \nobreak % Never break after part entry \endgroup} \def\l@section#1#2{\addpenalty{\@secpenalty} % good place for page break \addvspace{1.0em plus 1pt} % space above toc entry \@tempdima 1.5em % width of box holding section number \begingroup \parindent \z@ \rightskip \@pnumwidth \parfillskip -\@pnumwidth \bf % Boldface. \leavevmode % TeX command to enter horizontal mode. \advance\leftskip\@tempdima %% added 5 Feb 88 to conform to \hskip -\leftskip %% 25 Jan 88 change to \numberline #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par \endgroup} \def\l@subsection{\@dottedtocline{2}{1.5em}{2.3em}} \def\l@subsubsection{\@dottedtocline{3}{3.8em}{3.2em}} \def\l@paragraph{\@dottedtocline{4}{7.0em}{4.1em}} \def\l@subparagraph{\@dottedtocline{5}{10em}{5em}} \def\listoffigures{\@latexerr{\listoffigures: Lists of figures are not allowed in the `acmconf' document style.}\@eha} \def\l@figure{\@dottedtocline{1}{1.5em}{2.3em}} \def\listoftables{\@latexerr{\listoftables: Lists of tables are not allowed in the `acmconf' document style.}\@eha} \let\l@table\l@figure \def\footnoterule{\kern-3\p@ \hrule width .4\columnwidth \kern 2.6\p@} % The \hrule has default height of .4pt . % ------ \long\def\@makefntext#1{\noindent %\hbox to .5em{\hss$^{\@thefnmark}$}#1} % original \hbox to .5em{\hss\textsuperscript{\@thefnmark}}#1} % C. Clifton / GM Oct. 2nd. 2002 % ------- \long\def\@maketntext#1{\noindent #1} \long\def\@maketitlenotetext#1#2{\noindent \hbox to 1.8em{\hss$^{#1}$}#2} \setcounter{topnumber}{2} \def\topfraction{.7} \setcounter{bottomnumber}{1} \def\bottomfraction{.3} \setcounter{totalnumber}{3} \def\textfraction{.2} \def\floatpagefraction{.5} \setcounter{dbltopnumber}{2} \def\dbltopfraction{.7} \def\dblfloatpagefraction{.5} \long\def\@makecaption#1#2{ \vskip \baselineskip \setbox\@tempboxa\hbox{\textbf{#1: #2}} \ifdim \wd\@tempboxa >\hsize % IF longer than one line: \textbf{#1: #2}\par % THEN set as ordinary paragraph. \else % ELSE center. \hbox to\hsize{\hfil\box\@tempboxa\hfil}\par \fi} \@ifundefined{figure}{\newcounter {figure}} % this is for LaTeX2e \def\fps@figure{tbp} \def\ftype@figure{1} \def\ext@figure{lof} \def\fnum@figure{Figure \thefigure} \def\figure{\@float{figure}} \let\endfigure\end@float \@namedef{figure*}{\@dblfloat{figure}} \@namedef{endfigure*}{\end@dblfloat} \@ifundefined{table}{\newcounter {table}} % this is for LaTeX2e \def\fps@table{tbp} \def\ftype@table{2} \def\ext@table{lot} \def\fnum@table{Table \thetable} \def\table{\@float{table}} \let\endtable\end@float \@namedef{table*}{\@dblfloat{table}} \@namedef{endtable*}{\end@dblfloat} \newtoks\titleboxnotes \newcount\titleboxnoteflag \def\maketitle{\par \begingroup \def\thefootnote{\fnsymbol{footnote}} \def\@makefnmark{\hbox to 0pt{$^{\@thefnmark}$\hss}} \twocolumn[\@maketitle] \@thanks \endgroup \setcounter{footnote}{0} \let\maketitle\relax \let\@maketitle\relax \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\gdef\@subtitle{}\let\thanks\relax \@copyrightspace} %% CHANGES ON NEXT LINES \newif\if@ll % to record which version of LaTeX is in use \expandafter\ifx\csname LaTeXe\endcsname\relax % LaTeX2.09 is used \else% LaTeX2e is used, so set ll to true \global\@lltrue \fi \if@ll \NeedsTeXFormat{LaTeX2e} \ProvidesClass{acm_proc_article-sp} [2002/2/10 - V2.6SP - based on esub2acm.sty <23 April 96>] \RequirePackage{latexsym}% QUERY: are these two really needed? \let\dooptions\ProcessOptions \else \let\dooptions\@options \fi %% END CHANGES \def\@height{height} \def\@width{width} \def\@minus{minus} \def\@plus{plus} \def\hb@xt@{\hbox to} \newif\if@faircopy \@faircopyfalse \def\ds@faircopy{\@faircopytrue} \def\ds@preprint{\@faircopyfalse} \@twosidetrue \@mparswitchtrue \def\ds@draft{\overfullrule 5\p@} %% CHANGE ON NEXT LINE \dooptions \lineskip \p@ \normallineskip \p@ \def\baselinestretch{1} \def\@ptsize{0} %needed for amssymbols.sty %% CHANGES ON NEXT LINES \if@ll% allow use of old-style font change commands in LaTeX2e \@maxdepth\maxdepth % \DeclareOldFontCommand{\rm}{\ninept\rmfamily}{\mathrm} \DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} \DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} \DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} \DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} \DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} \DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} \DeclareRobustCommand*{\cal}{\@fontswitch{\relax}{\mathcal}} \DeclareRobustCommand*{\mit}{\@fontswitch{\relax}{\mathnormal}} \fi % \if@ll \renewcommand{\rmdefault}{cmr} % was 'ttm' % Note! I have also found 'mvr' to work ESPECIALLY well. % Gerry - October 1999 % You may need to change your LV1times.fd file so that sc is % mapped to cmcsc - -for smallcaps -- that is if you decide % to change {cmr} to {times} above. (Not recommended) \renewcommand{\@ptsize}{} \renewcommand{\normalsize}{% \@setfontsize\normalsize\@ixpt{10.5\p@}%\ninept% \abovedisplayskip 6\p@ \@plus2\p@ \@minus\p@ \belowdisplayskip \abovedisplayskip \abovedisplayshortskip 6\p@ \@minus 3\p@ \belowdisplayshortskip 6\p@ \@minus 3\p@ \let\@listi\@listI } \else \def\@normalsize{%changed next to 9 from 10 \@setsize\normalsize{9\p@}\ixpt\@ixpt \abovedisplayskip 6\p@ \@plus2\p@ \@minus\p@ \belowdisplayskip \abovedisplayskip \abovedisplayshortskip 6\p@ \@minus 3\p@ \belowdisplayshortskip 6\p@ \@minus 3\p@ \let\@listi\@listI }% \fi \if@ll \newcommand\scriptsize{\@setfontsize\scriptsize\@viipt{8\p@}} \newcommand\tiny{\@setfontsize\tiny\@vpt{6\p@}} \newcommand\large{\@setfontsize\large\@xiipt{14\p@}} \newcommand\Large{\@setfontsize\Large\@xivpt{18\p@}} \newcommand\LARGE{\@setfontsize\LARGE\@xviipt{20\p@}} \newcommand\huge{\@setfontsize\huge\@xxpt{25\p@}} \newcommand\Huge{\@setfontsize\Huge\@xxvpt{30\p@}} \else \def\scriptsize{\@setsize\scriptsize{8\p@}\viipt\@viipt} \def\tiny{\@setsize\tiny{6\p@}\vpt\@vpt} \def\large{\@setsize\large{14\p@}\xiipt\@xiipt} \def\Large{\@setsize\Large{18\p@}\xivpt\@xivpt} \def\LARGE{\@setsize\LARGE{20\p@}\xviipt\@xviipt} \def\huge{\@setsize\huge{25\p@}\xxpt\@xxpt} \def\Huge{\@setsize\Huge{30\p@}\xxvpt\@xxvpt} \fi \normalsize % make aubox hsize/number of authors up to 3, less gutter % then showbox gutter showbox gutter showbox -- GKMT Aug 99 \newbox\@acmtitlebox \def\@maketitle{\newpage \null \setbox\@acmtitlebox\vbox{% \baselineskip 20pt \vskip 2em % Vertical space above title. \begin{center} {\ttlfnt \@title\par} % Title set in 18pt Helvetica (Arial) bold size. \vskip 1.5em % Vertical space after title. %This should be the subtitle. {\subttlfnt \the\subtitletext\par}\vskip 1.25em%\fi {\baselineskip 16pt\aufnt % each author set in \12 pt Arial, in a \lineskip .5em % tabular environment \begin{tabular}[t]{c}\@author \end{tabular}\par} \vskip 1.5em % Vertical space after author. \end{center}} \dimen0=\ht\@acmtitlebox \advance\dimen0 by -12.75pc\relax % Increased space for title box -- KBT \unvbox\@acmtitlebox \ifdim\dimen0<0.0pt\relax\vskip-\dimen0\fi} \newcount\titlenotecount \global\titlenotecount=0 \newtoks\tntoks \newtoks\tntokstwo \newtoks\tntoksthree \newtoks\tntoksfour \newtoks\tntoksfive \def\abstract{ \ifnum\titlenotecount>0 % was =1 \insert\footins{% \reset@font\footnotesize \interlinepenalty\interfootnotelinepenalty \splittopskip\footnotesep \splitmaxdepth \dp\strutbox \floatingpenalty \@MM \hsize\columnwidth \@parboxrestore \protected@edef\@currentlabel{% }% \color@begingroup \ifnum\titlenotecount=1 \@maketntext{% \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\@finalstrut\strutbox}% \fi \ifnum\titlenotecount=2 \@maketntext{% \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\@finalstrut\strutbox}% \fi \ifnum\titlenotecount=3 \@maketntext{% \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\@finalstrut\strutbox}% \fi \ifnum\titlenotecount=4 \@maketntext{% \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\S$}\rule\z@\footnotesep\ignorespaces\the\tntoksfour\@finalstrut\strutbox}% \fi \ifnum\titlenotecount=5 \@maketntext{% \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\S$}\rule\z@\footnotesep\ignorespaces\the\tntoksfour\par\@finalstrut\strutbox}% \@maketntext{% \raisebox{4pt}{$\P$}\rule\z@\footnotesep\ignorespaces\the\tntoksfive\@finalstrut\strutbox}% \fi \color@endgroup} %g} \fi \setcounter{footnote}{0} \section*{ABSTRACT}\normalsize %\the\parskip \the\baselineskip%\ninept } \def\endabstract{\if@twocolumn\else\endquotation\fi} \def\keywords{\if@twocolumn \section*{Keywords} \else \small \quotation \fi} % I've pulled the check for 2 cols, since proceedings are _always_ % two-column 11 Jan 2000 gkmt \def\terms{%\if@twocolumn \section*{General Terms} %\else \small %\quotation\the\parskip %\fi} } % -- Classification needs to be a bit smart due to optionals - Gerry/Georgia November 2nd. 1999 \newcount\catcount \global\catcount=1 \def\category#1#2#3{% \ifnum\catcount=1 \section*{Categories and Subject Descriptors} \advance\catcount by 1\else{\unskip; }\fi \@ifnextchar [{\@category{#1}{#2}{#3}}{\@category{#1}{#2}{#3}[]}% } \def\@category#1#2#3[#4]{% \begingroup \let\and\relax #1 [\textbf{#2}]% \if!#4!% \if!#3!\else : #3\fi \else :\space \if!#3!\else #3\kern\z@---\hskip\z@\fi \textit{#4}% \fi \endgroup } % %%% This section (written by KBT) handles the 1" box in the lower left %%% corner of the left column of the first page by creating a picture, %%% and inserting the predefined string at the bottom (with a negative %%% displacement to offset the space allocated for a non-existent %%% caption). %%% \newtoks\copyrightnotice \def\ftype@copyrightbox{8} \def\@copyrightspace{ \@float{copyrightbox}[b] \begin{center} \setlength{\unitlength}{1pc} \begin{picture}(20,6) %Space for copyright notice \put(0,-0.95){\crnotice{\@toappear}} \end{picture} \end{center} \end@float} \def\@toappear{} % Default setting blank - commands below change this. \long\def\toappear#1{\def\@toappear{\parbox[b]{20pc}{\baselineskip 9pt#1}}} \def\toappearbox#1{\def\@toappear{\raisebox{5pt}{\framebox[20pc]{\parbox[b]{19pc}{#1}}}}} \newtoks\conf \newtoks\confinfo \def\conferenceinfo#1#2{\global\conf={#1}\global\confinfo{#2}} \def\marginpar{\@latexerr{The \marginpar command is not allowed in the `acmconf' document style.}\@eha} \mark{{}{}} % Initializes TeX's marks \def\today{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} \def\@begintheorem#1#2{% \trivlist \item[% \hskip 10\p@ \hskip \labelsep {{\sc #1}\hskip 5\p@\relax#2.}% ] \it } \def\@opargbegintheorem#1#2#3{% \trivlist \item[% \hskip 10\p@ \hskip \labelsep {\sc #1\ #2\ % This mod by Gerry to enumerate corollaries \setbox\@tempboxa\hbox{(#3)} % and bracket the 'corollary title' \ifdim \wd\@tempboxa>\z@ % and retain the correct numbering of e.g. theorems \hskip 5\p@\relax % if they occur 'around' said corollaries. \box\@tempboxa % Gerry - Nov. 1999. \fi.}% ] \it } \newif\if@qeded \global\@qededfalse % -- original %\def\proof{% % \vspace{-\parskip} % GM July 2000 (for tighter spacing) % \global\@qededfalse % \@ifnextchar[{\@xproof}{\@proof}% %} % -- end of original % (JSS) Fix for vertical spacing bug - Gerry Murray July 30th. 2002 \def\proof{% \vspace{-\lastskip}\vspace{-\parsep}\penalty-51% \global\@qededfalse \@ifnextchar[{\@xproof}{\@proof}% } \def\endproof{% \if@qeded\else\qed\fi \endtrivlist } \def\@proof{% \trivlist \item[% \hskip 10\p@ \hskip \labelsep {\sc Proof.}% ] \ignorespaces } \def\@xproof[#1]{% \trivlist \item[\hskip 10\p@\hskip \labelsep{\sc Proof #1.}]% \ignorespaces } \def\qed{% \unskip \kern 10\p@ \begingroup \unitlength\p@ \linethickness{.4\p@}% \framebox(6,6){}% \endgroup \global\@qededtrue } \def\newdef#1#2{% \expandafter\@ifdefinable\csname #1\endcsname {\@definecounter{#1}% \expandafter\xdef\csname the#1\endcsname{\@thmcounter{#1}}% \global\@namedef{#1}{\@defthm{#1}{#2}}% \global\@namedef{end#1}{\@endtheorem}% }% } \def\@defthm#1#2{% \refstepcounter{#1}% \@ifnextchar[{\@ydefthm{#1}{#2}}{\@xdefthm{#1}{#2}}% } \def\@xdefthm#1#2{% \@begindef{#2}{\csname the#1\endcsname}% \ignorespaces } \def\@ydefthm#1#2[#3]{% \trivlist \item[% \hskip 10\p@ \hskip \labelsep {\it #2% \savebox\@tempboxa{#3}% \ifdim \wd\@tempboxa>\z@ \ \box\@tempboxa \fi.% }]% \ignorespaces } \def\@begindef#1#2{% \trivlist \item[% \hskip 10\p@ \hskip \labelsep {\it #1\ \rm #2.}% ]% } \def\theequation{\arabic{equation}} \newcounter{part} \newcounter{section} \newcounter{subsection}[section] \newcounter{subsubsection}[subsection] \newcounter{paragraph}[subsubsection] \def\thepart{\Roman{part}} \def\thesection{\arabic{section}} \def\thesubsection{\thesection.\arabic{subsection}} \def\thesubsubsection{\thesubsection.\arabic{subsubsection}} %removed \subsecfnt 29 July 2002 gkmt \def\theparagraph{\thesubsubsection.\arabic{paragraph}} %removed \subsecfnt 29 July 2002 gkmt \newif\if@uchead \@ucheadfalse %% CHANGES: NEW NOTE %% NOTE: OK to use old-style font commands below, since they were %% suitably redefined for LaTeX2e %% END CHANGES \setcounter{secnumdepth}{3} \def\part{% \@startsection{part}{9}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@} {4\p@}{\normalsize\@ucheadtrue}% } % Rationale for changes made in next four definitions: % "Before skip" is made elastic to provide some give in setting columns (vs. % parskip, which is non-elastic to keep section headers "anchored" to their % subsequent text. % % "After skip" is minimized -- BUT setting it to 0pt resulted in run-in heads, despite % the documentation asserted only after-skip < 0pt would have result. % % Baselineskip added to style to ensure multi-line section titles, and section heads % followed by another section head rather than text, are decently spaced vertically. % 12 Jan 2000 gkmt \def\section{% \@startsection{section}{1}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% {0.5pt}{\baselineskip=14pt\secfnt\@ucheadtrue}% } \def\subsection{% \@startsection{subsection}{2}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@} {0.5pt}{\baselineskip=14pt\secfnt}% } \def\subsubsection{% \@startsection{subsubsection}{3}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% {0.5pt}{\baselineskip=14pt\subsecfnt}% } \def\paragraph{% \@startsection{paragraph}{3}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% {0.5pt}{\baselineskip=14pt\subsecfnt}% } \let\@period=. \def\@startsection#1#2#3#4#5#6{% \if@noskipsec %gkmt, 11 aug 99 \global\let\@period\@empty \leavevmode \global\let\@period.% \fi \par \@tempskipa #4\relax \@afterindenttrue \ifdim \@tempskipa <\z@ \@tempskipa -\@tempskipa \@afterindentfalse \fi %\if@nobreak 11 Jan 00 gkmt %\everypar{} %\else \addpenalty\@secpenalty \addvspace\@tempskipa %\fi \parskip=0pt \@ifstar {\@ssect{#3}{#4}{#5}{#6}} {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}% } \def\@ssect#1#2#3#4#5{% \@tempskipa #3\relax \ifdim \@tempskipa>\z@ \begingroup #4{% \@hangfrom{\hskip #1}% \interlinepenalty \@M #5\@@par}% \endgroup \else \def\@svsechd{#4{\hskip #1\relax #5}}% \fi \vskip -10.5pt %gkmt, 7 jan 00 -- had been -14pt, now set to parskip \@xsect{#3}\parskip=10.5pt} % within the starred section, parskip = leading 12 Jan 2000 gkmt \def\@sect#1#2#3#4#5#6[#7]#8{% \ifnum #2>\c@secnumdepth \let\@svsec\@empty \else \refstepcounter{#1}% \edef\@svsec{% \begingroup %\ifnum#2>2 \noexpand\rm \fi % changed to next 29 July 2002 gkmt \ifnum#2>2 \noexpand#6 \fi \csname the#1\endcsname \endgroup \ifnum #2=1\relax .\fi \hskip 1em }% \fi \@tempskipa #5\relax \ifdim \@tempskipa>\z@ \begingroup #6\relax \@hangfrom{\hskip #3\relax\@svsec}% \begingroup \interlinepenalty \@M \if@uchead \uppercase{#8}% \else #8% \fi \par \endgroup \endgroup \csname #1mark\endcsname{#7}% \vskip -10.5pt % -14pt gkmt, 11 aug 99 -- changed to -\parskip 11 Jan 2000 \addcontentsline{toc}{#1}{% \ifnum #2>\c@secnumdepth \else \protect\numberline{\csname the#1\endcsname}% \fi #7% }% \else \def\@svsechd{% #6% \hskip #3\relax \@svsec \if@uchead \uppercase{#8}% \else #8% \fi \csname #1mark\endcsname{#7}% \addcontentsline{toc}{#1}{% \ifnum #2>\c@secnumdepth \else \protect\numberline{\csname the#1\endcsname}% \fi #7% }% }% \fi \@xsect{#5}\parskip=10.5pt% within the section, parskip = leading 12 Jan 2000 gkmt } \def\@xsect#1{% \@tempskipa #1\relax \ifdim \@tempskipa>\z@ \par \nobreak \vskip \@tempskipa \@afterheading \else \global\@nobreakfalse \global\@noskipsectrue \everypar{% \if@noskipsec \global\@noskipsecfalse \clubpenalty\@M \hskip -\parindent \begingroup \@svsechd \@period \endgroup \unskip \@tempskipa #1\relax \hskip -\@tempskipa \else \clubpenalty \@clubpenalty \everypar{}% \fi }% \fi \ignorespaces } \def\@trivlist{% \@topsepadd\topsep \if@noskipsec \global\let\@period\@empty \leavevmode \global\let\@period.% \fi \ifvmode \advance\@topsepadd\partopsep \else \unskip \par \fi \if@inlabel \@noparitemtrue \@noparlisttrue \else \@noparlistfalse \@topsep\@topsepadd \fi \advance\@topsep \parskip \leftskip\z@skip \rightskip\@rightskip \parfillskip\@flushglue \@setpar{\if@newlist\else{\@@par}\fi} \global\@newlisttrue \@outerparskip\parskip } %%% Actually, 'abbrev' works just fine as the default - Gerry Feb. 2000 %%% Bibliography style. \parindent 0pt \typeout{Using 'Abbrev' bibliography style} \newcommand\bibyear[2]{% \unskip\quad\ignorespaces#1\unskip \if#2..\quad \else \quad#2 \fi } \newcommand{\bibemph}[1]{{\em#1}} \newcommand{\bibemphic}[1]{{\em#1\/}} \newcommand{\bibsc}[1]{{\sc#1}} \def\@normalcite{% \def\@cite##1##2{[##1\if@tempswa , ##2\fi]}% } \def\@citeNB{% \def\@cite##1##2{##1\if@tempswa , ##2\fi}% } \def\@citeRB{% \def\@cite##1##2{##1\if@tempswa , ##2\fi]}% } \def\start@cite#1#2{% \edef\citeauthoryear##1##2##3{% ###1% \ifnum#2=\z@ \else\ ###2\fi }% \ifnum#1=\thr@@ \let\@@cite\@citeyear \else \let\@@cite\@citenormal \fi \@ifstar{\@citeNB\@@cite}{\@normalcite\@@cite}% } \def\cite{\start@cite23} \def\citeNP{\cite*} \def\citeA{\start@cite10} \def\citeANP{\citeA*} \def\shortcite{\start@cite23} \def\shortciteNP{\shortcite*} \def\shortciteA{\start@cite20} \def\shortciteANP{\shortciteA*} \def\citeyear{\start@cite30} \def\citeyearNP{\citeyear*} \def\citeN{% \@citeRB \def\citeauthoryear##1##2##3{##1\ [##3% \def\reserved@a{##1}% \def\citeauthoryear####1####2####3{% \def\reserved@b{####1}% \ifx\reserved@a\reserved@b ####3% \else \errmessage{Package acmart Error: author mismatch in \string\citeN^^J^^J% See the acmart package documentation for explanation}% \fi }% }% \@ifstar\@citeyear\@citeyear } \def\shortciteN{% \@citeRB \def\citeauthoryear##1##2##3{##2\ [##3% \def\reserved@a{##2}% \def\citeauthoryear####1####2####3{% \def\reserved@b{####2}% \ifx\reserved@a\reserved@b ####3% \else \errmessage{Package acmart Error: author mismatch in \string\shortciteN^^J^^J% See the acmart package documentation for explanation}% \fi }% }% \@ifstar\@citeyear\@citeyear % changed from "\@ifstart" 12 Jan 2000 gkmt } \def\@citenormal{% \@ifnextchar [{\@tempswatrue\@citex;} {\@tempswafalse\@citex,[]}% was ; Gerry 2/24/00 } \def\@citeyear{% \@ifnextchar [{\@tempswatrue\@citex,}% {\@tempswafalse\@citex,[]}% } \def\@citex#1[#2]#3{% \let\@citea\@empty \@cite{% \@for\@citeb:=#3\do{% \@citea \def\@citea{#1 }% \edef\@citeb{\expandafter\@iden\@citeb}% \if@filesw \immediate\write\@auxout{\string\citation{\@citeb}}% \fi \@ifundefined{b@\@citeb}{% {\bf ?}% \@warning{% Citation `\@citeb' on page \thepage\space undefined% }% }% {\csname b@\@citeb\endcsname}% }% }{#2}% } \let\@biblabel\@gobble \newdimen\bibindent \setcounter{enumi}{1} \bibindent=0em \def\thebibliography#1{% \ifnum\addauflag=0\addauthorsection\global\addauflag=1\fi \section{% {REFERENCES} \@mkboth{{\refname}}{{\refname}}% }% \list{[\arabic{enumi}]}{% \settowidth\labelwidth{[#1]}% \leftmargin\labelwidth \advance\leftmargin\labelsep \advance\leftmargin\bibindent \itemindent -\bibindent \listparindent \itemindent \usecounter{enumi} }% \let\newblock\@empty \raggedright %% 7 JAN 2000 gkmt \sloppy \sfcode`\.=1000\relax } \gdef\balancecolumns {\vfill\eject \global\@colht=\textheight \global\ht\@cclv=\textheight } \newcount\colcntr \global\colcntr=0 \newbox\savebox \gdef \@makecol {% \global\advance\colcntr by 1 \ifnum\colcntr>2 \global\colcntr=1\fi \ifvoid\footins \setbox\@outputbox \box\@cclv \else \setbox\@outputbox \vbox{% \boxmaxdepth \@maxdepth \@tempdima\dp\@cclv \unvbox \@cclv \vskip-\@tempdima \vskip \skip\footins \color@begingroup \normalcolor \footnoterule \unvbox \footins \color@endgroup }% \fi \xdef\@freelist{\@freelist\@midlist}% \global \let \@midlist \@empty \@combinefloats \ifvbox\@kludgeins \@makespecialcolbox \else \setbox\@outputbox \vbox to\@colht {% \@texttop \dimen@ \dp\@outputbox \unvbox \@outputbox \vskip -\dimen@ \@textbottom }% \fi \global \maxdepth \@maxdepth } \def\titlenote{\@ifnextchar[\@xtitlenote{\stepcounter\@mpfn \global\advance\titlenotecount by 1 \ifnum\titlenotecount=1 \raisebox{9pt}{$\ast$} \fi \ifnum\titlenotecount=2 \raisebox{9pt}{$\dagger$} \fi \ifnum\titlenotecount=3 \raisebox{9pt}{$\ddagger$} \fi \ifnum\titlenotecount=4 \raisebox{9pt}{$\S$} \fi \ifnum\titlenotecount=5 \raisebox{9pt}{$\P$} \fi \@titlenotetext }} \long\def\@titlenotetext#1{\insert\footins{% \ifnum\titlenotecount=1\global\tntoks={#1}\fi \ifnum\titlenotecount=2\global\tntokstwo={#1}\fi \ifnum\titlenotecount=3\global\tntoksthree={#1}\fi \ifnum\titlenotecount=4\global\tntoksfour={#1}\fi \ifnum\titlenotecount=5\global\tntoksfive={#1}\fi \reset@font\footnotesize \interlinepenalty\interfootnotelinepenalty \splittopskip\footnotesep \splitmaxdepth \dp\strutbox \floatingpenalty \@MM \hsize\columnwidth \@parboxrestore \protected@edef\@currentlabel{% }% \color@begingroup \color@endgroup}} %%%%%%%%%%%%%%%%%%%%%%%%% \ps@plain \baselineskip=11pt \let\thepage\relax % For NO page numbers - Gerry Nov. 30th. 1999 \def\setpagenumber#1{\global\setcounter{page}{#1}} %\pagenumbering{arabic} % Arabic page numbers but commented out for NO page numbes - Gerry Nov. 30th. 1999 \twocolumn % Double column. \flushbottom % Even bottom -- alas, does not balance columns at end of document \pagestyle{plain} % Need Copyright Year and Copyright Data to be user definable (in .tex file). % Gerry Nov. 30th. 1999 \newtoks\copyrtyr \newtoks\acmcopyr \newtoks\boilerplate \def\CopyrightYear#1{\global\copyrtyr{#1}} \def\crdata#1{\global\acmcopyr{#1}} \def\permission#1{\global\boilerplate{#1}} % \newtoks\copyrightetc \global\copyrightetc{\ } % Need to have 'something' so that adequate space is left for pasting in a line if "confinfo" is supplied. \toappear{\the\boilerplate\par {\confname{\the\conf}} \the\confinfo\par \the\copyrightetc} % End of ACM_PROC_ARTICLE-SP.CLS -- V2.6SP - 10/02/2002 -- % Gerry Murray -- October 2nd. 2002 cl-containers-20170403-git/doc/containers-hierarchy.graffle000066400000000000000000002367371306646076300235510ustar00rootroot00000000000000 CanvasColor a 1 w 1 ColumnAlign 0 ColumnSpacing 36 GraphDocumentVersion 2 GraphicsList Class LineGraphic Head ID 601 ID 603 Points {1578.09, 80.1797} {774, 153.031} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 568 Class LineGraphic Head ID 599 ID 602 Points {646.977, 180} {566.744, 234} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 601 Bounds {{576, 144}, {198, 36}} Class ShapedGraphic ID 601 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 non-associative-container-mixin} Class LineGraphic Head ID 592 ID 600 Points {539.353, 270} {531.643, 486} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 599 Bounds {{441, 234}, {198, 36}} Class ShapedGraphic ID 599 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 unordered-container-mixin} Class LineGraphic Head ID 595 ID 598 Points {1609.68, 90} {1161, 225} {755.873, 282.875} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 568 Class LineGraphic Head ID 595 ID 597 Points {1890, 195.934} {1728, 180} {1260, 162} {737.4, 279} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 567 Class LineGraphic Head ID 592 ID 596 Points {646.03, 315} {541.955, 486} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 595 Bounds {{558, 279}, {198, 36}} Class ShapedGraphic ID 595 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 findable-container-mixin} Class LineGraphic Head ID 592 ID 594 Points {1581, 504} {1404, 432} {1242, 414} {873, 423} {675, 441} {572.143, 486} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 515 Class LineGraphic Head ID 592 ID 593 Points {702.6, 387} {557.4, 486} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 589 Bounds {{423, 486}, {216, 36}} Class ShapedGraphic ID 592 Shape RoundRect Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 abstract-bag/set-container} Class LineGraphic Head ID 552 ID 591 Points {1255.5, 1034.6} {1271.16, 1061} Style stroke HeadArrow 0 LineType 1 TailArrow 0 Tail ID 546 Class LineGraphic Head ID 589 ID 590 Points {981.901, 306} {801.257, 351} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 571 Bounds {{630, 351}, {198, 36}} Class ShapedGraphic ID 589 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 initial-contents-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 add-initial-contents} Class LineGraphic Head ID 528 ID 588 Points {1632.46, 90} {1188, 306} {898.914, 549} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 568 Class LineGraphic Head ID 527 ID 587 Points {1635.05, 90} {1170, 333} {1056.09, 603} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 568 Class LineGraphic Head ID 563 ID 586 Points {1342.29, 801} {1350, 837} {1440, 936} {1620, 1017} {1681.09, 1062.82} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 536 Class LineGraphic Head ID 555 ID 585 Points {1334.57, 801} {1332, 837} {1350, 909} {1458.43, 1017.43} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 536 Class LineGraphic Head ID 532 ID 584 Points {1317.94, 801} {1287, 846} {1206, 882} {1088.73, 884.665} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 536 Class LineGraphic Head ID 555 ID 583 Points {994.187, 1209.31} {1323, 1170} {1454.1, 1061.37} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 538 Class LineGraphic Head ID 563 ID 582 Points {998.481, 1222.89} {1503, 1242} {1681.47, 1106.2} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 538 Class LineGraphic Head ID 532 ID 581 Points {903.865, 1188.05} {873, 999} {982.38, 907.85} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 538 Class LineGraphic Head ID 546 ID 580 Points {1372.94, 576} {1467, 819} {1274.51, 973.746} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 513 Class LineGraphic Head ID 555 ID 579 Points {1378.29, 576} {1494, 792} {1481.73, 1017} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 513 Class LineGraphic Head ID 563 ID 578 Points {1380.26, 576} {1518.43, 810} {1694.46, 1062.23} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 513 Class LineGraphic Head ID 563 ID 577 Points {2010.55, 234} {2142, 675} {1733.19, 1062.52} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 567 Class LineGraphic Head ID 555 ID 576 Points {2008.47, 234} {2106, 675} {1517.03, 1018.21} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 567 Class LineGraphic Head ID 546 ID 575 Points {2006.39, 234} {2070, 675} {1302.61, 977.806} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 567 Class LineGraphic Head ID 512 ID 574 Points {1666.35, 90} {1609.65, 414} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 568 Class LineGraphic Head ID 571 ID 573 Points {1618.31, 90} {1108.48, 270} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 568 Class LineGraphic Head ID 511 ID 572 Points {1121, 306} {1243.67, 342} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 571 Bounds {{963, 270}, {189, 36}} Class ShapedGraphic ID 571 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 basic-initial-contents-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 initial-contents} Class LineGraphic Head ID 565 ID 570 Points {1992.48, 234} {1919.17, 432} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 567 Class LineGraphic Head ID 565 ID 569 Points {1681.08, 90} {1900.93, 432} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 568 Bounds {{1575, 54}, {189, 36}} Class ShapedGraphic ID 568 Shape RoundRect Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red0\green0\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 abstract-container \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 completely-created?} Bounds {{1890, 180}, {225, 54}} Class ShapedGraphic ID 567 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red0\green0\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 test-container-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 test\cf0 \ \cf3 test,find-item/search-for-tiem} Class LineGraphic Head ID 515 ID 566 Points {1859.87, 468} {1764.69, 504} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 565 Bounds {{1818, 432}, {189, 36}} Class ShapedGraphic ID 565 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 searchable-container-mixin} Class LineGraphic Head ID 563 ID 564 Points {1672.82, 783} {1707.23, 1062.01} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 547 Bounds {{1602, 1062}, {216, 45}} Class ShapedGraphic ID 563 Shape Circle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 associative-container \f1\b0 \ (nested hashtables)} Class LineGraphic Head ID 557 ID 562 Points {1481.3, 1062} {1482.19, 1088} Style stroke HeadArrow 0 LineType 1 TailArrow 0 Tail ID 555 Bounds {{1453, 1160}, {85, 18}} Class ShapedGraphic FitText YES ID 561 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 delete-item-at} Bounds {{1453, 1142}, {52, 18}} Class ShapedGraphic FitText YES ID 560 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 item-at!} Bounds {{1453, 1124}, {93, 18}} Class ShapedGraphic FitText YES ID 559 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 (setf item-at-1!)} Bounds {{1453, 1106}, {62, 18}} Class ShapedGraphic FitText YES ID 558 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 item-at-1!} Bounds {{1453, 1088}, {59, 18}} Class ShapedGraphic FitText YES ID 557 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 item-at-1} Class LineGraphic Head ID 555 ID 556 Points {1651.38, 783} {1495.36, 1017.2} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 547 Bounds {{1368, 1017}, {225, 45}} Class ShapedGraphic ID 555 Shape Circle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 simple-associative-container \f1\b0 \ (single hashtable)} Bounds {{1192, 1097}, {52, 18}} Class ShapedGraphic FitText YES ID 554 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 item-at\cf0 !} Bounds {{1192, 1079}, {158, 18}} Class ShapedGraphic FitText YES ID 553 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf2 sparse-array-value-to-index} Bounds {{1192, 1061}, {169, 18}} Class ShapedGraphic FitText YES ID 552 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Oblique;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\i\fs24 \cf2 sparse-array-row-major-index} Class LineGraphic Head ID 546 ID 551 Points {951.3, 1191.69} {1193.41, 1032.49} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 538 Class LineGraphic Head ID 546 ID 550 Points {1057.38, 639} {1222.08, 972.295} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 527 Class LineGraphic Head ID 546 ID 549 Points {1324.62, 801} {1250.96, 972.225} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 536 Class LineGraphic Head ID 546 ID 548 Points {1622.03, 783} {1286.88, 975.187} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 547 Bounds {{1557, 729}, {225, 54}} Class ShapedGraphic ID 547 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 contents-as-hashtable-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 insert-item, size, empty-p, empty!, iterate-container, iterate-key-value} Bounds {{1125, 972}, {225, 63}} Class ShapedGraphic ID 546 Shape Circle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 sparse-array-container \f1\b0 \ (hash table and only allocates memory for "cells")} Bounds {{945, 1043}, {68, 18}} Class ShapedGraphic FitText YES ID 545 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 nth-elemnt} Bounds {{945, 1025}, {98, 18}} Class ShapedGraphic FitText YES ID 544 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 iterate-container} Bounds {{945, 1007}, {72, 18}} Class ShapedGraphic FitText YES ID 543 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 dimensions} Bounds {{945, 989}, {52, 18}} Class ShapedGraphic FitText YES ID 542 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 item-at\cf0 !} Bounds {{945, 971}, {162, 18}} Class ShapedGraphic FitText YES ID 541 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 make-container-for-contents} Class LineGraphic Head ID 539 ID 540 Points {1010.09, 908.993} {1015, 953} Style stroke HeadArrow 0 LineType 1 TailArrow 0 Tail ID 532 Bounds {{945, 953}, {142, 18}} Class ShapedGraphic FitText YES ID 539 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 print-container-summary} Bounds {{819, 1188}, {180, 63}} Class ShapedGraphic ID 538 Shape Circle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 concrete-container \f1\b0 \ (inherited by all that can make-container)} Class LineGraphic Head ID 532 ID 537 Points {1590.46, 576} {1215, 747} {1038.88, 865.692} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 515 Bounds {{1242, 747}, {189, 54}} Class ShapedGraphic ID 536 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red0\green0\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 initial-element-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 initial-element,\ intitial-element-fn} Class LineGraphic Head ID 532 ID 535 Points {740.979, 747} {969.963, 866.628} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 534 Bounds {{612, 711}, {189, 36}} Class ShapedGraphic ID 534 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red0\green0\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 typed-container-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 element-type} Class LineGraphic Head ID 532 ID 533 Points {958.138, 783} {997.256, 864.198} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 526 Bounds {{927, 864}, {162, 45}} Class ShapedGraphic ID 532 Shape Circle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 array-container \f1\b0 \ (regular array)} Class LineGraphic Head ID 526 ID 531 Points {1293.41, 576} {982.253, 747} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 513 Class LineGraphic Head ID 526 ID 530 Points {1035.87, 639} {961.839, 747} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 527 Class LineGraphic Head ID 526 ID 529 Points {884.045, 585} {942.955, 747} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 528 Bounds {{783, 549}, {189, 36}} Class ShapedGraphic ID 528 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red0\green0\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 uses-contents-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 contents} Bounds {{954, 603}, {189, 36}} Class ShapedGraphic ID 527 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 bounded-container-mixin\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f1\b0 \cf2 total-size} Bounds {{855, 747}, {189, 36}} Class ShapedGraphic ID 526 Shape RoundRect Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 array-container-abstract} Class Group Graphics Bounds {{1723, 675}, {104, 18}} Class ShapedGraphic FitText YES ID 524 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 count-elements-if} Bounds {{1723, 657}, {94, 18}} Class ShapedGraphic FitText YES ID 525 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 count-elements} ID 523 Class LineGraphic Head ID 525 ID 522 Points {1870.44, 639.812} {1804.52, 657} Style stroke HeadArrow 0 LineType 1 TailArrow 0 Tail ID 521 Bounds {{1854, 603}, {144, 45}} Class ShapedGraphic ID 521 Shape Circle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 list} Class LineGraphic Head ID 525 ID 520 Points {1698.18, 576} {1762.82, 657} Style stroke HeadArrow 0 LineType 1 TailArrow 0 Tail ID 515 Class LineGraphic Head ID 514 ID 519 Points {1638.47, 576} {1561.76, 665} Style stroke HeadArrow 0 LineType 1 TailArrow 0 Tail ID 515 Class LineGraphic Head ID 513 ID 518 Points {1562.97, 450} {1440.59, 504} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 512 Class LineGraphic Head ID 513 ID 517 Points {1310.4, 378} {1348.2, 504} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 511 Class LineGraphic Head ID 514 ID 516 Points {1411.39, 576} {1540.9, 665} Style stroke HeadArrow 0 LineType 1 TailArrow 0 Tail ID 513 Bounds {{1530, 504}, {279, 72}} Class ShapedGraphic ID 515 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 iteratable-container-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 iterate-container, print-container, collect-items, search-for-item, delete-item-if, iteratable-p\cf0 \ (containers you can run over...)} Bounds {{1507, 665}, {94, 18}} Class ShapedGraphic FitText YES ID 514 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf2 remove-items-if} Bounds {{1251, 504}, {216, 72}} Class ShapedGraphic ID 513 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 associative-container-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 some-key-value-p, every-key-value-p, some-item-p, every-item-p, same-p, collect-keys, search-for-key} Bounds {{1512, 414}, {189, 36}} Class ShapedGraphic ID 512 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;\red255\green0\blue0;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 indexed-container-mixin \f1\b0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \cf2 item-at, (setf item-at)} Bounds {{1206, 342}, {198, 36}} Class ShapedGraphic ID 511 Shape RoundedRectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf102 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 initial-contents-key-value-mixin} GridInfo HPages 5 ImageCounter 1 IsPalette NO Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo AutoAdjust YES MagneticFieldCenter {0, 0} MagnetsEnabled YES PageBreakColor a 1 w 0.666667 PageBreaks YES PageSetup BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpFJKEhIQITlNT dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE mZkLTlNQYXBlclNpemWGkoSEhAdOU1ZhbHVlAJSEASqEhAx7X05TU2l6ZT1mZn2cgQJk gQMYhpKEmZkZTlNQcmludFJldmVyc2VPcmllbnRhdGlvboaShISECE5TTnVtYmVyAJ2b hJeXAIaShJmZFE5TVmVydGljYWxQYWdpbmF0aW9uhpKEoZuilwCGkoSZmRROU1ZlcnRp Y2FsbHlDZW50ZXJlZIaShKGbopcBhpKEmZkOTlNQTVBhZ2VGb3JtYXSGkoSEhAZOU0Rh dGEAlJeBImeEB1s4ODA3Y108P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYt OCI/Pgo8IURPQ1RZUEUgcGxpc3QgUFVCTElDICItLy9BcHBsZSBDb21wdXRlci8vRFRE IFBMSVNUIDEuMC8vRU4iICJodHRwOi8vd3d3LmFwcGxlLmNvbS9EVERzL1Byb3BlcnR5 TGlzdC0xLjAuZHRkIj4KPHBsaXN0IHZlcnNpb249IjEuMCI+CjxkaWN0PgoJPGtleT5j b20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5Gb3JtYXR0aW5nUHJpbnRlcjwva2V5PgoJ PGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4K CQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQk8a2V5 PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFycmF5PgoJ CQk8ZGljdD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuRm9ybWF0 dGluZ1ByaW50ZXI8L2tleT4KCQkJCTxzdHJpbmc+cHM5YV9vbl9uaXRyby5pc2kuZWR1 PC9zdHJpbmc+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY2xpZW50PC9r ZXk+CgkJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4K CQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJCQk8 ZGF0ZT4yMDA1LTAzLTMxVDIxOjExOjQzWjwvZGF0ZT4KCQkJCTxrZXk+Y29tLmFwcGxl LnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVn ZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUu cHJpbnQuUGFnZUZvcm1hdC5QTUhvcml6b250YWxSZXM8L2tleT4KCTxkaWN0PgoJCTxr ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJPHN0cmluZz5j b20uYXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJPGtleT5jb20uYXBwbGUu cHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q+CgkJ CQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwv a2V5PgoJCQkJPHJlYWw+NzI8L3JlYWw+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50 aWNrZXQuY2xpZW50PC9rZXk+CgkJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21h bmFnZXI8L3N0cmluZz4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2RE YXRlPC9rZXk+CgkJCQk8ZGF0ZT4yMDA1LTAzLTMxVDIxOjExOjQzWjwvZGF0ZT4KCQkJ CTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxp bnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJ PGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk+ Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5 PgoJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCTxr ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk+ CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9y aWVudGF0aW9uPC9rZXk+CgkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPGtleT5j b20uYXBwbGUucHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJPHN0cmluZz5jb20u YXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJCQk8a2V5PmNvbS5hcHBsZS5w cmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJPGRhdGU+MjAwNS0wMy0zMVQyMTox MTo0NFo8L2RhdGU+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVG bGFnPC9rZXk+CgkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQk8L2RpY3Q+CgkJPC9h cnJheT4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1T Y2FsaW5nPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQu Y3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwv c3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tl eT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFn ZUZvcm1hdC5QTVNjYWxpbmc8L2tleT4KCQkJCTxyZWFsPjE8L3JlYWw+CgkJCQk8a2V5 PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY2xpZW50PC9rZXk+CgkJCQk8c3RyaW5nPmNv bS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJCTxrZXk+Y29tLmFwcGxl LnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJCQk8ZGF0ZT4yMDA1LTAzLTMxVDIx OjExOjQ0WjwvZGF0ZT4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0 ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8 L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5Q TVZlcnRpY2FsUmVzPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50 aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFu YWdlcjwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJy YXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJp bnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsUmVzPC9rZXk+CgkJCQk8cmVhbD43MjwvcmVh bD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4KCQkJ CTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCQkJPGtl eT5jb20uYXBwbGUucHJpbnQudGlja2V0Lm1vZERhdGU8L2tleT4KCQkJCTxkYXRlPjIw MDUtMDMtMzFUMjE6MTE6NDNaPC9kYXRlPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQu dGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJ PC9kaWN0PgoJCTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC5Q YWdlRm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNv bS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFw cGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50 LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtl eT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5 PgoJCQkJPHJlYWw+MTwvcmVhbD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tl dC5jbGllbnQ8L2tleT4KCQkJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdl cjwvc3RyaW5nPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lm1vZERhdGU8 L2tleT4KCQkJCTxkYXRlPjIwMDUtMDMtMzFUMjE6MTE6NDRaPC9kYXRlPgoJCQkJPGtl eT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVn ZXI+MDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5 PmNvbS5hcHBsZS5wcmludC5zdWJUaWNrZXQucGFwZXJfaW5mb190aWNrZXQ8L2tleT4K CTxkaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3Rl ZFBhZ2VSZWN0PC9rZXk+CgkJPGRpY3Q+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp Y2tldC5jcmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFu YWdlcjwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFy cmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk+Y29tLmFwcGxl LnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhZ2VSZWN0PC9rZXk+CgkJCQkJPGFy cmF5PgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw+CgkJCQkJCTxyZWFsPjAuMDwvcmVhbD4K CQkJCQkJPHJlYWw+NzY3Ljk5OTg3NzkyOTY4NzU8L3JlYWw+CgkJCQkJCTxyZWFsPjU4 OS4zMTk5NDYyODkwNjI1PC9yZWFsPgoJCQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20u YXBwbGUucHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJCTxzdHJpbmc+Y29tLmFw cGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnBy aW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAwNS0wNC0wMlQwMToz NjoxMVo8L2RhdGU+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRl RmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJ CTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3Jt YXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5h cHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBs ZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQu dGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8 a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8 L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFsPi0xMi4wOTYwMDgzMDA3ODEyNTwv cmVhbD4KCQkJCQkJPHJlYWw+LTExLjMwNDEwMDAzNjYyMTA5NDwvcmVhbD4KCQkJCQkJ PHJlYWw+Nzc5LjkwMzk5MTY5OTIxODc1PC9yZWFsPgoJCQkJCQk8cmVhbD42MDAuNjk1 OTIyODUxNTYyNTwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxl LnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4KCQkJCQk8c3RyaW5nPmNvbS5hcHBsZS5w cmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50 aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJCTxkYXRlPjIwMDUtMDQtMDJUMDE6MzY6MTFa PC9kYXRlPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8 L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2Fy cmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1D b25zdHJhaW5lZFBhcGVyPC9rZXk+CgkJPGRpY3Q+CgkJCTxrZXk+Y29tLmFwcGxlLnBy aW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+Q1VQU19DUEw8L3N0cmlu Zz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJ CQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBl ckluZm8uUE1Db25zdHJhaW5lZFBhcGVyPC9rZXk+CgkJCQkJPGZhbHNlLz4KCQkJCQk8 a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY2xpZW50PC9rZXk+CgkJCQkJPHN0cmlu Zz5DVVBTX0NQTDwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tl dC5tb2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAwNS0wMy0zMVQyMToxMTo0M1o8L2Rh dGU+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5 PgoJCQkJCTxpbnRlZ2VyPjE8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+ CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVBhcGVy TmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQu Y3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPkNVUFNfQ1BMPC9zdHJpbmc+CgkJCTxrZXk+ Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJ CQkJPGRpY3Q+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFw ZXJOYW1lPC9rZXk+CgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8 a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY2xpZW50PC9rZXk+CgkJCQkJPHN0cmlu Zz5DVVBTX0NQTDwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tl dC5tb2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAwNS0wMy0zMVQyMToxMTo0M1o8L2Rh dGU+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5 PgoJCQkJCTxpbnRlZ2VyPjE8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+ CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRq dXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmlu dC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPkNVUFNfQ1BMPC9zdHJpbmc+ CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJ PGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJ bmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk+CgkJCQkJPGFycmF5PgoJCQkJCQk8 cmVhbD4wLjA8L3JlYWw+CgkJCQkJCTxyZWFsPjAuMDwvcmVhbD4KCQkJCQkJPHJlYWw+ NzY3Ljk5OTg3NzkyOTY4NzU8L3JlYWw+CgkJCQkJCTxyZWFsPjU4OS4zMTk5NDYyODkw NjI1PC9yZWFsPgoJCQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQu dGlja2V0LmNsaWVudDwva2V5PgoJCQkJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5n bWFuYWdlcjwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5t b2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAwNS0wMy0zMVQyMToxMTo0M1o8L2RhdGU+ CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJ CQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJ PC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0 ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQu dGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5DVVBTX0NQTDwvc3RyaW5nPgoJ CQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxh cnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5m by5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxy ZWFsPi0xMi4wOTYwMDgzMDA3ODEyNTwvcmVhbD4KCQkJCQkJPHJlYWw+LTExLjMwNDEw MDAzNjYyMTA5NDwvcmVhbD4KCQkJCQkJPHJlYWw+Nzc5LjkwMzk5MTY5OTIxODc1PC9y ZWFsPgoJCQkJCQk8cmVhbD42MDAuNjk1OTIyODUxNTYyNTwvcmVhbD4KCQkJCQk8L2Fy cmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4K CQkJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJ CQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJCTxk YXRlPjIwMDUtMDMtMzFUMjE6MTE6NDNaPC9kYXRlPgoJCQkJCTxrZXk+Y29tLmFwcGxl LnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRl Z2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5h cHBsZS5wcmludC5QYXBlckluZm8ucHBkLlBNUGFwZXJOYW1lPC9rZXk+CgkJPGRpY3Q+ CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJCTxz dHJpbmc+Q1VQU19DUEw8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlj a2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5 PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8ucHBkLlBNUGFwZXJOYW1lPC9rZXk+CgkJ CQkJPHN0cmluZz5MZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmlu dC50aWNrZXQuY2xpZW50PC9rZXk+CgkJCQkJPHN0cmluZz5DVVBTX0NQTDwvc3RyaW5n PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJ CQkJPGRhdGU+MjAwNS0wMy0zMVQyMToxMTo0M1o8L2RhdGU+CgkJCQkJPGtleT5jb20u YXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjE8 L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+ Y29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk+CgkJPHN0cmluZz4w MC4yMDwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5wcml2YXRl TG9jazwva2V5PgoJCTxmYWxzZS8+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0 LnR5cGU8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludC5QYXBlckluZm9UaWNr ZXQ8L3N0cmluZz4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5B UElWZXJzaW9uPC9rZXk+Cgk8c3RyaW5nPjAwLjIwPC9zdHJpbmc+Cgk8a2V5PmNvbS5h cHBsZS5wcmludC50aWNrZXQucHJpdmF0ZUxvY2s8L2tleT4KCTxmYWxzZS8+Cgk8a2V5 PmNvbS5hcHBsZS5wcmludC50aWNrZXQudHlwZTwva2V5PgoJPHN0cmluZz5jb20uYXBw bGUucHJpbnQuUGFnZUZvcm1hdFRpY2tldDwvc3RyaW5nPgo8L2RpY3Q+CjwvcGxpc3Q+ CoaShJmZD05TUHJpbnRBbGxQYWdlc4aSoJKEmZkLTlNQYXBlck5hbWWGkoSZmQZMZXR0 ZXKGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkoShm6KXAIaShJmZFk5TSG9yaXpv bnRhbGx5Q2VudGVyZWSGkqaShJmZCU5TUHJpbnRlcoaShISECU5TUHJpbnRlcgCUkoSZ mRVwczlhIG9uIG5pdHJvLmlzaS5lZHWGhpKEmZkITlNDb3BpZXOGkoShm6KXAYaShJmZ D05TU2NhbGluZ0ZhY3RvcoaShKGbhIQBZqEBhpKEmZkNTlNSaWdodE1hcmdpboaShKGb uKEkhpKEmZkOTlNCb3R0b21NYXJnaW6GkoShm7ihJIaShJmZDE5TTGVmdE1hcmdpboaS hKGbuKEkhpKEmZkLTlNUb3BNYXJnaW6GkoShm7ihJIaShJmZCk5TTGFzdFBhZ2WGkoSh m6KXgn////+GkoSZmQtOU0ZpcnN0UGFnZYaShKGbopcBhpKEmZkNTlNPcmllbnRhdGlv boaShKGbopcAhoaG RowAlign 0 RowSpacing 36 VPages 2 WindowInfo Frame {{21, 18}, {781, 814}} VisibleRegion {{643, -17}, {1532, 1473.17}} Zoom 0.5 cl-containers-20170403-git/doc/introduction-to-cl-containers.pdf000066400000000000000000001715421306646076300244630ustar00rootroot00000000000000%PDF-1.4 3 0 obj << /Length 4016 /Filter /FlateDecode >> stream xÚ­ZY“ÛÆ~÷¯ØèÅ -"8—]—¤Ø%²Ue­óçK€$¼ À Vò¯OÝ=8–XÛqüBÌô\=}w_Þ~òço¢ðÆOÜ, on÷7~œ¸Iìß$^ìÆivs[üËyÕžNm³ÙI꼩ú³´^µÍWMÙÙ».§¶ï97ÿ¾ý;íkn|ßÍ¢ûn}?t³8¤Fè¹i’òξ‹žç¼xùîöû›(r^ÝÊêпIiAŒÅ­òh§ ï£ÈKœ7´…S Gã,ÀþX{i>Øñá(€\§^Òi÷òÅÝR§ÝÐÏ~Ên©eèî‚Mj]€¶"PäCœMCÔšýÐ]vÃ¥+é 0ΜªÙÕ´èRTÍ”*eè=Ťô =ß¹«u¤æ‹ Ï©—DáRËÒ}™cëBfå]—o‚ŒOëûç+Èä M hê1ïÛ!¿*%“€X`Bß¹EaÖŒÄèN$fÞ{à=Î#þƒ %†; $á£ÌüÑ‹¼Wo¶+(ñDšÏbÔÓTŸîc@ŠcÞì˜p&ÜV½t¾DFá¥tt§~e§cfj»À†‘aøŒ†_ðOâè†.â&^6J¬É2ç%Í SZS(?ÓÄÙTÁud×;æƒLÈ»R Mk!8÷ý&¢ßM#³TÆxA> '‚"¸ùnù ŠZÝ ™êû¶“Nù!?yÛ/÷ pîxceQ¨Šw; ØÐ•BÔçPˆØ!QÛ2j9ϺÇ,×ë˜ûåªÔõç¼›X²h³Œ«¸ö &­|Û†e²‰M·ã]×Þ9X°AuŸE©)ò®¨~æ+dyPJ{·”ÜN BiH#)|¾ã¹žlÚJ{P&zãn¾Ø¹5F0ŸM@6¦‚kœc‚ØZ_zÀWLj=‹gñYh KòæÀ2H!l‡Fö(ʺk:ÖWm£D¾cËÆxï Ú§RúêÐ`ýžovù¨“õG.ó¾*;eD¸Æ q{¬h£€ð,Z>bw9‰3I‰ÔM¢êw—^¤AXJòâå½b ¤bÅ,<ƒÜû‘Åf?a²ÉOøYæFABD`ó†©B»¾j™¿aàX‰¹r3‰ï&Y «Á¹3C?›[‹é¦¥\¤Ì|5è™7‰£š"ŠœgÂIÞÀ aæ¸Q=3§˜ÀÆŒàE¹Æn‘êÚ]ñ¿41ÝÄOFõa¿ûíÛñœÛ×ÿÜøa伨duÞ~÷k.ø…øüË*Ÿñ^2æ(sÚŽ¹(!DÆ—Ä`^3‡•VjÔ¤hMÛlÁóND@ÊkÙå܈‡.gOý¸¦GIH…t:Ñ,2ΡelXîIžTç3VÊ"!:5N9+ÄùRçàaÅŽ†àÌúЇ/ãW¸àÙ9[&ã|kïr [Cæî« ™ù[0i ‹Îûª”x¤~.ñ¯Yx:=%9¹|"Î9åOár'4¡4´]QJPÁù^#ñèhÞ¸W¨„Dê˜xœ·(?0…zvl*MÁï?þÈ”¿WÞY'ö'‹LmòoÑ®ù!® ``ntõlàcßîÌÍ hx0료¹½4{²ºão³šåþpÉ,\Ì»¹Ég+œõ×C ýþ”ëÖ%w9Hkßµ'i‘TVRþ®ÂäjP%Á,¼4FNbÍ"$MŠÍ_\:À^]xÊbH²û°™bŒœÉfë;E—÷¨ïu‡ö¤Á$Öb¨•“HpkS—8¶tE †|\>#K®/@m£-ö¦dÔ]ÉS7(›Ãpì—S(øfѳ)ÊLÈ\D"³• ƒHc†y¤ p0 Z™V‰|cxO"c!´íîÅñð0ÈIïúüsü~ºßݾÑMZÝ­ü°]Ñ .@aãÉ„3oŽíå€H.…ïÃ$ÉßȨ^eKuÀÕ ;a,ÊÕãväÎ ù™Þt2Èfœæþè‡fÃDzÚ% Ñ|çtÊØ»EìŽlåÇÈ—3I~ ì=ûFZ¤*l4Û!­µÁ B¥ÖÆiô&a!äZÃÓ»Ðj”Ñzì¼5NÒ&È ’0ž ”™Ùa»QmB{ÉÒ=¸Ž£yb%q7^£ê$*ãð{…„6×ë¦Öœ¥ú¬òA”ªlÄ»"±˜tÔtCm5Ar™¿3σ iJ=¡Òn·"*ƒ8cšƒ‹Õ‹´ôf9s@EË®:³)‡j'd*Ƕ¾¨ÿuíÙÅ A 'ÔÓ˜E²Š£É*ϤΩlŠjT¯cÉ(tc/ý½±dœ¸qëjaë²µÑ4E–žY2»l8¿%U–t-›RsžÅ2€M‹êöFާÆi”¢êŽ ÜØ­æïahHšFky-›<9 ’P›8&Û jf <ƒf`´ôgÉZŒÿÄyÅ ²Ô놊<ögó{ëB¹ôÖ qèRÔyc<’ŠPCR8Î(ùż&JǼfy³â/\æ’2}%CDÒ^sÊJãâxŠþZIø2ìÔ`@èØg@œZ̭͡@ UÖ ô8=²Y³Œ‰F×í™Î€CÃ:Ód}/+ˆ‚»òÉÀ4Èâ)0•n1敦”A¦å ‹!ë+kÀ;ó3Îb9@9è}°T·`û…9„(b¬µ ^mÁTþÀEÜk SJJãßüÅn8*,»“; M©Þž''ÈZоk¡'à’¨¢ˆ¹¾¬TlBcsÃ0{$ðªÉù–¢As‡£ûòÔKO¿RÇš¾ì8‘–ž-6c3qxá£GCµÝlï§d×§ÆFHÊDqV©zÚÌ‘’<7ËgNév{]ÍtPçÂ&|S:?`’Ë—‚³IWX´’Ö›Y‰6‰G&¸oÅñ?˜è»Oa1Îí4®5]¬ÂÂEwú¾eñ±õiÚb¥¢©›3Š«Å(ÉÝè¢qœ:›Åêj÷´„úüb|c¹«Åv@J?Ý /Y&[¿QÔ}"Ý¥‘¢]A‹ËHÆ3£QšÖMÏ"èp‘aÚ…f§S€FG9–­ßà’O}ü•ª­õ¦ÆÏ›ÎµPöàÌïq³W«™¢bd̘™Ý€Œjq•øžq3/³±U¿á·„(ÀS/B{%k0›¡.{¨ðg<J¡Þ)O'ò½KÙtûx|P¦<"—FRLE9’|}”zˆ}9á‘Ñ¢3¾íÊÄñÉéÉ]ßй#cmSn¹=·OÓ¨"•þ%ÐÞÁ¶;?•;­¾ÎŸ0¤n1Ê\È‹çËr¯¶(D(»ã§™;)˜&¶ŽJGiQbÏM$5™qužArðaS×$\ÍHPí‹Â)&›j€Ýê4þ_ÌoŠÕ(ÌJ2[ž¬¦£å1d*Äó¢Ô—aþQÆ’Hà=—ÿ±%ÛDËàG s©•‡RÍêVOg´…À%¿©-Âã$Çq¶*Á% Àû²óE/µÏmhN.ÕKÇê5Q»ÔúzÙòÉ㨟ÀÐ‘ÉøæuÇÿ“2A¨6]¦\ôÈ+~x ¢ÿÏå¢ÀõÂHÉ/ c)àÎOQ4†c.—AGª¶lµ ´û#ELAo³“¿hH>>†Y’2ÊÁ3Ü¥ JV=V·DßÞºay£Ýˆ¢òX=æFg±'fUs?î"l¾:gvJ(Œ?"éj/gµ—/yv®Á$b¦ùɤáW>›=7‰›%6wò] yÁ—_’j‡LÇ(ä,˜.ÑÞ_ì?ûPÀÈÑá·9ž©7Å%q%¾†ö^^–{é? èá‚vÁû+hÒ»s¬c[­÷ ^»Ÿ«aÍg¼A{–·áo;ˆÒ|ÆQ˜&áãÝNlFïK0 x#H×l÷OVW™íŽÄ?,ù[ªéÖG –{–ýóæõK³ åî|zÃøbsg7ˆß)Ç3R²è -ö‚/Û·;Þ4·›)Ãì~Z›è/0(ÝóåAî³uòë3÷¦•ù´Å#€Orƒ×~¦ø0uŽPpÎ}@&zêe™œ»ZŠÝÝÖž·•â·¥òI¤nè'Ü×È)w}ÆÏ¿u™wJF.@.Äšw‡sIû§&Ä9œÎýé yøy_þ“¯o?ù/“Ã2­endstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 612 792] /Parent 20 0 R >> endobj 1 0 obj << /Font << /F53 5 0 R /F54 7 0 R /F31 10 0 R /F49 13 0 R /F50 16 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 23 0 obj << /Length 4828 /Filter /FlateDecode >> stream xÚÍ[YsÜÈ‘~ç¯h¯:ÔX…Kްƒ#Ë;rhfÂ+:üàñØI¬º€EÿúÍ/3 G_’,:‚¡uÝÈÊÊãˬ¢¿ð蟿ð½À½p‘„‰›ÒïjsññâÿôÅ…·øË…ç†Yºx ²çúY¶Ø\ÏwMk}}ñþ⯾.¶ôÜ`±ô=×ÄþÉ•xžG+IIGï-² ‘³L‚Ä M€Õ~¸¾øï?‡þ"u³8^\ßÒÔÄÍRÐNk¤þâºø‡ó:ïË»¦}¼üçõ_.Þ\+úqèf‹Éj_C[æqt@¯tž°$t#ßÌ kêË uúKßÉ«ºl÷ =Ï£§!Ñ®u–È8$sîý©ì.—¾³""[**l{üOÔïy¡›šo¥÷øqC¨‚0aÚw ¡GGä&Ù÷‹2ŸP˜ ‡oÜ8;/Ë>éaòiü­nÚ¢lËâë‡å¾óàÁoÔ3nœØ©h"í7ŒÞçùÝ’Dlµ¯!ËÌóâB×´=1ašE³Y¯éÿÒJj_5ô-ýÍ­üBfûrÓbÝHàsã]œ…n§gxg±›y»÷e‚w¡ñ¾—wCíŽ$¿õ´»-–©VyoW;ÅéÉvž‡}øhvœt$çU;Nc×3rl¿bƒk§•{²â³“Є 欄&‘¥²U”®_®DÒ ¥9šTJ³Àyó¬ØAÀ>]F±“³ˆª@“¼NßÈo.â÷®ê¶RÒÅOñp$ô©xøT,Œ}’‰³,Œ#×bfa×ç«Ë s>€OƒºgÄHábj’Ô¹±g×EÞªæ¿8Á¨‘œg'l‘ïFArŽS¹AAàÔǫծ—ºJ‡UþUQsñÖ wg´|²ËïÓòg ×£8!`x>«%aXæÜUÇü'Jvr.ç½ U6´'89~ãÙ©|DdzV”cZHìe>øcˆ MI ߀;ÿ-ŸwØšQ4Ê؉Á=Åבøgê#8<ËV“qbŽù:zï P˜3×Áw1wøÄ VŽ?;%ûå³Q˜Ñ:¢Ÿù1ýåc… ©ó8á1 CÏcC[7àý²Ú ë¹.7#ŸËâœÉH}vL ( ÏΥᢠu“0ù.îÅœÅ‹ß ›âÁ¦9¤ºì†ÌÔ(²÷ywÏxh¸sO±|ÜØ³ã¹Oq{x.²üÔ áyg…m9Â}ÿ²<AIj¾Ç8Ì8}ŠÏãfž ŽùOÇLFÁ¬./‘#§€_ø¼Í[ÁPKÆ]ƒA˜³rf&Ó0ó¬©FkŸ÷(Á–¬µ¿VÝÉ{Ü£ ™¾»*¥øpÏ'WË̺\É]ËòdTÖ0STqJ &x"¨–}'T³—‰t8D¡?*É&‡“%0§ “Ä$[’¶¹¾ÌRGãßÌ8þ+:‡ v^Oß-Á¥×b¸Ã@í±.I3gCL‰Ø:…!̺53|Ú­,Øcæ#4 æÞ)9žËÌÒ7$4I)¹èP\ô5Ž, ‰´‚´+qòÑAßiOs+KMw˜H°éɽ߻åkÉ|Äéò9  ‰NS„Oˆ¸…> ñVlŒOÍë1 ßj‹­ç-ßÛawäêc0|Nl]7pš]+…=Ë A-¨À®Ó9÷ÂðyQ¹hþUÖLmè4ºÔ=ÜÕŒ¶çV¿v#2ï 1¢ ÿW®úî%ŽÝöfHøWy-…î¡ê%B—:¶ÜH1—Ÿ §]x^ì”ÅðZU).c`ôt~~£\Bí&ëPRvš'kÙŒˆA…%Ï?ì»92T{´•Ò^Å`'y}§uÝ Yèhí•øƒ¢|%² ŠLˆ èHþüþ÷l¶À‡(äì-Ö|Øáw+m¢¬`Ñ䜱@m„«ÜÑ7¼>MÔ‰é¨ßË*uãÕ/ÏÙd‰xÈuꋜ AäÀ·MM-i”ÊjæÁÀ`…ºŸr•f|öwLCó¡ä™ÝòlG›^î~Ç …dp3o¬¶aøPZ x!èàdõ‚L6[üÀóª]³âf8búý„„(ˆØ[°ÐBÃ={b)⃒®p §—DJ!åòs¾Ùª ¢¾j6ã·Ü¶ÔD¥狆+NØ„Uµ£ÑuwÇNhX¡eÃPaêœß¯×¤Í%ç*–a" į°èkÞ5’rmõªo@%Míç8,Š…aen•5Zv+%5Å(Š`SKɧg†@x$™²ÆGKà!ÿÙÞq1`m¹×ò–]w+•F $Šã%æ0ƒ½6­ô«š;Q®rÒßÜ•Dbû_2èfè÷¹÷ˆÈÿÞ™Mà²Ò*­EÙ.u‘ +@M‘÷Úµåà£í¤fY$Œ[Î5“,:õ W2Æ> ྛ!Ê›SH4Xî$dI*$žHj‰O¢éJPõô€'©'à‡ÕQz7vw¨LÍ2FšømËn·f€”:U-mùáAw»•B ŽóZa˜ÉCöHÂL9¿ ›o¥=¹½Þ)Š{)m8¯Rй-°®‡ëZ¾iûNú]Ë2øˆ#xn¼ÉÍ‹‰¡u éèEüÔ¢sK#¿šª“ÊCµ–t=*t2eEÄo¾êwùZÅÖÁ¿T ­o1‘™(RY¸Gpˆï†©?àĶŒ¥öàÈ1(‚±Pd½Ê}y§¿÷î±q+$‰ön{<7ðÒ‹l1TÌ?S6(Ê[–M*:xê=›ŠE™ÆãXÑ~láÁ]c Ò1A0Œ¶AIΩ醘•'z6ÍdíWø*y<öpNaMVÄÈ‘Ó×ùlÑÕîtŒ~2vVkNîª>8r*î`î7ÖÅÉÌ3lEb¾TCB¿Ëñly4õ9¿hý êú˜Ã¶\—½:,L|d”°“JÇnµ\1!·Ò(«V÷2ýyÜ–•Èï®+™d‰Àdüv}#o×LcÙQ bØ(•†cŒîUkQùÈȉ¹„i0”Ô¬…Ô»Ó¼°#ÁòÈ:†ÝvËLaC4£‰â@þX× âQñè­„ 9é€ÔN,ãQÜô¤ƒ9)E–³àŸM[)¿úÇ¥dJÙÿRöЇø:bä¥É¼Ô¨Äÿ–oïZ‘ƒ­ ªO„X˜uBb·jÔ·è«^8Ò ‡~û‚/6y?››B‚qþŽx0Ôk¹%-r™êO$˜ïÒz_ß ,\£0šbÔ}>ŠÔo¶;AºËB1,Óξ“%6gÖôEçísJäkK¦U¾º<øì«CMãKµÇíD&_ÜH§JÉr¼´„*-{afy‹êщ%’Õ S”â8ôPÙÖ¼„á h¦•ù™¿18â)M«v(š^šdn©Ã»¾eòô>õ€¤”¼Bd센c2ô+&qYâúÈöLÒ"“\M˜¨»·QXœY7)…œ·¦š“¾F~aTx _ª³¨€× ŒN<’¦hûÇݘ˜[ ön™±C¤#´EY©cL¥3¤CBôÁmn_O=JWs+âK¨a¼¼¼EG½˜8.<™Õå›rF7“­HQ¥„„Q¬!,'CÀ/ ±˜‘X­íG¤ÃÐÊA¦§-WÈùêà ш3>s<;^ZÝ/‹G@R…á\<™¥’°ŽŠdÚFÛ´ér«|¼d•ŽŠ'%âª0e½–ûÀ‚Ät¸è&iˆ ÿ¼½•f é$˜Ú ]Ï7‹`Yê Ÿç§ª9’Àú:±w¤aÄèϨw×Û ˆ¨Ò[ðÐ#çBî$õƒoQ[ã&¡ðRO!ŒÝȘýS¨'I%¡1ã%Šò®„ééËqìbÓtH)(¬Ú+IµjF%?¼6ôßèVÍÂ÷ÝŒv¬P)â?q}¡ «ìyÞåÛ¬\yÎOÕçª>‚ˆE=2½»ãך@ê7ÙÙ,²ðù<\Í\/Nu|ÆÁ~ì¦Yô¥%² D¯½rD.Hå\&¢B&}T Ù¶7H'‘ä=ÄÉÈ¿LœÈm’Nã‘”ÌvUnÈ&žÉÍÞ˜Míí¤"Ã!'êK:ÚØ.¹ºŒ(ú¯Wí%i +G¤7L\ŠP씃Կ1öÐà–.r±<&JÙ<âT³“RÁÒ’¯Ô}%™küd®»A|MLlŽ"XÉj^±•0Â;¤0œ³á%Ï&kÌf‹*b¯ÅŸÖ å:V²Ös›O*Ëž0©!=P!AàÁÑøŸ/áwZI@OW Ðøuo«0’ʈxXMv3á‡~Tž±\×,•Òþ5òù9 ?¤]GFÏ@$ž!A(Y#;ÿ‡B#ûÜ[ ‹çŠÓȨ́¢¼Ñ‚‘o9¥C}’ˆI»8ïñ^j# 뤥(‡Àô®~y„Jñ$‰‡ÆÅß$˜"OϪðëMF2Ÿì„bÈCÒZRda”¶JE`£Iv+¢²œfãP”´æ1Žnì xÆi¶„Z»N'í|D¡G¤—ëm'E†oô»É‡çŽT[7’½Âtky)QV(þ†Ý!&3ÿ½pœ¯ :P•N9|U ™[éeÅáƒY´NÐÅ‹3júËσŸ)®BÍŒ‹tr»q_)^Õ­YpÂßJ’³¿ÔÀØ3qÍRAœ˜Èí‘ê-²êbl~£¨†EExvͳ¡XiªåÍïÉ¨ŠŒ\ú¤NG1²®«iG›nÊ8àÃÏ-ghLæ©¢Kk£§ÑN’H4$·ýr…”ych€ÖAÛÇ;Ÿ u“͵Àu~ê¼ÁÓ<Ú"nc\$IAe¸CŸnQJÅÂ*v’E×Ùù6· I°A¹a¤ˆc§+0n?ü ’„¹5îÐtY•§b·³ÙyNKIãš,¶F»FÈKµ¥,† êòA&íÀî˜Èé_µåzï)ƒEm¥¨Ã#ÔÀ=ÖäYµq«ýpzÎÕû·¯«½þåçëK:׫·?¿ù_…oo®üåOïOã·ô¿oügug¡_› âL˜êMX,yÉ SÒÂéI‡ê‰ïþ^n‹NºŠ’eœƒnª²M³=þ+Î \ƒ?™ž­õÜ1 ûOÃ×MàkºÔgoáGàK,ÞAqaBª óH†ˆ=ò2¥ãoƒ;‹ÁÓd-\7îê®lû¥F±Ø¬qŠfÛƒ8ºÐ®7­ÎÆfÊ\£˜£îJ™ÅTó c¹ó»±/xzl ï'¾Á]wÒ6cž7qò›Ùr²¶‡ûjPÆL°Öìðñ GqHÒä8 D’¯ ÂÃ}5:+½:ž¼ÕšüŸ-Ö’x.ìRjÄÖl¯h™÷‹Td•òoïßþü?‡Jûn’|Í#ˆÅR‡N¬o0pcÅCÒÀ¾TlÍ>Ux‹9oÕJøÔHm¼©&O¥P’àóSÕ‰)ýÜ È  éÑ”g½UZ £ÈNi6rC±XáJŒq-9r õ³Ô™›¤ÚŽ‘ï=Û ^R•Êë†Òäza†øåø!VŠ<øqÂgKâO¢ìí†ÖgEƒU…¿KMÕÏe"¤€o0œß~ÄÆÒpò>.7åSËô }xx5ñRžþHz:,P<úŽY²žqS?ÛƒO]_æ–4®—©¨ÀŒ m^ h²©9Â"Ã÷ÎbèN_a qnåMšÚ÷ý¥{ç^*è §æmɯôŽÁ'õ^ F~< \¹Óð£1¶DïÄÌdüu4²³²v ò‰—·°bŽAX”îGs·¸@õmFêå¡€•›­Dò¿„²8>T”ßF_o ˜ŠÔ…¬¤:>ãùò‹ÆÍ‰–!$GeØ9*6HÖGtÿ‹JðKendstream endobj 22 0 obj << /Type /Page /Contents 23 0 R /Resources 21 0 R /MediaBox [0 0 612 792] /Parent 20 0 R >> endobj 21 0 obj << /Font << /F31 10 0 R /F49 13 0 R /F52 19 0 R /F55 26 0 R /F54 7 0 R /F50 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 29 0 obj << /Length 2758 /Filter /FlateDecode >> stream xÚÍZKÛȾϯÐ-°dØd7¹%cñÆk#kA°»ŽÄ‘S¢–¤ì™üúÔWÕMROŒ=s0 Œº«_ÕU_=ºh5 韚¨8 ´J'iœYOæ››?o~û#œ,nÂÉÏ7açÙä+µÃ@åùdskdinûÕÍÇ›ß(»™/D_…NÔŽxRH{IËÎ>Ú ŒE*›øi”±Ž°Û?f7}«IäI2™Ý÷iæàžöÈÔd¶øÍ»­Š¶þ1ûùæõ¬ß.2&ÈqÍa³§°–QbŽ9s{]åŒÖ&>`ìUÙN}åÍ›õTy»ëí1£:Mƒ0ÿfFÏ˺J2¨«ž¥Ú4B¢~!€Ä*ˆ³ø©—ãÙÑE€$y¤Iv Šàe¬‡â®íšbÞ‘üý9i ʽ®€6¶%ôÓL}F‰÷v»*›uW.¦~lBïneÞ#ÚÊ+*š] }Øa[6–ò^íO D^·Âþ­¬^ÛßBf/ë©Oàoæ-dh‡Šy tL”ÊõV…+t4;NŒ·ÛwÒÀeV5ã«´C¼kÙ~íQh<¾ßñIe3bS†qÅz/mÉC é•_¦¼F¦líÄ -oÌ r%’D» .A|¤·ïGC›…A=Ùçðì+J£ ÓéUH%Yh{éxÄ­pÇÈjü ˜Ã’`”hï5Ðv¹)e)C,Vz"v¢èxÁOk5;Ç6¿‡J;=að÷ЄD~çŽa0žQB±ÝÁîWvûÏ›²9§³ðÃ𦼬ÙA|߯ŒCÍF/¥Y£hÜ\×,|w¤ùªwÖ8Én¶ ‘´O«áD»*';¾Å4’zA4Ì$u¥½¢)шEÖð0è|u«»• ùŽyg7±uÿG*ðó$ó>Ša øê¦k/;xŠ¢ò6Ü6—49ˆë¥4ùb6J! õuM"RVÃŽ‰ô÷ð$ÃŒà–UGdøÁªÜLÙÇb¦5W Ì ,$ƒ¾s¶j1Ÿ—mëtÊ—u!ód¾‘3Y¤M‡N›þ%%îzLBÓ$ÞØ[wŽ+°çè^Vê ¹Î<éšav=ÙK¢˜²e•ʳîA YGêCë‡5\mF’>£Ñ8õZ1›f#FªÛ—#½_Vcé–² &&¤Æ…]=²®-º¨Óûíeu 2ùÑlÐdy $Ó¿¬®0¢0^[ÎH­S‡úàâdêsž4Žb1;4z³c*LƒEφÀ)\tä`A8ÑÙY~âH»¸ZaÅg“±CqIŸïÖˆÓ0Í¢iŠ>=àH|Å4GýÑLÓ$YÅùU]›LY,i¶¸¤¦èŠ»Þž:MžOŒâŒÂÛ½ürÊ[Jû|g©M¹“ÄL: ðÆÐÀ¦C²Õ6¹zžn >á$Ø\Vü ÝP¼Í•_æ}eâ$ÈÌõdØ$!¿‰!ySÍ7_YíŸHb°ócíGaèÍ ÙŒ^Nóš©lúýÊŒR+V,½å£#±Ö í‚ ëÝRæÃmébrÁ”êñ’†ÿܯyŸÏЇ&Lœf““ø‘¨ìˆÿ¾f¤£4MK½‚ƒ¿]"bžæ¸ï +xáø%œ!¢l~RƒÞ^à}õ² M ÓëY¸‰òÀÄ’…#Þ.¾Ù‘DH°J±I/9 “P@AĨ§È¢×S+ Ùa×”þ¢df¤,)Z¦Ýï·ó3ncx:ÕðIʱi#M=ÐØŸP»íšý¼Û7Hóé©i¯B8Öì èø=3Ó eðwÊ=…2_ó£qqVÖêèà ÈŽ­ðÑÓ49yÌùâZ7—Q9¨þy¨t…­ü™%)WeP†”©8Pê|TÎ ³ ¤¦NÉMGâçfÓ<ó“q®½èo7¢Ä»ÅûÛ‡ÀoE‚qd1J‚J³œqÇHeFNÏãâm3ä=, ñÐ:(8ê ÂÝ£4ÈrU}'áËîW ¬ÇÒ±ñ¥}òÃÙèX³b1à‚(Ú»½3€ÖRà{ï¥ikC,?gJ-¡#¥»þwš%¨"T†6. Ò¹²h‘vÇäâü‹µ…¥dD ½’Mº€ÏÛU¨¡bª˜lµ_¬·K™†<¿ýn²7lŠö Úë¦d+ª›Gðª¬v÷ûJŒ °¸ªbD\–ÎĨÓvECD Z2šÌ=Èšè$z¥äJNJ,B kgŸÞ¼A‚Cæä¤÷þõëW¥ùêÃí§_^¿'t…žLyûá½1F¤Ü%7’lݾóo%Röh» $ò0¢å’[)B¬‘¦×PmŸ·èØrîÿª+›{Ή* ûô!·DÞÈUÑí¿º±ûö̱ð AâÝ\Μ^Qgdû¹eõöt6«§]4%éd‰]ÝWl“ô|J“*×E3¹(&°lº•øv_©<ˆÉ“¯e«¸íéeT$Ã]ü§_%R§-B_„³ËµèNd¦Òä2Žëʶƒu¢›I ¡Q9ÏNÆß|š}ú•²÷ˆ°üŸ)E¢¿þë2|óïd4 r­-£»¦>ð ºJ¤ˆfll,ٺїn'<)0wQtÅh˜]‡`Ѹ=õ dÞ‘N\,†oJ V+R xäo%>€z_´îƒ6qŒJà¶F“fÝð£ÂÖòA giʇs‰àÚ¥DFkoQö%½å–Õ‘(r!" ,æ~ð‡)¾P„öƒv£¦/[Z¡á“ƒÑ£‡6ŸXoKwÐöûÍ%U;Ž¿]Õ;å,ç'þ8ƒï),keeÅrŠHÄlvhÈ®j\dH‘UWg\ðl.bœâa(;Æ¥vdZ ›ÞlàêÆl¬®%ıÈ@(Öâ $A<ÿϩ޾T¿Oõ)%[ÎÊíç C‹6ý§–Y2±Bä*¥u–9:øüaix–Á2˜BâëÌ(ß²<ŒpÐîªâÑïš²<åXS’›Æ–cùìbB|KÄï\€d ––mšÃNˆ~]J†vùpð!‡—ò…ilÆú¢C×2qP^daÀ÷iå^h Η7Y8u#íµÍÀT„ºë¿^ÚbHõhïMÛ×î[#a˜Ùm-ð§è%´!=$»ª÷Kˆ9A^IéÜlš!#¥a-É`¹®X”(ã™ÖsêJ¸Å5nàát‰ã³ù ¦õ>B¬ =çcÙü–b…l¹õ-óÑ‹‘²Œ"̓0ßù'Ã\Ôˆ$ùlí€Hµ–^_ÝÊÕ¡_å¥ýl’R‚â2ûÒƒúgìk9=v)qÿ¶d´°GØQ*\Ù4šÓU”3N¸õíy® ý|ž)¶ãUQÙ')òµºí¤ÅEÃ$^×Ô^Ö.þb»Å‚ÝJ#U†G  •@ÒÉ[» aÊÇûHÞ_Ö¬¦8O¿¾‚˜Ÿ‰0ÎHÐçLË·õÖ·¸$<4û^ù_z3¡¶GßϽñù˜4é—²BàÉåÕ"Șñ”? ãg¤ó>NÞYÓ¯d·ûºæ™q,;7ÅŽ³3?NNž‹}°Bœâ¬šR±qQbaÿS‡òóJ}ááÿ;qdžendstream endobj 28 0 obj << /Type /Page /Contents 29 0 R /Resources 27 0 R /MediaBox [0 0 612 792] /Parent 20 0 R >> endobj 27 0 obj << /Font << /F31 10 0 R /F49 13 0 R /F54 7 0 R /F55 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 32 0 obj << /Length 1629 /Filter /FlateDecode >> stream xÚÍXKÛ8 ¾çWøèµVO[Úãv@Ñ=žº=8޲1:yÔvÐöß/)ʱ'‰Ót&‡E€XЦù}")‰„ÃO$Bq&…Jr3elRmf_f?ñd9ãÉ›gÊÙä+´9Î%›™ÒŽIkcÿqö~ön&¢² t%™àL瓊Â2Ѝ„Å©´ŠƒUY® ³.˜õÛÃì—?•H,syž<¬ÀtÃŒ“I®ã †–Ó×eÛÎ?=¼™ýñpT'eBŠd¤ìÓà;ssjY¯ëªe2/X¡ÌË~÷í<i5iSﻞ»í©¥ºpLqù³–^v""Å­CT½Y˜°Â©{ðC ¦¬¼õÛ¢ô$A¸dJêë‘Àm« »fé¿Ì*p¾tiW"[ßdl|CˆÂÈ<“Nªôaíç™r*õ8ó3~ãie‹º—F™®>UN£eãiÉ9° Á6‡(Ò÷‡ý_ vÁ‰’éú …ÖÿÃ…nÚ.C½ß¼šgƹ4ö2x”«Î7¯P#/‚f¿Ú5>®}ÒáL ðˆK–>|bç³`ïã—ƒ¨ÒEQåëã`¹]R£Þ¶ô}Ì÷æ²Iº >ŸD¦™@/l Ô^ ðwRWÓøEæ¯ÛªMàQ•~]c¯BËÖíUB0ëh$²‹:a™léÛ0àÕH¿$e\U5¾Ä­éU2íjd¢ŸdÉŠç{dÉ]£1ÐøI Ñ88ù3zÓÿ—¨‚N!ªVU´“=¤¬CTÁÑuÙR£¤G¯3A.뉀*<©2" ÁŸÀ:‚)F`B»Ð,IìO|jß4lƒo^vœö¡¸×>Ìál¤®ŸŸð3œú ØÖÔ\“«cÀŽ;’Ôr N—F£®#„$á qqIÝ·u»§¹žÜŒ½ÕÓ~{ÙN¼× =ëorRp ;Q»¤N1çt¢ñfÂRV}˜;H‹Çx:U¿bòÌÓ¿É8hÒ×Ðy›¡w_SPT «ÿ¸½°.àƒãe9¥s¯†¤û-n§˜6Çþ&gPj&RÌÊËY¡~týôÒ¨VÁùöš*˜Ê‹ËÛ#Ìh:g†›+÷OX­ÁAÙó®«–I '%“?±ì¶û'£ ÄU?kée'"RF b÷=½KrDVäŒë +Ëcí E[ª5q_¡ ÿC,³—ª_mGW;1¼Áné+ l¿;øCTQÇhØ¬Ê ÂO¦•}r74ïkÏ‚rñ$hùí2ëàON@Kœa“˜y¾{ Cq§$Õc%œaBæ×±â–ÒœaÕve…ý ÀëX ãêSH_ÝõõþžNÃá6.È•a‘¾‡[‘Ï´è 6WÜ [”‰}V‡ÊtsßžÎíkº°ë@›‹%GDsä²—¡yÜÁîe;¸ô¦ ŠËé©°U € Ù °—Ò“Žé馌ô—‡v] 9ìTŽfàp ÚìûhÊ äÿpx¸Óendstream endobj 31 0 obj << /Type /Page /Contents 32 0 R /Resources 30 0 R /MediaBox [0 0 612 792] /Parent 20 0 R >> endobj 30 0 obj << /Font << /F31 10 0 R /F49 13 0 R >> /ProcSet [ /PDF /Text ] >> endobj 35 0 obj << /Length 2422 /Filter /FlateDecode >> stream xÚí[[“Û¶~ׯPߤ™Á·¼¥NÓI¦M§õ¾%y %®¥‰$Ê$åxóë{n„´"h[Ðd§õxÆâ<8À÷áÜ€es ÿØœQI¸Hçc„¦b¾ÚÏÞÍ~þ•Î×3:ÿqF‰(‹ùïpM +Ëù~&)#\ s¿›½žý{ÆŒ°D?L%2c£²T# ²ô•i}! £"›'¥$-9JûëÃìë̲ùÃ#|Z’ŒöT^<¬^ü³î7Í2áÅb½L„‹Ÿªý’-êå¯?Îþöàzà4#)Ÿ{â?_Y#+¨+gœPàëú]Ý-¶X~íöØoá·9\*šÒ”𼌣)ÂG¥D¨ð³›à¦€ÉË—Hš´ÈI)ƒœIK˜‰¼P8ü½>Ô-ÎþJSæ_G P¹¨ÛÊ`Ò°gè糕æeAò›Å¶ŒI,DòœÐ‚…!)(á¬Tì+˜øß–°Œk\" ‚kPé+Ää ·c¸ ½Ý¾ªCªÛUí«¾j몯‘I|QiBêßõÅÅÚ±ÅeãÈk+ËH¶ÇiV§õÚê¶ŒÙÞARƵryZµujaY+PúAë€|;í¡7Ê…’©—Í£nÈõõÞ|»:µm­1ÝÁ‹'Óæ`$Ã#-\|}üfæNè§ai†?- /s5ÑõþØã°Ÿ’ã ‰hPÏñÀSÏòTûú{Y#…(@8¶êõ{_XÊØ×èã•„òéâS–l‹kÝÑÇpÇÍÍ( bLÍx S’ébœ²€I¼àÁ_Æh0Œ@ƒ€vŽžvm½oP»÷ÊáXxô]û„Kµß¨eûV¿zl›½¶ ×WxȲÇç9¦7Éb”YÈã—ÅD£=—Dä´ç9I™&Ö‡N[zäɶ9˜¨à`r“ïê]=öÛe1tø¢À)^"8LÀÄOø&ž5ÍÝ> :]ÝöanÁ¯á0ÈŽ`žŠ:óä)úízmlReO*µ!jÎ"NÏÿÀ•²HdÔ$ÅÛÜ dË4Xo0«Ìøó5.¨z ËAh,:,= ÿ£Š@:¬J4Ð{tê‘Ù˜‰m?´U·cxpæqÆñ1^‡/§¤ä¯jÍGñ•' œp_Y¦$‡Ævɰ ÆTý¼žÌÏ×ÐÂRÐÂë+8$7Ñ`f‘Ü뛪Ç_¦0„[U:êtcµý…2Y¯ÍWhŸÖŠô“_hJ»ºï«7˜lÔpËÈ̉\eFIÁ&Öb&H™¦Š3¯ëª]¡ùÙX³e¢šÛ±xÖ(;²L‡î¾Ï&‘%ÌzØ ÊŒ|é[I N¦ NŒ¡‡Û]bH]g3=uWš¥Ýyˆóx:¬lh¬žÛàYÙÃJkÁ,m¬«´q êõѤ“hІM>Ô±ýÄFíNˆea¥XÓé]÷Õ¶Rµ®÷fïîS‹Q¦î>6Qääyá­/Q‚pÁ.Ã0êäý2E÷qÛóº¸ÝB†ôµÄñõ} ïñ¿]…ö /uU© þPìJðÀü X#ïtsuâÂ?‡ϼ(î*-ÿ<ʃç:…7uåâ;¸C“hWf‘.¾ºâmÝÔ*;¥ˆy¬¶Æ®m]åÕP·Sœµ”Åô[[ˆyVˇ[¦æ5Z˜«Ó¨!5o›“ÝI4E¸}uÜTÝfœä1`þ’)ÿY™²HS"Ù„!H båŸ*Aáio«pÉß“þ‰)$¤„Ya$$x”’¹ °íú‰8Õ“Á}TtVØSñúÑ­¸öê׋ÑøI)Õq#¾ÀRbŠì¢ÌÅ}6„€‹‰£Bä„ë`Wé­wôe”ˆŒ€t@?‡ô ßH¸~;¤«G/ ¬½œí8œWÂh{ØGãJ?r.)™Ç˜¤ûäxL–O0‚eDP}BïØÖëzšƒÔ¤¨èHá©øI¬x£«Bì\ÿY܈1Wÿí Ü_à%#E^?¼”¤,49_›óÑ:qR…?,¡¼³ÓúÈËØÙi¯ÓÿE|¢n“óœ’tÂåñBSêìóíð N£Çp=á·×BšZ;çiꙫ…X>¨>XÅÕyÜÖh³À]|©Êñ™°ÛíN,î¸ãûJ?¸²Q€OUM8»R­ê®T0”j^7ÙÕŸØMv]¶µûêZÙ‹Áëg›r £P4¢ûDc<£„†7y&§…9 óN•˜ëÑØ ðv¯PΑÑS®Se߃FçÉ?xÓ˜äIWBÀ}˜lr®õF›¾§ÆˆFÙ£½°УáÓt<å$—æ„ïaÙAbhê9l=õ¦±……޶@‡\ÉY`„Øž;½dc öNÈŠ’0>NÀ%'¼ÐS§=:&•ÇÄždAxယaOͨ«·ë+µ©öÛô Ž1滤Eœ$+&pÆ?tàzßñxê6S"#ÐÏìéo ;t§—qŒG/íŸìªéãÅ`ý?_á§àIÐ1ÎÞò,Xíƒ)(å"ýf™¤<[¼‚IúG‚ÓðJÇ=‚û×yQ.^éj’{ŒŸ§‹}ÝoÌ ¼YëÓ«fÿ ªDÿiendstream endobj 34 0 obj << /Type /Page /Contents 35 0 R /Resources 33 0 R /MediaBox [0 0 612 792] /Parent 20 0 R >> endobj 33 0 obj << /Font << /F31 10 0 R /F49 13 0 R >> /ProcSet [ /PDF /Text ] >> endobj 36 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/arrowup/arrowdown/quotesingle/exclamdown/questiondown/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/visiblespace/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde/dieresis/visiblespace/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/.notdef/.notdef/Omega/arrowup/arrowdown/quotesingle/exclamdown/questiondown/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/visiblespace/dieresis/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] >> endobj 25 0 obj << /Length1 982 /Length2 3136 /Length3 532 /Length 3802 /Filter /FlateDecode >> stream xÚí“WXS붆C½,z™ôIè R„HG)J É‚@ª€¬tQ°ÒUŠtŒ´‚iÒ¥(UæŽzÖÖã¾<çêx@ûgôO*$©¦yªI€jƒÇDЪf‹§ö©Nþ7Lý)Ž °E~—ÿ>¤ÿH£±ÿU€ !À ¸?KÁŸÞl@ 6$ðϬ €Eã|@ö3„%"±á æ(–„öH„ðGÄaþô@ÛjƶŽffJ?×ù#w…Å‘#‚þ-ú½øÃ1u8l8p¦ ƒÁ©…Ô÷Ÿ/÷?z™áÐx G½šZŠ@@E@©ƒJšÀi8€ÅaÀp §úUSÅáIÔ#u$Ñ€žý¾M M@Í/"ÈÄ}ÿQ·¤†úE:€š÷/ÒÔÐÿ&8 ¨a~C8 þ†TíßÚ ûRÛœú ©}~!œªŒû €ZÐoHU&ü†Teâo¨¨‘~!‚ê*âþç–LLðá§U´„º: ©´tu¢ÿ{Ùq68´04a0˜ŽúÏ-¡CGúñSP÷ÿû`©—ÃA4thÖ'ûgÕ$ǘÝí)aP¤1ñ­½bû¨ù …%~ð*M@Á3«`űJ—íÒöY†Yñ°]abòã(û—ÈϱÁW²û÷gC½fs"ë…]Vsl"ÞInÆ/p4Öô­/jÒØõŽ=/Nw½×ž»Ü±pû¨¼©ã㨤ådhUËu²–¶ 2'àxRB¥¬º„gvpñ9¤waœé©ôï^ÅÇø'1Õ)¬à‡poßeº•¶ï ùŠ>‡0ɬ}åo”£"¦ïötèpñ\—OÏâp»©ºoKÕêî=ïã ©[\YÞëóÞg×Uô17o![‰,6ª¸íz®žòuËÉÓ\‘Í,ø"ä —e†6Æo§pb`3`!-7KÁÀ’{¢w](o']z(%ÅS—·#9®nTiþ%A_ldYéLÞúIŽIøÛ~ëäÛò¢ óÄY°á¹8Ÿ™Ã Ö¥ý¾ Ëœ÷ñ·$MF> #k¬Nír…ª1’WùvS®ç^8œÂ»ñ~¬L1Û(EãÍ6MT´yÈÔ?£ñÔý¡à<¥1“ÏËþqSÅøE…½xÈÈHžºÔó¸õì:C;¥â¨ Á@‘E±‘ó>ïÍ›‡ZÒ»ðLÎÃó‰µYãRó0Žý¾BÙ^©sNBFô‚í •ŠÙ‰ŒÈ¤'ã¤!†'—fŒ›äçkˆº×Ïp_ÏRxwÓ›”¸¢On|¶•Óþ 2Mš0®ðà…RÕã ®^ö´vÈäp™`´dRLã,PäÊÄ+%T ³|ðäêeˆòÙp>®qö¦ÍìY/Q›{ÂÈ­^^òQ=OkäÝë.§Hõa•žoš­n/lï=i‡ÏóŒS|!ïuºé{u놌¶z ?_Áv|{*š÷pMô´ûjŒKKybt`dËpÞN²ÊrFu½FÁ¥IÉahü£€ i¸Ë©Œˆ+*ýCš.}rÁ'ëcAÚè£ýQ6CŒ=ŸnÙµ¾¬_¾>W¯Xj²,ú((³ç'õ\z7QçÕúàxŠYbì{u<+ÓW龜ý]ŠKs í)ÞH37ý#¹z‚›Å5©»Ð§]KÈD‡ÃÌ%è¦Áq7‰›¥½os†œ!ÇË Â—íDS·_ÉK¹sÏô”ëZxØúXÀnf'¥±ñ‰µœÎ¸œÆ6·XÜ dt5ö: xå›,¬?iipM¸º½ªŒtÃõÓÓÇܹ|»»ÄònÁ¾†º›Ag+÷¾L¬žëHþ—Ø[ëð–ýêõ[0‘, Ž@Ÿ¶’¨Øâœ©÷<~ ×ÌøÞk®ýk®Ô$Ñ/á@”‡ÅI†ž§ú)¤iŽ‹uѢ㺠FQ‡¢Ææ3kÁ{¸%Ü®ûQMqaÎòTŸ‘eY¹ƒ¯U"»õxÊ<ІL`{š÷Êãs~¢ÃSNOPË!½‚,,%S}ý~©Ġ숣_ yޱÝF8ˆH‘ŠsÆA3iwI¯f:±Â|_¥ßxºžäe7½0QX3ª»³«xûÝË¢±AÛ‰J'²ã³Y<ùŽqš®‹Þ× ­[†&Œû)¤ë'Ï×I.¨Kú…*HÖJ´3otVF.| µÍÉw¿Ù`Bññ¡=4$´XevSɸæ®óÑÂÚÓIêþ°•YF Œ;l2šG2û÷¡5消ZCæb“vãpduŸÑµ\«Ì'i:êG"Sq$2Ú´-s½ƒ–Ä€-Ò²ŠøÆc¶¤H9‘S¼^Ac$¸‘äš~á"2Ø;ydcb+ ñrsÝÉyþàdÒ]T]òW;ÃpõÍMî†ÇsŽqúÑGJ¾Ý.K˜LéP„w¸WDÉ(æÌã_}íM¤ýöwüž=¿ý±=MGƒÁw›ÒÓW•aæÑsäNgä*d½”/;0kÔ-˜Y‹÷‚º%ó8»vœ”·ëФ‰MQ«³Ø¹7åMâ¨e‰ì`|»¶–Ìó/sZËê‹)tˆú°KÀøÑ/Ûm%Õð nÊåÐs ¶<Ѽp/ël3“oz`½Òn›k&uÊ2UŠžÛ…ä‹³CN˜°æ…|ð§~®³ÎݼûpìyÉTás“ZõaUqãã |ü}²gùeFoÿõr^§/r©¼d†âÐLÙ,@DYe›{ãマ¡ :žfB=7¯Î²Vñ/bŒ>»“ù ÓþiêÓy«I%yNôgŽË© h'ï*…ývA…9’Wëš9”·¡Lt:—ΘUø£Ä>öd*÷ÓxO;n#Ù3ê[{/è®Ãç…Æ>bðœ>öÍ| Jîy†;åcü+gKñ÷ÈeÍLÞó9VÓ=5 dJ¯ _ÝØkù÷bqÝ››ü —ý1õ^kA³úè7tgŒC&¸¬›˜Ú\²òJTRò"X3XßJn\íÝ¿>ÈúNmÚ£¸£öàTÿ”røÿJoçÝžx¤x|ŠŸÙ“ÖZîÕç~ˆü+…í±±Ÿ¼³·Ìg|F­üU¼ðBrHƒXW¾ºü¸ÓTr “¨\ªLW&× Ý£GA¹¡‹xÑgON_ vû¯Û!kŒäØ€ÕÄyùWSµ_‹¬¸)·-p|èÂi9ö³§ìêm¹Çç=‰,¹tÐ>Õ´´ÈËÚ†’y5©pG­‡ö>„\qsû«ðòÈý½ôý…´n¸5Þg±e[ëKM>=°$Þ¾ÍzÝio0®A¤ÐEïškÝÐÝ¿Øì;]ä\N6iÙ>$Š—DI5®ãbŠc,¸mÏ ¿³dÑŸ&³zÈVù¶ûÖyC»Qò¸jb~ÊÁ_3óóeÈëò¸S‡4^òMÊôÒæfÞÜ|ÉÂ8ât¨„¾o æ”Ü-l¹Üõd%_ÀfìïúMnÚéä NV×ÄBBŽž'_ze‘Æ4úàj¡õ)M=¶*d@c>äÖÀadc¿Ð>-å„Ô¦#²j2¼›šSIÙ7üTs¡¨1غuˆsï©3K|¸tù›\¡”À™­’ Î0v®²7¹56SÔ¸™gep!¹Ð¤ÿ¸ƒ‰%/n˜Æ„ãþ¤`p&«sßJíc†©-sšJÇ&¬´¾ªÎÍöNòÑ-óê™­€Î®{w{äfÀ±¥Õüü^v#ô­`­üùW£*gŠÊ„¦Íìýu')âÿš<“|0,òk›ØÇ"ŽxÊÇÀÇ&g7ãåõcfa0!Þ;P•"Û™á ¹UGögi‰È„®.ÞY£hûoÐ#䉑Âè³kKñ¡/²âœ‹n€C‰ÞOngðîHœnÕî3·Xªsàeô¨·Ç"foýÍ••™cÆúü00H§üö¯ìÍ"ãBåÏgfèïûe¬äpàõo x’›jç[EÄÒ6ÖÖÔô$e=òôí&NtYÑ?S}–)Úâ r|áæO\R½¿€ý¤ÓKÓeZÖùŽ[Ó×8ÊÎ&?Žg«ÍvùKºL¨•PËÐØòãáõtóôv%üB²Ó ¦Ó5ºíɬ7‡ M í+ŠùèV¥ƒdË1Ùñã+€£‚|]ÔÔYTâÅ£h%)ú‹«Ë´*b¡)ÇD¤O:Ge±sËÔã/‰v/.BnØÐ0=µ ú†Ñgbƪ).²44óºY1\cpCûÏ£]e2q†:f4Ýñ³KB1&´òvš&J…‚tV–°¯]k¬è2‘Þˆ¸,UÕjê7l4T”f\|ˆ?91Ë”È'n–‘åA„,óåÓÓqƒŽÈÐÜ̬|QUqühúY¨;K”•„„S昡c¶„ðבͼgS-›î>mýfñÚ?)W¹Ž·Ã‹è\«?uã´kzkÒBPXqZóS§‰K¬þs{UÃUoĜ놎E|P1tiµeöš“­í9&Ê·•h…´v­oÓr½¶„æÃ^®Ž N‘kU›ä}#}ŸZjæ6©XzœL,¾ÆP29Ìø|ÝdCx9üâìø@ÿ_àÿ„:DHø@áô_¯·™Nendstream endobj 26 0 obj << /Type /Font /Subtype /Type1 /Encoding 36 0 R /FirstChar 45 /LastChar 121 /Widths 37 0 R /BaseFont /RANTEE+CMTT9 /FontDescriptor 24 0 R >> endobj 24 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /RANTEE+CMTT9 /ItalicAngle 0 /StemV 74 /XHeight 431 /FontBBox [-6 -233 542 698] /Flags 4 /CharSet (/hyphen/a/b/c/d/e/h/i/k/l/n/p/r/s/t/y) /FontFile 25 0 R >> endobj 37 0 obj [525 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 525 525 525 525 525 0 0 525 525 0 525 525 0 525 0 525 0 525 525 525 0 0 0 0 525 ] endobj 18 0 obj << /Length1 1407 /Length2 6630 /Length3 532 /Length 7492 /Filter /FlateDecode >> stream xÚí”e\Ú·°AéŽ!¥™¡Sº»A¤`¨!†NEBº¥‘’–.‘n’–î))‰;žsÿGï¹ß÷Óû{g¾Ì³öÚk=¿½öFZ mI+¨Xêãq‚„Òª::‚'“‘QÚlƒ@dÌa`aHHt·p ~a^~a &#@êìí ±±…˜¥Y~% $Á®Ks'€ª9Ìì¯aiîІZBÀ0oN€¤ƒ@ë×7€Ø ìê¶âÄVKÀlqÂäú%¤èd ü¶rwþÏ’ØÕ .`†K²àŠVP'o€Ø“K üßúwq9w5sÇ_åÒÿZ6w„8xÿwÔÑÙv¨B­À®NÿNÕÿí¦ ¶‚¸;þ{Ufî±”t²q€‡ nr/°•fi €¹ºƒÿ ƒ¬þí?¶¿ ¸T%õ•Ùþç_kæ'˜Ž·ó?E%ÿÅ ß ?WˆÀÈ ‚à‰ðï~ÿ«—¬“%Ô â¿|üsWWsoLøÅ€À€8Y½`/¸/§ß€‰?ÀêŠùkš<<.ø²ƒ¹ã¯øß!^—‹;¶²pøäp9¹;ZüšºÓï°Ðçþ=æÿ„y.gsW°“Øú(è¿£ÿJæp™»ý*áfÿ;ïgëíl þÝ‹—¾žµú‚·‡:ÿa>x_˜'ô7 ¸,¡ÐßEøà;ÜÀŽÿå‡+Øüzfð»òO n ù›\Òÿ üˆtþ!øµæ2ÿMðž¿ ÞÏòá‚V üDÀ \Ãú„ÏÆæ„7µýá~?.aÿÂ-þ@¸Æï ƒ@p §?®ýáÎ \Ãå„k¸þp ·?>$Ø·rÿáV ÜÊó7rÃ5¼ÿÂÿýœ¤¤ ^¾|nnüvð ùÿÏ4]'ˆ‹;XQ~ €@Až¿Ÿ—¥»+üÂÁþú÷‚?Ôÿ°5þªÁ`/°%æü ÔRäµÝۆВÙüñRVD)›Æ8µÚŽÉÖÇÁsñˆ]X—k nÊÒ p¶Q¶iùiŽÈ}é—:}¿ía¶îÓLapš®ê½åLw|ð¤¥aêüQýËòpI’aAoÖqßA®³ŒÎÚ"-B§‘G]gÆk~¹tݰ&Z-ÜT—’pÞ°%Oܤ䥱à»0ô&¶…è'wü›|ôw‰÷¦ˆa hðÒÆú—À‘‹ÞQõä†#’ÖøÆ Ðß}~ØôXCßÞâëN¯3i–¤ÛÀr§çß$s×ò5HbÛd“dñÜ(ŠŸûí¼…*اéxö@Ö×a‰Ux+1Lþbzuˆd´¶šòx’¨ƒòŒA­?@¸H³±ª}Ò,FbLyÓp“Äñ:ƒÅ9d.ö>Zõ²áØ07ùS”/hTDs6K*U2iêÄ+ˆð†«aÇüAºO`Í!4}RGùvg”wÍ®+‚: Ágß_E31í¤±DáÆÁ׆A£+'yÉÌúý¹QkquÖ°äìL²—Êp?LŽë'ð©¿Ã:®ªRY˜HMµcaÈcûKæž1.ué5-¬yî=ºíaî]>ûnG“\ÑõzžJÖ¾ˆø¾#ª2S_ºy®oq03ié€t¥ËÖ>ž+†7­H ©ûØô- Jµ³às'(ÚÃ-\D™~Úô.ùÅ](’ì‰ãÛÔM½¥+¦¢a;¬žai´ÈƒÉÍ´¯Éz¬èGó~y¾>X7­¥aïÑLaݶ6­Q¯¨xj%Džæ;›vrŸuèïPÝëymù¯%Vs¤í!$â\(Å(¤$bST‹ cÜ \ֹűì4ðmòñ‚¿ôª¨¨™×Ú^53 vÆ ­m%u¼fŒ ªd·³W6 H5­=L¹GÂuÙIraˆü½¡ KÉ“ó›dýµtí~–ð1ò{HˆÙœÀB›1Ë(n“$ï0ÙñCyÏfpkó«ú^¥ç’Ñ-h×¼é?„™¬®QȆª c¸¹j.ûö¬ÛM}o3ÅŒ¾(†^|«Úg:µû«·²)’k§,WÙ²¿H4é *£‚hÛ3ƒ"èͦz~„¤Oº¹œÔÌR\‚_?Óó{W­abë|8Ÿùä#€K˜7¤&05Œú/_;|2Ðpì »•uŸV%N„ÞwD¤Ïs|T?˜.黟¡7z¥=®î+x½“™ÛTÔ.+x jØ+ÇœRS~Äaw„\€~³–¨%7u§\î²³ÑSS`£zgÁš9ºæ>®§Y'îÉ$Üa÷X•[@oþj(‘ü¾_¿ˆA+©ÐLg+d|â{CïLÒ1‚ LÇľ#ŸU]¹B¢@È(âªáyì!E0ŽC׋ÁØb§e—/¨³@µ5pÑÌû©ŸëQhÝø aœÕ¼åü™yo(ŽëEŸr‡U0’N¯zül°tæ~ÉõR 䀌ÊÞ1¼ýµºŒI‘oÀÜ­ÑO´iû&»Q:BC⾂”±(É€—"Ú¬yòD÷j=?©ZŒ¸A§ÝþÞ±.v_\ m}d¸ºx’²[1É¿)¾ò›Ù‰ÉñªU×'£¢§Ð`I?Òœ”¦·0¥+¶—Êê"ËákŸõ=9 F‰KU|}ã,«ÅÌ-wDž¼7ÒÓËnáDæ)rbAI¨ìBˆ¢ÄP|‹(4Ç6Ús7üe‘ù¾´ø˜“7’’¯1ôËäiTŽ@WÂz+͇æÂÂ"ô:¦Ÿè•µ£Iô÷a\žlm\4‘A“´@ù]…¡üV‡‰}O‡¨£(æ]ßTwß/ÉÞ]û³›_÷)Ïn²z˜ÔߌhìOÕ}ag@&-go*­Í ‡ÍŠ%” yõ¡äJÔºä ]Ù˜wç‰L|KX÷§ ´)f½‚…í¶ íÇ@¾+3AVcôl“"›v-ø¾® _¶"Ë÷|Æø ¼¬Kâün_ÁIëÑ&‹|1üÙa•f¼ˆâÈmyôfz\¾©Ü;á‚ô¸ªaún©縯TÁÕ㉡Y×d$^cžéÊuŒ4µ{Ê–H·úÞ£zñnž‘‹ÁÚ™¼¬‘ë‹´µLT¤ LP£ôhjáŒ5‚³'§›ïº…šú\#r¢ùÀ=\IK6V¼šüø§‰ÄÈ7Ž©øQsÇ1R „ÈÖ·þ<öÝo*ß~¢x6UN.F#ä´0À>¶áF.3óÏ£“{,üå]<‰Ââè†^1{ø ò»ïØü‘'4ñâh“²ˆ*…ì¤u5Éz‘×1æa"vHf«^&f˜ž·Ò_(£f1ž:OÊwYuglª|ª!o³µ têGÍ%Æ™[K¡Õôä–µTg,.'¹UEãg¡ñ¨i\¨pAÛçýº[j7gÓæ 9âcy´‘Jb¤:C›edÜ2E¿ÕÞÊõ;;­ß?Ô×Ã4vÑ\ožDebIvl€2Á7élÂä´SÑOw¶oH¼8 ;¯Ü3[û´©ùÃûz#«·þ¡ûl16Æ3¿ÁzKÌ„¼ÂJW2Ëñmž>®áæòPvBª5ñn×ô 4GÎθ¯ª,@ø-z%|Ú…÷Ó¦/ÉDŸ…]ˆ¡2} búŒh–¡Ïôp…¹:S‚Ñ:E3¦Êc=# ¶þÒH½¹T…qœ‘3bµGÞ¾l¥íÜ’¶:Û(œ¬èšm É®è³ÐcÞÃü*ŒŽu¬‘nNÜ”Ö3örš oÕˆúŠbf¸ •6aRVfô#“ vüýSV¥ìp;¤G“¼Ô 4v Þ©!qG¸W™Ä‰¾Ìo”ØM^Zi—ê[ZT»·‹ÌÉï«aÏÅ“éóÞ 3F e§ÝQ“4õut$ƒkµuŸ-­É©PÕ&¯º]¿FÁž\ç9AiêþI&®íM=cËO½š®œù éN3eO×ÞuGÄ÷šIVÊfŒÈ:¿ßú¥K„áVaßÏØ:ŽÃôRºÐ®ý~?øMVï…Æ7³&sëïî/ž6ºì­ ñ/Éãò¤<ú‰õ¬dÿ­oÿТ’Tø<Áô§*ÓíóÉ&©= ¤~ä36aã–6;ß5fÞx«ô«ë²;K¶Ö^BøsêCÚ—¬(!”Kц VsÚÈœRy¥¨ý°gü:0-nEÄf $q"ÒzGö‘çÚš‘[»¿'UmtÜŒ‚Å åOú¼†£ •^nU‘5u_’WóˆUàyÔüå*[ Êé†7éù÷Œ<5™¨HÝW) ªÔE±Àüëɦ"•åUúå–ƒKR¾vÉIBÊ®§Ž•¸!þñ¬áÝ÷vk›Xúv¸©ï%uÙhæÙëUXæÜ…Ù4R:Þ$.¯6\-ÍÂÐõprˆq?GzæNßê¶æßD„>yz¯ÊÖ1½m4FœT@g›3š/·!^ˆ7|­”;Èâ1§oµmŸ%´~%Rö$ŒÛ?±ŸÆf 4n¥¹»É\ò3¨ tÖ¶ƒ*àãè” W×Ìwšíó˜!” S=\I8â…ð$gº°ˆÛ)Ô—½¨/ßò©ž—òP)vŒžÆ]u¼-õò´WîÛöG ea]±g5¬]©u.IQžY<=M”‚ÌÌô•™Æ èø½C9'D]±“õŽÂx(ÉE ):#óOlD'fä±",¼¿#ùaå]åÕß (EUó@U­ªÚ%Ö¨^½EõB³Ñø~oO—´,¥‰GŽV,¬øÙí&‘.륄óœáëXÆëà}=Á'xF5|“uIœ¼Ða4ïPĆL"®¨BÊ;Þ¼ô·ØgO,¢îÃ:xº«‰zp4Z8تÀ]ƒqƒnrt0î ßþo[¬”o¨i 1TuŒ ‰#WãA&êéTuînßÌIË$9ßø[ ”k)È_Õ?FÎýU÷hû˜ZDߋް+·0¸ßÚιZ½¶GÐÏ­÷ÑÓaCàš(ƒb…Ì@-9Æâs<Ö#ÄÂð,ÈR°ƒn×¥þÀGa«½l#2Û[£ˆü ’XÛlœa§e·áYMiÞö. Výe;ÆmºômëÏ3W%Ÿ¡Æ8y ^àVœ3‹l+û<"³Mí›c$2µ|!e׿ØL‘„aCå'Ñ¼ÛÆÎa Kž®•Ê€uUSµä§ tY¦VšÈ§ŸÄÈŒ¡‰v"u\}È2{cPsSöãL(©{È¢‰Àš·å«hIPÛ™*„ü­RWÉöÒ?nùí33\LúÒe0~mzYépÇ|¶sTþv%ÉôÆAÿ-©Þ»&Änƒ[pÍVš³°¾ØûNrØ¢²}ƹÔ/†Ç–ÌêSXG2¬Ã7íâL ¸ZoS§,w£«žþÅÃc˜÷…ï>zÜ£ûSeñÙeÔíì³–¼J+Â^Á ŽQV Õc£1´…Kt¼ó­êËZš'LcÅÁûW=Vœb\ÁUü8ÞȒƘùÎ2¯¨´ÏÏ<@+©·Óæ½w猲MÍ¡³<¹$V%‘Ñ“’Ï^ž‰œ…¸1wj†“õ`Ùßé»JD˜j9~¢&ð°cKÕ\èQ1Òæ7{n&¸/ã®Èq8ûödêí]8ï›Lw£0Xž|ôf; Üž&³Ñ®#¸fÅÉE ro°iævÌùõ´UEÙ莗'ïÚâ ·¼bŠ„˜í+ù0óûJ½œÜEñN¬öF ßK·CiybqqÁ(½Ö|7ç`C¶wa«gã¸Om*Ju»Ü;Ûv›'ØqT‘Ö¿SϼcïöÎî>öš§QõQ’rÅŠÛ¼…µ}c»áÆÅ~B¹²-Ãʲ‹@v©ß( ×ô¨ÏÎü ¨”È”ôR3‚µ{✸ÙÒ¡‡j>Ž>ÉHÇÔñ'Ó£µò€2d_‡Ü=ˆN¢ýZ˜‘Õi è 5ö‹ë6ž½ê·‘|çÀüPù ΞE͇‡3‰™.²‰£,ØúÊN é èß*” ^J$=½+ÏÙy;¶é³DfeF~væ-@3;£-èÏ´´ƒöÞJ‰–éåJ§=wꩉ@ðËE1Zw”Öw`æ“Û/]E¿iæfXû†Â5É/H8]A$aºˆ¶‚Q¿ç9dƒ­3cŸ-gkb—Ùù»ûÁGÅPÆ,!õZº_'Jlͽëð•XwÄ ¯‰ñó©' -]§£èD÷«¥ãÒm–˜Vö?ñ‹މ´fVN;Ô 9KyWí-ôns­²¶Ì&^ômšÝ¶âç÷·ð¡­,«`ŠÅ?œVqÏÎdÏ9éµu€I1˺¹§9eš°ŸúLS!ο.)í²Œ½ze1Ó2•R¨&ûãFw/=I›ßyKBžÖrÞú}GÄŠ3)¥.ŸœÿÞÌÂòØBS·ŸÇ¤ƒ8x\à‡µóÁÓ-Cwã÷ K[½©IòUOµ¢G²mÌ_˜übø¤´¸ÌHÓÁ9h;6ÜŸ&„:>ëªçÔ_˜R‚E¤;L&‹âCèI=¯ XF) ðɰõý¢ÂuZOÁ¦ëæ{®lQx ½CGeî„4>,î¶Ÿ Œ;yðß±>z3µ¡´›ƒ¹0øfz£N3=žròèI†@Ç‚ü÷Èj”xö|©Bꑯì"]D›ÜI†åÜ';Ͱ R‘ËÅØG/ÍiþÀAÁ.ÛI “aúð&JßáÓèÐaÐÉ\îÞ›–:D¾ãOô$SLl?i2:ÖÝe®í&=adaþ<“£uÊ4n„¤ó¤ ÷ÖA³$&ñzæÅ*ÊÑ“‚¸)Û'e @A¾Y‰ÖbÎmܲ[·ñ­Ög Ûá|íiüÌ‚l!ÀíW}%Ïå‘Ö÷Ÿ¹Ì,C­ Úž¼þo›ºþÁø,|)`h0Ö(ûòP¬€¢UwzgiБœô Î¥wy²¹Ò¹›îãÃm4‚å…ØJjNm¬Ÿ]îM½WÊL-ä(—uµg•ñÛ I+kŸ—«5Æ7ç¼9ÛýòvòzþÖ•îÀÆŸîÂú± „g6C‰)Á+ ø$ÑÆ«cË8½Ã$¨Œ…P1„Á¶“g§\ÆÇ͉j¼C•OWëS7è3Õk"½$j™À@ºvñÉ@Þ§J‘B Áz-{%b5öÊÿÙs~Ü Av’tÄÀ0áJMfïXàvŽÖnÏ5á «Zx›øú>%mÛ,Î&Bì|À³ ÅàþÂ&P¢•rÉ7NÉà½}‚%ûT<·ç Æ8–g©ä ôÑã7ÉØÎŽa¡Ð+‘ ä53 [D#.M¡˜Ú6Ïe×^@ß,ÇK̲„"&æ;µ¹‘:‰nÙ)¢I²šá:h8S"áŬZ)´:Þì¬2‰@j–Ö­w²"ö‹±ŸÇF’ø‚EQÓø[i}ªÄa ¥'+¦ÍMÞññnÈ¿>S.ÆOv/xA÷µÜÞRH̃Ïrا쀜ÍCênsâûkA ûìJæÑÒ-Uóƒ@9¿00¾G«¯ùQ8¢~”n¦æ›Ö›÷¨FJˆÛ"Ö’†zh$)ÁÓ¨úîµT^é'ÀrpW•Ðàp ¨:Ò}S}ÎЫ©Ó%«jœ*Lp«{e]slä šKy«¦;ëâüÜQÖͼ•ñ™e~ü Ípö±Ü½â¡²Ž$ÈÓŠâà“C‚^Ç62=µs[zm4h’ʺeP ¡¢ø2£A[2ð¦oð¤n5sýÁW‰ÍsáðååÏùÛú—W‡ó‚0…ëO–>èQšmS¨¤4œO±s°ðÎ%dy©ïu5 ÁÑÍMV{Ë~¤[KhÕ¢:La÷Œ$ãÆÓLLš,FÅ¢“?WRÑtdÝ™„.2 UÏ4¨›ÍZ™Ó0>XÙ†k.Á XX1&ùó¹|n ’r‘„%W7Èhs¦ö4™ßÊÛ~»œN¥®Ùˆék©}Å 2«yå< £kGw%fC3ÉyYËÿöå3&o†.xw=:ðÒ¯?0¾Ýäm1^aw˲íQ yÖ1šoÙëRD“âêµ®ïù_é%óqMð,·übL&ÛIÒÚQù¿}EeŒÙ¸VjWÀæÓ*è7õ”pi½hŒßíZù„P¢ëWLÑN½jKgà|aU.@PkÉ *ý|-Aõ„¶¼­-x·ë“åÈ,œ®ï%i¡Ø¨c¾J_A{ÔLg˜jòY0#{–#x‘+»½ÿEK)Z+äUÃ¥ë±w”nRv–ÉJ"i‰^=eTx MãÎ’.C5§WÑ¥çôŽˆSÙ¢í¶/cÖp%üN¸ùgWC„¶Ô9¥Dˆû‘ä¦lXüä…- Þó×l}Ÿ;jÚLøgš’2LB÷ý-^(Èe×>3¸’Ùå$Ecö5®`ÅÌ6àõÒâ‚ÚŒkÈn5 ï)¶Ö¢ØT"·ÈµÛìKY§v¹*RÞ^0âöeK[£f¤ràbÊ^™‡/Û´MÓÙ^Hê~‹Nà2£EãϨ|„Ðneòqé:ek¶"XF—œô1êÅ.±„À`VJ>¯¯§´S1Ó%tÔ,~“‡tY šŸí«IFˆ…… UœG~u24ô ÑÞ§ísn´cbz•Û{åŸ¢å¡ ¤šH[› ìÊuÍ®PDÒ D<4‘ɾ»RÊfHÍ7âúfŽ¢?ýøÖZþAx©Ô½7…r6dÑi#¢Í ð=›0‚份[Vî`æZEŽ›¥ÌlvÈÕPÏ­¿Ë9–Úþm€ßKr?¤q¢Ò†ˆRRÿPG÷eàqýõ‰8æ~ÊÌ3´FMýRá7Ó›™|CmëuTìOòéhT± &/bõÈÝF¯XìR´Ú ÝVa¡¥tÃ> endobj 17 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /HMAWKI+CMTT8 /ItalicAngle 0 /StemV 76 /XHeight 431 /FontBBox [-5 -232 545 699] /Flags 4 /CharSet (/exclam/quotedbl/numbersign/quoteright/parenleft/parenright/asterisk/hyphen/period/one/two/colon/semicolon/greater/A/C/T/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/y) /FontFile 18 0 R >> endobj 38 0 obj [531 531 531 0 0 0 531 531 531 531 0 0 531 531 0 0 531 531 0 0 0 0 0 0 0 531 531 0 0 531 0 0 531 0 531 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 531 0 0 0 0 0 0 0 0 0 0 0 0 531 531 531 531 531 531 531 531 531 0 531 531 531 531 531 531 531 531 531 531 531 531 531 0 531 ] endobj 39 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/exclam/quotedblright/numbersign/sterling/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/exclamdown/equal/questiondown/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/quotedblleft/bracketright/circumflex/dotaccent/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash/hungarumlaut/tilde/dieresis/suppress/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/.notdef/.notdef/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/dieresis/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] >> endobj 15 0 obj << /Length1 897 /Length2 2670 /Length3 532 /Length 3301 /Filter /FlateDecode >> stream xÚí’y<”{ûÇ+Ädw"œ3û¾dÉ–¡ì5fnc˜Ech&d×vÊ&»,B–HÖâ*rìš(RBYCx¦zÎïôëüùûýõ¼žûþç~_×çûù~^×uËr@*cHÞà1‘¢ ‡ÂuS['+m…AääLÉ Š‚#ÍPP€kkÃã ,×Tá:0-˜&D0%ÐÈ8¬/P0Uü*ÒŒ ‡F[Å$°<Ð(<€$¡q …ŒñxÀñë‰@À ÉÁ  à M¼A,ŽQùÈŠèC4¿—1Aµ‚Ar + À ©°"bHD< À€>;ë.•äÿ#ÔÏæÇ‚ðx;á«ý×!ý£"àð´ H„€ HlILüYz üžÍÄà‚?w­((<mLÄâA@®…©¯ãᨠÆGAû>(| ø­1?'a ï[çc–v'~_ê·ž G¤8Ñ@ö·øÃÿfÖˆÈ8*àƒÂ`p–õþõåùÓ]æD4 ƒ#bU„€"“Q4Œe¥Š@!pGÄ€T¤²«@‰$ ëÀLàC"C¾î”µÔ×ÒwÒTÐÿCp PÁü€p@ü€ îo„³ÄÄ%&ý€ê€ ùd ü5Ê7üç MLHÔe5 ¬Š€}5Ò4°°ÿ-t&âÎVfƒi©j~«¢ƒÈdHùöÿ²–ôûàX{A*ˆ†Œ ’к1~ôÚ¸â æù=%Š’iE1Ï›cï¥éBg_ê ö“ï¿p¥büpwøS玗©`|¯ÄkCÛC*±Ãí¼ÂŠ·Ò‘œ èY¯=9OZùY—ߎH¿ ¸taôð 3¸™ã®Í;¸fžøÜöâ¡Á­¥ þá]¯F¸obO¥BÄ*ÂþËœá{¯ª¶)è„uN¬Ô-žDºÍ¨·Æl _¿-á¥m†ªOÛƒŒ¾«ÃˆFƳÈLNõˆMºÒC…^±Õ[}fÝèåÍÅŽ#Ë‚DnŽ<”\œ›ðVHìµáê“Fm$¢­>yŸ¤zvy²Ò<‰;á¡Å[dš_hæ£ÕÖ/]¢ï·Æ²ð3Õ¼ó¹¢iÖ€ÏåcÊýÄI@FVµùJ4ŸSUFú¼)Ë=ß­k&k¹Ì6 ?¯¨)=HÙšiŸ­‘Ýu;îy)sBëRMD&BŽ*öq>s½æwçE¡Oo¼¬fí¬N›•꜋íáq}½‰6»Èà‡b͆ŸvÏr}ìOFNÖ¾÷ܺ!ûþ–äÍŽêÄ#%vîÀŸ÷¥u~}e”ZÛªHÔ X¹Ó+£lòZw5/‹\ ´ ç©E¯)vrôõKͦD†]ˆEbI\Ø 7î=ƒ;ãòAïc M©gz¼÷š]xz¥1¯EÈŒzÙÂSßU*¸KZVë.E[j­ÂºYm|‰c²ëe·X³…ú.ט××½µ¯;é¹ÿ1sRhwø¹ñ"ÆCeÇi¾ð¼Ñ·¡jNŸtÏn×aF$5ÝŽ«µŸY7<_hêxJΉ_šüÝèö.µ-07'1>|´xvÙpFLqÊæúPä°Ó6~ÎÄ¡Ä+”{Ò‰m2e´Û·ºÍHì…µ! 5 oÂMIä1ã cODé´Sçß‘;îì°UqɵìÅY¹šóÞ×t´Í©{÷\f¼õf×)1ãh/n1Ç’û«³øÎ~:Ì"J]ž‘–<üú•ZѤ¶š ›¹…}ÛšÏùôrüôkÆ|%}WÚ%¡øÑîΤ ¡Çvß¼ÐyŸ˜Á×ñcÛð~\ï‹ÑXà–ï‹{Ypi·È'×ÐS~ÿDl¡å¼¾bTQ–žxv¼õÀçOàmÆ%àdIHA6Ü÷E¿FçàÊcîáó Y‹y¾•aªèùàÅ%êÎØùz›ËZë\ òe§&’–èÓì/cC6ãЇ~³ŠÁ³ÏféMó*>ds¾dÜ”èÔvǤœª&'À´äËÊÀ^»ô(L>5öáÊ’Ô(þóP8íR‹jòËL‘‰ýy¥w÷$6¡ujLQieúµÎ=ˆg¯mî†=D¥sSsgbÔë3`"Û`l©Š—àë«5¿*“§æ\útÉ‘Áá›"Û|蘉צ »,ãáA´mðÿ07uÞ²:QÏ1iŠã^ØŸUÅXIî1ÁþÅDüÃœË =EƆ ~¢<Ó«ú Ñå'ã—?Ã,”~ CLñVôúGGЗ ¿3­o³×é.÷…ƹK&¦‡E‰&ÓÂj«¢µÒ?u}®%¸ÉQ甫¦…µžf˜ÖM5“™è_óm:-Û ed3‹;B“—DÇrí ô ú‡mK’˜¡WFÒ#eCFWQˆ Xrœ›üêÛè<Î8H§ÉhvWSt5Ñ“óð®>|@r5‹>ùÇý…]+ô¼¤5ûÓö;"¦½Å…iצ8ØÅw[ÿÝä¸oçÕI¥csãö-;TGB¥ílÎa¢"¶‡þ»¬[úõÜ«㩽¿—5"Ív´Ïb£Þ‰0^´ZÇuLè¼n42¬Oo¸'WqvÏ£NÕ}ºB7BàS{œ9º8…†iX'Úœh¡|6dªCÿ£—_^; ]z õ¥ ®¾$¾&°¿gaßÖCôε88!QmÞÕ?8ò1ƒ±©G—m4øpK¾lWÇÌV¥A²¡ëk†.WðÔ&TMÊÓ®ºÙÝÛ¹é(¾áß·âÍy…͹~èì‘£aÞgvozxùîlˆx6]QmÃõ¼½÷Ãh[S-ÄäŽÊ :­œ‹Ï=-s/ÒuçÊìªûm˜^^ç²4ü©O¥{oTü±k½·¨³@%£ˆ?Ç¿¾Íü<’PV ågœ#†¥¹œ*tçÅÞ· .J<{+2ÖqÓfÝóL£ aâ˜>fQ?Ïé½`Åo´Á‹w=túZæ²Ho©W G#¤\ж÷K1°É­O«’Ëo¤k óg¥=®ËÇG»^ÂF]¨‰PÊÀ|¤]+7m/ã2ä Ö 1¿¨ë’¾k¬}B#Y|@*—ØX'e \Ö4:»«éÓJÇbjͪ{̤ˆ˜,çV¢WsúÁþä¿ÿh<ˆ"SHÙò/§endstream endobj 16 0 obj << /Type /Font /Subtype /Type1 /Encoding 39 0 R /FirstChar 97 /LastChar 116 /Widths 40 0 R /BaseFont /BUFHNV+CMTI9 /FontDescriptor 14 0 R >> endobj 14 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /BUFHNV+CMTI9 /ItalicAngle -14 /StemV 70 /XHeight 431 /FontBBox [-35 -250 1148 750] /Flags 4 /CharSet (/a/c/d/e/i/n/o/r/s/t) /FontFile 15 0 R >> endobj 40 0 obj [525 0 472 525 472 0 0 0 315 0 0 0 0 577 525 0 0 433 420 341 ] endobj 41 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/exclam/quotedblright/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/exclamdown/equal/questiondown/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/quotedblleft/bracketright/circumflex/dotaccent/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash/hungarumlaut/tilde/dieresis/suppress/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/.notdef/.notdef/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/dieresis/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] >> endobj 12 0 obj << /Length1 1206 /Length2 5334 /Length3 532 /Length 6107 /Filter /FlateDecode >> stream xÚí˜W\“ë²Æ©Ò{YHDBGz¯Ò;Hï!!¡÷.¥HAAz¯ÒA"‚Ò‘*M@”"Mé°ãZg/=k_žsu~'¹É¾ç{fÞ™yoÂÆ¤gȫ෫Âa^¼‚|‚R@%mE3I  Ÿ!› ò‚ÀaÊ /°PPRR¨àí  ŠI ‹I ‰²•àþHˆ³‹SéÞO‘8PÁŒ„8€`@m— Øíá‚ á°—?P ü|Ãhö#}ÀŽ|„‚‚@GˆƒÐì òÿ,HæŠÿvôöø÷#0Ò]]ä= ºDG8 êt;òëÀѹÀèJþ7Šú§¹ª7ªrÿiÿ³Iÿñäúÿ—îîáíFµáŽ`$ìŸRSð_µ)¡ÿ‘Eà …8(Àœ¡` À_!ˆ§*Äì¨ñrp: žà?ã`˜ã?K@wíÏø ÍuMÔ¸ÿšæŸÏô@˜—‘¿Çß®?Ųà/F÷ ñZ ð ¢…èï¿Yÿ#— Ìî¡×AT B"Aþ„è½@“(0P9‚ý€`?tÁü|0¸ú º#Á@'8’ðç0EDü.þ.`ØÏø_!I ?þ›E€ü^¾ð_,ˆf$ø7…ß îüF >¿)$€üp(üW1´á öü¹Ø¿‚â@~¥¿IHí‰ùü"´Rûo’A·úoBo?è¡SÛÿ"ôáþ&AôÙCtFðoˆ¶uù ѽ‚ü†hcèoˆvvÿ…‚hgØoˆv†ÿ†èŽyü†èDÈßÈó7DŸÜë¢ï=¿ßoˆvöÿÿs á~¼èæó ¡§((() þïBc= eô ÄÑ#øuðF"Á0¯?/=zÁÿÍNôuƒýÀ„sàÒQ®MËBT ÆÊq¹0›“tº';‰"gŸ`B‹‡´\KõfçÙT¤›¸›Œ¾—Ï¸Ž ý÷ªßÂI™Ó×›>v›Ù­³Ãlmÿ æ“Èm²ö¦©ãQL݉¥á²TóÂþÜýí|=Ne£Ïx‹L=–>=O£ÄÄÍT³¡Æ1ÑõìÂL䙈²X‘˜¾ä©É8G#C\cð[¸àÞ”çøy)×¶ØŽïMìN´öÒýI>Yœ'½;¡¬ ³.ûä§ežPuio¹È˜#h =|ütŠãˆÇË*«ºËc¾zêY¡Å™.þm‘r5”¦8‰ƒuJ]„l¯M‹ kþClÆwY߃êïFalhz½DPîOykÒvõ<ùãˤê!žo €Êª'¸šR å~:~áM»0ñjóùY2‰‘oúj%ÂÒmú8¹Áõ@ìë“v=ú…Ûþ…@-ž—Ýú¡Ü©©O¾G´ ólЬ£gn}µº«@díS]ku.J×OúG ÑGX®þÒú›õŒœ·ñC1‰nœ9xÇ·"¬èðX˜«}߃œ&쬉ɨhÄ‚š0î' 2ÊŸ¸›(w†–¶Ÿ_êÃ($¡Ã‘i£;ÉöklL±¼Ý‚n„”¹¯Š.L7MPĬg\§kUrÎ \C>÷“`!‚z t»Å#:K§úÓü8 ³5ïô&ì$$Þ¹\”#'—äm±èW*”¹ÝôÄފ¸¯­Ó‚o’iÈùoD9Y¦560uB³*‹{ˆî'‡úŒ†}03)Òµz»t¶C¥¡…'<)Iñ¤ý’Æ5'æ.Í7¦Bk Þj“°±0§`®F×á~ƒ¦ ð…qup›(Ä…ãä\ëO1Ò66I`6k>ª¬QY~ƒ;+ÔÕšf,ž¬¶¹_óΫ¶ËÇcè² %LÄLÚ° ùNLµ>Üåú(ÝÝ+oª04í¾ö8Èe+Uù›ùqR Ìù»»çW“»óôUMkÝ·vºÎgèvï«ö ÚË$–¿ƒžÝãNÈûÝÊ› KÔ/êȸºAü´WSÍŒ' u[xV,Ó+V5«W”eÓ®RXS:þèIÔKùI±–E7)Dwù®cW'»I1–Nd‰Mà¸p9ʉ†ÙœãjÑjd9~ϧò€ôc'•Ãy<ÁôÔhßæË”»¢i Áû ®$F넸”ßšýiº)wèW‚§ÚUæT8v7B]çÊÆü1q<¹Œ²SQ ÉSÏØýŒŠn•þÍKZ† l…S­R<éï)ß‘§˜iõ±Uê!só8x‡Ou'žõ°Ép¾»qvRà{¡˜"¡Jía>ïòr€éáö¡÷µƒ&žò©hH?g OìÛ#JMBÁd’Ëûžc~¨¿¿’Ëà ¬ÔˆÑ2¾z³cš\G#•v÷ã"S÷S»¾½‹‚H]X@Ýø"÷œc¿ƒ‰Ý×3X`,ÒfË·}oO¬KvÅA+ɉysã‘Os*¼ŽEÖ× 'n†aípjÃ+Ø›LõŽQ+û*¯%qØÄ³q§F(é1>(KB(x¸›à‘\nÒG îd¸Ó{"Ç )ÇúŠ[À–IÜqý»:[äFiÑôÇ"ûà‘7ÍÞ ØÊÅšý/܆”±[LJVXzó’`LY½˜É×J’§}¶4‘÷w‡ÏæëöÌ®ÒÑ ¾*_eëé¶ÞÇ¥‘yÕâö¬á0£`å=ɃOÐo+<”%œœS¨•¡#ãâEvŠ ÃíØ€sç·Nç\MNÁøŠ¥ù¨¡@éÓç+`vßO\ZÂÇø˜\>²Ûê)!ÕžÒž“þ†R ‡·”–’+PØñOIó0ò.Abƒ•9Ϲr©ÛšIÍÌ2’[ürÕÙÈFíõI÷B“ô£Ù¸2"û·ꆚÍi¿/çbñìÐßtPŽ!%Ô¾Yä#‡JŸËªÚrUÙå v66¸RÊ•¬ù³-ÇbG¦Þ5‰¹î¼WÑNµ%c<÷ç]”Ê% ­ßŸœ›8pä`ìehÉO¢ûA¡ùtq»–¯¼U:MUEÀ+Ykà=8‡ïc3⾜~¡¤F.£®2'Â8òð¢ŠüÆ©ü©VÇÇ7 îj8§Gé\.Ó·`²;c±•s8Vº•;òKZ›‘Ìç~iýw¿ V\∙m{ÕçOاk ¾AøWÖ>ɬ4VWì¦[n´žÎ¶4D™Ö7ï?!Æî›ˆ¡x¼bHìòj¯xxð|€H»y$÷)EÞ¡‚%#NÛêAè„â=*Y¥ ¶"µ©a)œ5ÚáÉϾØìæ²»ižwñ2éÉqønmËrb „“7™ñ–€ƒ²`{Á÷¥)1mb·àjbFg¹Vy•3sµï—’” gÒg2/÷}t™¸§íè4÷¹Œ«é¼s=ßPp{Ö†ä¦|Ÿ·"u<¢çm½¾ïö£´+¼ÛZ¦G©åzÐÉiàåÞù€—ÑÐEkFXÿWltîïOZŠ:N‘S`ÄB}d•z¦¡ ¼7«[žÑM±¾ÎÁ=?¿Á-±WV“D탟JÌs£"/,„ìÞo9qŸèà|°¡éÞ9œþ,³¼ÂéøHq 7ÓËtõå0¡S&f¡ÀCõe’RŸÓÇ‹?åþØâlŒÀI§MUBô# :mòi"ç‹Mñ½pPcÖ]Ã.V‹×Ñ_XÊлKÓe}L™lb„<$^óÕÃj—¾«Z u…Á¯rÚ€Ó´?T¬À%g¦ùÊ7"¼³žÖ°Žaí ëKÖ›-ÕÇ]˜<$¹¡ß •BŸ„ºñéŽF/-¼—–ßËžP•ÝÓ¼ËpÖßqgSâ¢Ò¥7§ÅÝEПå`G¬¡ôáéð•FXÌ‹·¡8õO4ã”bq‚21PÎÔÊYÞ­L¹û­ „¾a²ðo'aè,dõ¦YôXÝ‘9ÑÚî¦ñá"ÀJuæT|ÉåÊÙŸ# …j(Tùâþ¨ƒE”ìø1.äyÖþ {Å7—8M%Ç.¥»”G‚-k³|·é­¾êe¥‹7Ùá½9ET—«ŸHP'è„#y½N™#Ž^˜ùYë‚ý­‰ &ø¡fdG‹'#Ϫt' úSuCêªs­¡Ïh§seN(Ê oh<èfz³?ŒØê^1ó½$ZzMšÛè«æì¤`‘½¬-Smð$ã[¬g¦0h½=^=zFÄsŸZãcŸ¿‹Ï¦ÐkÍY¶«´ô~²z™ðé}ã¢$ËQ¦PöYêÍÛ¼ª×¨¬G£_¤R™ƒÕ’ÆóŒ%‹/¨Ó:£ éq¸<¹HM£Íc‡™Æ™ž™f.Š­á–ÛÛÄÒU'쀧¸Ô ¿7bû©¹>µ{Ëøè½SÔæ0>ëÚøUÇæiÂ+NsM¥êÝÝ]EjfƤô8(ÛpÌé  þì@D¨¬Ø\ËûŒme:Ï¥¸¼Öçý ¬Ÿ#/)¸H:0J;ØgJìJ1§¢"hÝ|B1µ§½ Ó)#<ö<ÇÕUÙûì+Þ?£¼T êФ8þA^ËÚúRÅvÛH€ð×V"Ùô©^©l,o™*õE C5FWâk$‘åVÒêøÛœ—úËeÃî:Är¥|_Š’ì!±„Ú˜ ÏéÙ u:ÝWgUË 3SîÍKO¯÷¦`‚A&åNY˜ !n˜}á_ªü§¼ªW¬nX¹ˆÝŒ;ÂÛ컄¾cÚµšÀð‘iG*>k0§NNºá÷]ã¶²+õköü lÿÎÄ›ª„ÃL±³À!bþŒ0í$Ä$QîÔtY6 ­éˆÖBìRêI]Ž×Øà·ÑÅÒµê%û˜mÚGvÎÜMJñÇ=Ñ-…Ol’†‚ì³/E?øw(Þñ„6P¾Æ¹C\"y÷â;»ß;³æˆ G'euô÷nóôð \fÀ\¿Aˆ3Fû½‹ñ Ïw×ÉïjEê°Xݦ•äÍ…6ÿÐ܃ԚäÅ{íg,V«„É2Ÿ)5.|–¦kÙ×ÕJHê®»›ï`Óí",Ž_#q,òjÝ"/ÊÖˆ¶0Óaµî¬cÐP^{¹ÿ¤zXÕOv<~ý„^¹6ëžžmÎ</9”É3e3!,^U¾yŽÙˆÌ5žafó¼b?¦â NºérµÁèô\çÛ¿¬âØ?óÕ’Á¸G 44C{nÿ/¡Ÿ£Qk×Dq*4P0Gr“_Rãwóu®IžMÓh^èó– 먀…¿JtÐc¶&("Ì /oÆæ;׿æ×Íö}z:³£ý®rŠ ºŒ8W«ÄÅAÚcꃚ8ãÅ(©N$-Gà«ÐGýá‰HM¼¶‹£^:ÓÐÒBƒbSŽÉüÙ´ ²`’ÑK»£.‰„ú…ØümŒh¶ íy:â–]`]ÐÇ…YKÁ£('&¤<”%ˆ47:ÑúÝLŒÍd‹± }Z–znû²éR/©,Ë +íL¥ZgÆ›¼™C•ç)Ä&Cg€äI*‡Ìçwˆ›L¢*¶Ë¾“q¦ '0 ;ö[ ꥙¬–»j-<.D¶/Öcf1“SH µƒMj0¾`[æ8®áë©7}h\%"=?¥$¶à™;,Ÿ…mí‹Û_`YRAκÆds*,û™ó‰,oAíÃyM)µ…}ãùm¡™Qûâ­Ì1b³î\è4_ÜÌ[l*KÛCBÃ6äâï¿} ¦²ö[  ^2•»O á²C£¾{ãèBÃTÞºž7ãñ1âñ%ÊW‹¡ílº¾áo æû»J±ñ„ßГwéÎ)Û6 VúrY ÷ôáÁT¦ú¬~£°6œÁÜG´‰µ4±tW.’x´ú/ѲYù òƒÞ’ çw’ÉmÚ½×)_øµRåŸ{Ô˜kM\ß×è!èyLÁ<\D:lâÍiUÈœúìÑ‚ø*v:† Ùñm¿~~؆†9ñ„Í”õÙ!ÿuqÙ ú›)J.É4½«¬£M&]€úÃÍ<³c»x²!^t¥êvîkÆõPËg{¼¨úðé[»˜eÖ³Ì*çp󵱪ØXŽ´Dr±+-/håC5ˆ…UÓ1+’µà™ý¢¹?Òíx' À0Þ€Ù/§‚|‹å¦Í"1ÙqOZ‚ ¹ØUg-ÌÕ–Ã.w–êø¸®wËw3' žEü©kEƒÇð­yà°+nÜ;Ìù"•7)ƒ7yÝ'Úë{ý$&.¨ÌkÖi½¸ÞË9l,ÐÕ8o{\ºÖ¡ Ea‡Çk£›ë[Z–ºÊ ·ýܲ&¢ù/…]P…ÄÄ8V(¥†²w#J1‘š—ÉnÂ9;q1Gã¢GÀ~8ù4™ÅŽÍ™EdÜü|†XÜ„bcáR`oè4»§ÛÎ÷6,4mèb~mM%’Ÿ<¿Ú´ î?dè®I~ò©£›–WRA·vϽÛH|ŸJ…oSÍ·Xòu>Û :%`½_y ˜ÇVÎ^Ü™æÁÙk’g‰@Ô¤HÀEg0ÆäLd¶«&íÊSV2 OºÕ[(Lj5¡ÞáÉ\Ê3”W¦U›BµGÊþÿö0£§zÉÄìr]úM8)þJ>e-×ü{ÏàRá˪5­mïò-@”Áí%SPÃ.E±”]/\Å5™ü åVv‰¯¶1ɃâHA7¹×uë…?:||Ã'i,mI5‚~Š©4z¹BÛÔG ÙZ)?òYÛGvή’j 3\ §@B7’æDJWèzlaU-Kþë"CËuÝñã×WëÕÑ>LF†÷’žRŽíF—qlP”xdÙè’:ˆw¾<øfÔÁ+›‘g„îy€FO¯Ò°/ ä«W¿Ò„#,.Vb>õiŽIûÈô¨òëC³'Z<à˜¡nÌKLóæ³ã2mƒ÷‚ ZÙU"î~Pœp§ƒÔmþHPLvDÑqíäIüóEì‰8üh¹7%KÄÊÖFÂ&å푯úèá¨2· 2&…‘.¨ÿçƒQ& ·hç´Èö26Åï:à?Fx|{ü›k·P|€é‹ãVOå—üRÜ 8Ýž>uýJnR½Ûy›ý"´éXþµ€Òû±£ënL ©^KØŒãÆLz¼› CÝmõž»o ¦EÇÊð9BV\pYkoia¦¶¼THŽŸê/’Î^ ENV>U ýn°LhRäãm‚!Eâ™\¯cðÉÓ$?‹[l¡ÁaU×úD5¸ë2ªw5ØôÅeõ¾kdbÛ6Ù–Ælffê(»Ä%Q®‡Ðç›Kƒowûü¶?¿LºWÒð[e“9WÏ·ë"1’š Q¡k}¸3˜ÓæÆø&°ßs%m°È¢Š”®HÿÎ(ú:býk9‘}ƒSY¾á¼\ûXí«¯û$az)Ñ¡óSý—/Ïö=Ùó³Óã§ôWÒ=ÌÉ3ÆW¨°ùʼ·r«UŸ3úÒ¯’¯'»Æ jË{ˆãܱkƒÙ¢`Z¶çvÅ>“u4Uɹ~“’EŠÞÅKQÖò¶1“x¤sðïîΘ\©Ö I$d¶Ë,'ÝⳆƒÀw*·çr‰-b ¹?,1Û#"ô`cžÊšŠ¶×/öÖ—kp²¶®;ólZo“Å}ÀRS mÞzQ+ÿó/Ðÿчðÿ þO8@Á ¤Ü„t#ü^:endstream endobj 13 0 obj << /Type /Font /Subtype /Type1 /Encoding 41 0 R /FirstChar 45 /LastChar 121 /Widths 42 0 R /BaseFont /TSYOVG+CMBX9 /FontDescriptor 11 0 R >> endobj 11 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /TSYOVG+CMBX9 /ItalicAngle 0 /StemV 117 /XHeight 444 /FontBBox [-58 -250 1195 750] /Flags 4 /CharSet (/hyphen/one/two/three/four/five/colon/question/C/G/L/M/T/a/b/c/d/e/h/i/l/m/n/o/p/r/s/t/x/y) /FontFile 12 0 R >> endobj 42 0 obj [394 0 0 0 592 592 592 592 592 0 0 0 0 329 0 0 0 0 559 0 0 0 855 0 0 0 930 0 0 0 0 711 1122 0 0 0 0 0 0 823 0 0 0 0 0 0 0 0 0 0 0 0 575 657 526 657 543 0 0 657 329 0 0 329 986 657 592 657 0 488 467 460 0 0 0 625 625 ] endobj 9 0 obj << /Length1 1730 /Length2 11051 /Length3 532 /Length 12027 /Filter /FlateDecode >> stream xÚí¶UXœÝ²¶‹; ÜÆ îîîÚ¸»k°ÜÝÝÝÝ=8 ®AƒËßß\kÍdÍÿpï£}íæ¤ïªUÏ[Uãm(HU„Líâöv. FÀgb9enb#3…ˆÐÈÅÒÞNÔÈø™ÀÍ r5'fa&p|fåþÌÎ@A,bïàédináBL-BóO'±-ÐÉÒÄÈŽXÎÈÅh ÊabdC¬bob tñd$²±!Vþç„3±2Ðèä4eDˆM-M\ˆæ–vLÿ葲3³'æü/³©«Ãÿ¸Ü€NÎ QÄÔ ‘4Ä ‰¦öv6žÄ¦@3&y{P- HÉÿ¢þ3¹¸«¼‘í?éA=ú¿¼F¶–6žÿí··upu:ËÙ›ìþ3Tø_Ò䀦–®¶ÿé•r1²±4²3·3ÿ—ÉÒYÜÒhªhébbAlfdã ü—hgúŸ"@mû—&uEeYaºMó_.E#K;UO‡'ý'ö_ øÃ Þ8Yzë0323@ ¿ÿù¦÷¥ÄìLìM-í@ëÀÎAläädä‰Ú ±{ˆ-íLÄ@^&F;{ÐbPK|‰Íìþ&hÞLfÿ²ý²€Ðò²‚Ðæ²ýüÇÍ rƒrÛÙþ1B]í]€¦Æ6ÿ5ù{¸ÿÛó¿ÍlÌÄLFN@; Ù_VÀ[ÿ#TÐÁÆÕùTÎÄÞÖÖè…˜ÉÂÓÁh÷ÇÄ:*koúÇcoü7³ƒT¸¸Ûÿa®òÚØÿIÂÊ+ô‡@)…ÿ'1“ÈýC Jbÿ&NPñ?zJ‰?ê½ä=ªÔÕ“ýC zrTOþê)ü›¸@”þ¨‚òUPùC Nªþ!ÐÓªý!P=?ª õoâfù3ðÿ5BÐ]gú3nHã?Jaòg­˜A]1ý A¢á?;ù‚d›ÿ… Ý!Hø_ûË ê›Õ_Òdý‚DýµÝÌ U6©²û AªìÿB*‡¿¤Êñ/©rú AªœÿB*—¿¤Êõ/©rû AªÜÿº  U!H•ç_Råõ/ü¿_HÂÂöÞ  kÈÀZwP9ˆ9Ù™}ÿw š¥£+PJt#˜™9AÃýÇjâ꺊.ÿú½ìþ‡Í,A¯F Ðh‚°ºdoÂóÅ*¥9´ÌO¬à{94-¸°yK¬|Cï|bðJ¸Mñ¸Œ#íf½æSE:Êô‘û ¾ó×N¥)ñ‹@ÇØÔÅ·7Ãt¯6|Íët9Ï}ÒûàÓÍ ·gìà s›e‰Z…CY—çyŠÔ¢ª‡°ë$`}:n}_885ÅÓmÔÂBê)YI”QSËÂÙÂ6ÜQã¡6f‚ý¬ÂàZéÖ®ì;]ÑŸ àrÞtï±bÐL:‰X•wh1•ÎJ ÃP?Ô½ŽÖf›«8@ÿ€S— ÎÆ­ÉòÂ3˜½Äž —s» oëÔ$y¥àÐÛ,Þ3`¥3°(”^)b¾Œ/°¯jöœÑlß'xÇlÃ3TÃZ¦ùE±H«Ê¢ç×à¤rÀ/W¶10òNÂ\º"BK@$Héóø8ªƒÿš‘òŸu’‡«Rœ24nD¨~A²Tð =*ƒ)óÒþÍÓš¬”CÈû¾©ŽÁü^Te”É€â¾|énávݘ‰j©øùl@Ë; Ïòâƒò‰W™¼Eïä«i¤?ÛoG‚Ú#‘1Ìu“!Tï5ׄ¾~-’•*ÖTzVëk§öúÛh È·Õ0orÌR?S9ªä_BžÏFd³Ý»KATí èy€¯W‘û±\X”Ø=•,¥ã²) p‘ÙûbÖfße8ï¾t6i1 ±ml^oãÚ­ÀsV`ÙŠ 2 ØÙ¼Å~ÛSᚙΠœ‰˜ÀC†6>ݹoéB‘ S…×÷åÁ’1R2’G®ŠhøæeøÍNM£ç–LÔYRÎÊRîÉÖá÷úMw!D 'ŒŸ¿7Ë í|¾2&=\.ø¸b¡Û«×ò¨ä;†ت+RØNn˜Í]×b" ¿!CDzXùWƒ­P„=½(sol¸Xuz£­ eï¯ôâ"”î”ÝÁ?íC­ûVŸá•ü—á ¡Ç«Ú0Ž &š×â|™ºbÍ~Õ+šY\vÐ*„è^žMÎ@Ÿë»Y¡| c]t%{ƒ³gËV \&ílnäøßùä[u„}üŒéÙñ,LRˆØFŒO„X¹|ä2œJN¸e•6áõ›Eo‚i M™"6Œ‘€÷ý¼àB\Sè“Q„L—/)þ– s~ƒ‚‰]†(ÐY(LH* ¶Å)ŒÀw3™‹æwuàU4ÃH¶EAñi‘ã„ɵ»ã_:£ížê+Q@ä©çB*!4ўݽ|X}ØzoC>¯r­šûÈ&iÁÊ{ï¡»€“¾ºÓ[ÑgõP)–]”‚å{œ^UJ®Q¥Z@J#¶JÚdp/ç2‡éÃYdhm}‰ô‹íÓÆQ±¼ÏÌcujÑ$c¾*'Η†É1}Ki8[’ÄÄ–1JOw׈5ê®ç‹¥¿däXÂõ¹é0õ]ù•!{¹aÂìíå>ðm¡&Kˆ8Ñ9þÄ0ÑP¬BÝËŠòÓ³Èïýºñ R„[%]&–é–i /÷×é4M.;Ü]£“‹U•¾,ÑBµ Cªà”ooÅ€5˜$™¸ma0µÐDó`€HnmA݆iüs¾ëßæí¼3!—wåz¿±,e„zàcSÇõ¾“ TDÒéÁ¨„J{KfŽä9Á4í¤…·`ð&iP€5màBPrS.`±}ìÛf,j„Q¶š×˜à²3i¾[¤Þê¥\ºNàWIïþl¼Ö„°A“zÐ¥\äé¢!ûW0‘Œ CáÍheþ-=— ßøärZT'±YS3§™`ÑÎíx²f¢ÄÈò*ØB‹öÙ†¯Ùì^$EQœêvÎå+Nï”ëWì0¶Ð‹×lª=ùІr6Mò<Ì´éàüba š(XRI)‰¤œ£Œ/ž7A¤w°T¸I–Ýô´Ð›+óF¯ѬxüÄÞq o½;KÓ•ÛÍiåF`ƒÂB£Ê³;üií‰.‘/C Úˆ”÷½K^˜ò‘w?Î;2ÖÜKNF9ûMP”9®E>96 ØHn0,wG"S.ówWìG4™`ÉmVUÃÈv«9:pÿ.Ú穽i¡ïÓQSM•€ ^³…´Ú4œAü¼ŽÁ—(_÷M¹[§šÌý†ônÍÈ +:Á)(¹i”`Œº—ä‡WýCüûò*»¢VÜ5Ñ”u“ºêÚÁÍd"$ŠxHè”ÄŒZ©êÔÔœ÷ëüÃW°Ó&×&Xîû¯{÷”õ*w{¥•QmÑjz„ÄŒêÂáPÂÌ%6¹á—Õ{¸üÝLòóZD¾F£'Þܪ';Ÿ"8œVüÁõ†I ‰þ|êy¯p—ê§(p¼H3”ÞKÜ4É„öž—fÄèO·÷H¾úlj£© ˜ó§Ëæäíƒ'ÄÍÚ|»ÐH×éé §^Bc8·AšÈR‚ðÍåºñ ?Æú~QWÃZ»}Ä üᨖà^Óé¬àV—4Œ'…¿B)ÇÓ\ÊÜ"² qvò‘j!*Ùð G¹,ñ²T{ùËܯ­Ye’œ>¥.¥@ãY:móíXKš˜Ü"f_õæÁ<³W\Þ¬ÙpµõͤAÃlmT}èú_ȘWkÎ8ßoF®Ûº’u`ev‡þW3ãÚ˜_º“Ã[g£*}:‹Ý£b§"m)=erYv…”ÁaóÕ¼WÁÅþr‹/—’æv¿FÕT+’"x–•®j­ûðyôsõáAM «3¡p€´ŒÃ²À9¿X¾^=C`Ì*Û(•ô·¼Õ«u+8 ßý€ñJ+ÔüC„DJ„¶‡¡ÓCË•³œ+%Û¶S’²¦håÝÐ΃õ ­QÛª¯J&Dòö«_$ ð9çlbÙ_wV¤ëœöíÖæNÙ½=&~>a1¦Ç¸| RN®YÚjYPù? —)\Zk?¦9Õ¸\«3y«šÍ=1, 8¢rûºÛeú—јF´"œ­rR?oêÑW/ÎWÆrë?`â³I¼ 7óÅšÓÔúo–X@snÀÝÇû:ià)¬5¥ËkøÈwîçø÷~2üqe¹¶Þ@‰«Tõu(ºÒ¬²ÌIˆÕÙ`é',WR|%ôÓvFGqçf?Àª2™c¢gœÔžásÄÞŽû,b0z’0d`îÖ°ÝA Aëxkrÿþñ”DÙ§$Âk5øN6†RøC;«žšS¾]3.F̲ö–e1­U¾»åž¤ö»îùÑ£gÛ«`\vß ~áÓöæ·? 7Hèc„hº—í¿Oyü^qâïߪôºŽ­Ä#Ùl‡VáA[Ÿ™:Ùø°MA»|«Œ¶æ±Ï€ˆX^ŒP7DÍ+ÒCD—KÃ@¥¼Ó¾º Ù°—ÑÖ¯ØK0ÿ­4cJË ‹gVènóåQ+[Π¤mbŒ@#¨}Ee32ãöþãRÐs8Ú•¶ÆÞ&âÓGUÍR_˜z{zâ|uNª-ÆÚð«v“:ßÇJà~Šò/ ûŸ@Í!Q ™ Ï°ù´•¿¹…R†D°-çDS/ƺքHKpÄE-Jú²8)ú46ô”ºo3G_¾äPÏû¸þŒGlaqˆ§Ó •,è¢èfû5”í¿Æ´…KjÈm­+­ë âú­ô ŸUæ›eàJ”Yÿ Ö®Ë8‰åÛÌXPX‡À¨Áž“æFÃl©a“ÝÌÒ“ ޏ±àá”u˜pH@¤Ù„±KØ€4'& |ÃÔÏ9Ô§ˆtÌÎB ‚:ËÁˆ=&Ù^äüf4×øhó_Ifæ ÒÔFE9JÙ!Ùï°º£sû@¼ZŸý3ê‚gbO ¨Ù¬Pà%;ä³¼ÿñØWþðD¡ŒQÓíãËt‡Y³Vlˆ½/4e½(,ÞOÝ\à&ÏÏf9˜]x“ÑÌŒVØÌÚàk‡s!ŒUéÆpÏ6«•4*!uì]R uÆ 6Ø[ åEj·p1/|ÂMaòZ£x®ë*”’]LÅ…I`±y§› <õA6›% …ê§½pºE¢öÈù±&h3·X›mÒ'%±÷&æ,&),UY«!V2ùà4Ä›ŠàXèøR©xVzEéT¢ëUÞÐX€q+XC(ôwdL2ûËxpêÍs(•vúbq×i)µ/iV§ fFºêeö–£vîôzº24~x£ÛmxYVü}™ÁÏIK¨Ù –™Å˜­‡—Ðè×Õ²hÔìb:‹ÿ=hÔ”vGA@:ðJ×ågáP¶šSÎ*±oŽËøó<äc|çÙ<ºˆÊÖ8Å—î¥‚Š¹±gy v’ Ö4¾}wR¦¬“:2f~ì¨0o‹àÛÙœgRºß&…»›!àƒ\$§­ˆh<´ßÖ€ U;ÇFÜ‹'¢¢܆sË=;÷$º½F1óÒ8Ä“÷¤8½ÁÉn•ËHÇð–ËG8ËË~ÓVbûÈnº© Ý)´Žàè˜î!¯Ìi"“ŠÊà ‘"/̦ãÝ¢ÔÐQ¹©vþ-&òs;|’¿°ŸÜº·y_3ÊáÚjxé`UU˜J›éÜn̬è±-=”÷ÑáwØWïj½/Ìwܶ±ÏNä¿ôÅh™7XãÀŽºâÔNΞùš¢ÇÌOŒ«bI! çñZW¿!Ån—ÇÂEƒ–_|ýLmV ÈκÙ@ÃÙ÷Z ™Ø,‚FäÞï{ lL¨dg—õ§ôà@æ U\È¿Öù°~²¾>VöÓ™[äî^Lió1Ô²±Îv÷!UY)òe—ä¦B~ü§ ¹^û¡Ñvía^Te¶VhÙëÈü¹ã® !Ëú´ /ȲL,_¥¸Æ…ÕV^®ÇMß„ôöÊt!t(ÃÁ[t‹SUu±UQ‹¯Àa¾ÔÝ,€©ÕÛíå„sÀðÝ!àÄþ‡›BQ;,k`j`¡‹Â¶8TªT]A• £ÐÇÒì¦=°ãGÈÝ“ø¨V‹±iøLžSbzñÓ~ŒÔ,«4òZÃbþ™Ø’—³ Mm¨wST¾>ûšo*ºù¡IZß§ä³9ºZÏom—¶?§‹y¼Ñ>nSB/dSYkõÃð¬'Uh•*ríÌÄêæç¥uˆX Ñze.–6Ãëù˜#çÖQ—ÀÁ,)¬WÇe§‹,‘¬6u‰1r­ÔO€ßý8ËT'¾W5ºúHoç†LTPoI:P 6ŽÃñ@-Q£Ép–§”ɉŽ8'^ | )¯Ð¬‹$”õGhX•Р‰¢²3õ2â¦4ŽhÌ<¨s¢eím6®J`v½Ý³&w ˆ–ÝWsm—xFÆO hzP˜U&z憰¦y²½ÈøÚp•h}k×Mpò"ynU÷–—w½¾}ÐåWKÖ ‡‰¢:F‚þ !GÝüu=ç循ƒîCÊv’¬“ÌQHܯ—"D²›èƒŠPâ&aj7íçº;î?yYƒ “©¼—«¬cÛÉxžâ‘(´;ô¥ÔD•(“#(Éñ£eeVYé×òœë”Œ¹a›äB“-0-tÈ_}-ƪžð0~F{©ßo{D|`ÖIcyìP˜=‹8Þc•÷xÞŽŸ¤2iÔÁÇŽ_p:hÎL\>]W%ŠÉ> +»)Ž9q‹ž”韧+±4§£êÝ&XÌöá—²–Јq7º«?W½¦žÉQmïºy{4U|í°’ K—úºƒ®Õzf-±oÙÄ0„ýò;Á8€I»è“¿œÑ—Ý”*Äé0ßV?ývŒ´¾;þ¤Û†Yllaû`àžâÇaÓºå«`™q¸ÈHRè? Ÿ˜´Ö$Ð2e*õ¶«(ÌVSØù3c`F*-„oŸËÔUõÙ …k ¹nôq¿5c_Ð2ÄN÷^ "7¾e]ðMµëPðeYÄ’SyÆÒ]LQ?¤Š†FÁéÃ÷¥¸Ù¥ þkY+DÌlõ˼QT£³eÞæà·0c„sÉÝ $L…¥Â½îˆ¯®;Mò¾¸øÔÉvrÃ<ãSîvt«“ ¹´„D=E'0öÁt dNg×* Á-|zÙ•ðo/¯ ßb®O%ıÞÛ ‹˜iÛÌ %(è)›ÝÂk+ X¢ß5ÆMýC`jëk*>¸Òt×GÒ½ó—wÝ£+eHfù­ê.õŽ D JÁÀ¦é_öO ÍÆÓ;/2÷¼³Ý/ Ç=Œ…Q·½+gûý«9d!Ö`²qI̼º~(ú’¨aå&bëÇL«¥¾’/£s†w"ÆÜÏÖÁFˆIP5§†Éj@£9Ö@õ÷°õŒÑMú¬s¥$av¢vDºÇÈ,¥†z‰‚éï—’uoúN ‡â‡O;n¿’=;k_¢òó|8ã¡1«%(=² áýíPy]è B¿Ýõ^K§¹Ò7>”~¾ôiöðóÍéSÖ{?ypzõ«GøâúüÎsºêj.‹ +/ ̘yn€Ž QªzˆÇO8‡ŒYyÃRÊ/’–2Z4à曆@& io%$¾›è-ÏôT¥Ff1ãùžä1z/S•ºÿ°á~3)¬³}¾ØÔIvàöCb3P¶cú6½˜6©#ÒóbŸÙå¸óV™Èa÷0íf_Ÿ¦ïãÄ)Þ@¡ˆ/2Ö|- ~Õ½zšÃÛÍ¡CÓ\ñéau:ôü…DEöyØ2#”&=uß<2;nûºŠÔåLpN'à÷ΧöµáwzÌœÌ BZi/$8X“ÃΞ2äÈtÍý+‚ KwíÉkçÎÌÛEΡ`¢ÝãúB'”7ž¿ú–èXtõxškˆ±¢Ðc Û‚,žíg§‹]æÜ~\Õ·ŒP;×”èÈ«¿zNá¸pYÝ¥åp¼K+#…ñÆ0øÏj&CµßãÐC-”Áäç܉¦jº»G&)hË j8R5ø8û‘¸.v¢ÛÆGiþz=œ——2P5àõä÷ û¥Ðô"*Ù+™}I7™[‡ªŽ‚}[5"mæv7eÉñˆžï][_¶ò[­Ñ}Öl›ý ±ÈmÃ鉙ÀÈ-Mø@ixjaÞ·ž!—CÆþ³ÿ“ÒŤ—†(fPà ˜²œSדõÎÊ*1:?Ð[ˆº\÷ù=É*Ÿr‚ÌUïgÛ Æw™ýäGENu|éœ9xx45´3$åÒ~iu*®9ȱ—YÉÆ™K;ÆåL‰½v3y½z` Q74Ýk…UVŠÕ¶¦Ñ×;Þ¢x ç²}•hdŒÛiX¬Êh“ºêå§[z9¨Xwõ\¡<`ÿg&¹ý²«ì1âgÄF‘š¬œÅŒÓ͇V$mñêàÉ(øžt=Ê r’ûæ°o%ý¥åå1ÑpÎríÊ3Ó¹‰Z¾Á¯%ÝM3AÙnšw…·ÇxMüÖÖ˦ÊéÂ>YÐê™~¢q–'a˜Ó$l¸XÕŸÐ64vxh¥Ô˜Aë‘E­½6CJ$›O éÐðôý þN,l%ÿ%€B@À$÷Û~Ù58á&¨ï IÓÊËÅÌâˆ;KÃ4z¯ŸeŸM4O!ŸÌrÊÙi1ÊLwìz¼°•ŽøÔ¼[n¡O­ƒ“Ëÿ¬Ì÷G“P¬,SÕêÇÆJTƒží¯„J<ÇjîÆ†½¶½/»cûyl¾¶;›°gjoà†Åù;ì†Ä„ð/&ÇZ²ÕÖåkŒõ[fãa¯XÜåyÚ™J÷âÄÓWÇéÜuÅVØà,ý¼§Uf¦êìŸg`Ǭà ö¯»RL‡³V×ÕßñʇžÁ/ž ÎN·xˆvÞ‹p¥²[%ÍÜgUYÝÚç\’¡ŽNâoˆî’ß•uw- ÙJR¡Bµ!4¡´iaì¹Ô´É¼…{xdr05‹mš‹.|o|mïüÝPI¶£‡?ãºó#®“à;ÊĹDŽtø‰oР”Z®²2S«?sö ýÈö3$T;·ê¶|²÷ÈCdóä×ú‡Eæ Þ ^ÇC°/gEYk¯ñ/)a1øEwX…¾;³ÝEü´ iF\­{xÞÁQ+㇩u¿èÜÌ“ì×̰0[ó?v:;Ù½˜ ñ¢³(pG ófÊ íøÌB㘚š¹îfå£1ºÚõ:aš6>’FÇ=s[Uî§B*)ÀîÙ.6ñá§Ú¤¶E\ëI\:ëXΠ+9»ný2»Ç'æ‡9 ÿd“ÑgúÇ•U›§ˆª/#':—ö+üMÉ=}_þ'½rºª©/6&á1D*'Ôž7Ö8Ôºé÷¨}ÝœªûL—?Ü>ÙÊmhŒåÆeW(d!Ë:‹¹Üå"Ò̲>·Ô7NâúµEíçø¬™ï9¸WA‹eÐЧö)IßqqÆ­ê¨Üëíņ~íȾ‹kXsšôm h [YEÿÊàpy:+Øc7Ã'›qÞu]mK®7à„Q¶Ÿ=m3Væ¯;¦Âº.¢[Ž’˜b¯ãÏ·"mô"\Š™ Žš0ã‹î¸á5òêgj-@6Uh¤¸Ýþjÿ]t=÷[äËLPóð™ôh2Ó4íq7ÇβN÷ì‹ÃMh<,K¶:²1·.%%•WI•—Ás%ÖÉÊM*žJ ¨ %‘㤺XÔþ{»Fj`&E¶e´ê0‰ ¬€ßO {ÄéaXÝØ|jëþ¶C(ŽÚÇ>ÎàL 2‡éeæsùaD8ÝHã¤æCx¹§.þþª:Í—@ÿK²¶bO™’•_êâly>²õh–e¤3÷ñÙZÌg© pK Æ;x7“²¤î¢l³qD”·jzQ!kkgØ¿ú»Ž5nCcYýLŶZî5Q¿D? lG‰ÅÐÁ<µgà„ªÀmv^ûÜ„éÚ g6 O'-~¹Ð§}ãèƒÖ«òˆ|ˆ95=ƒ{¾YQ_Úļ…#``“ÑS iŸAË£ßÞïG žâl6Èäß„~*:5x®¯eºGßS~Ëý¡Ç| )çTFrÛ+ÈÅ.h›øV©üõË—¼×àÔ ?È£GöP0"Ý·´¦è %ßÐ,£X­»¤ EœcF§çB0ŽaŒ@”’ð?\Sðàì×µÔ¼öQæ&nÛAÌ¥ds–zèkó8‹·B !Œ×ÝmQoÃάô¹È’lþʾeŽMfß‘8¾ iºx¦| †ƒëòë#(4Û¡gpý¬ëì1®Tfg½’P¬SuùºS$äÚ=Aü woÙÛ¾Œ¶Õ°1×<]èÇNC4BZJsâ¥ô}¡r?Ø]°îÄT:¯I×™ëÉ 0kt´‚B¡ÌÉu)ЇN†áÎùÀ€–N;¦[?.‡Ë×½œkÅÒ_]Ù<ÖЉ£×{B”StWG|; }ë«ù乜b‰õSå4?@%Àîwö¯63ìJ4¬„ŽêõCOqi)…iî;•ƒ‚bEÉxzEÃÌòÝòWˆw^åOŸkÅ ÏÞšŒØV¢új’/*˜d¡7¿$ÎJ]Ãô<Ú™ëTåþòy¨w—}XK$«gZÏ· âT 2àW>jmçÒ¼Clȸ{Å䥌Úf÷UæÈe¬^ìWî¾~I2‹ÌJ¼Âds^õHÙOþ‰ýy?:&Í_Îéã"ìEä“» „ÁGõTXÎnßã-¾é×7¯ ¦Û/|ã0<ħ!gË*ìoÈ'L«"²;ãÚ‘f³JlSëÖ j˜ª$ײ÷5ü>´wj«'äç%ÐZµñIÒÛ9MùÒß}¯$+³ŽÚC&}YõƒPj· ìGTrû¿8öÆ¢è9ûÑܾ½qÌjÀìWcOÇÆ :'eT‚Ík\UŠl‘³×e°!íØMÌ$LÔh«)î5E„LfwóÔœƒ>¡R·Ù(ƒþtóÔ×Ђ€ Ô?ÜH.zqTK3¦å½hFY#*…e9 †v•R¬_ý¨X õì»Hs­/2v(åÔÚy¼ê }Z¦ÙÂëšQ{dê}{Ëgý“qñ‚\ÍÌí(-b·{ɵ«Ûû©¼½;±ÐïCùð§´ŸH¥™6™óL ‹}>z; c‹zÞñ‰ì­š\“šÈÞq|³Þˆ1-›.Àä½oX•O}ÿÖNô¤èi~‹ž4üi9̋ӡ¿h%MÀe¦J§öÂ;‹*zìðãÕt‰Ëu,—cú' #ÙÃ]YÄtïÚ>âT#TÅåV³GJ³ÕÁ³õ¦P’»·±y”rat8Ÿf3o£G€ø€ºŸrz.sÿN~ ÛjPòÝvOòsƒcnô<º ö†³Ó®&´Õ¯ö³utcŽŒEâo¢Q'""žëù7ðLVŽÁ‘ áÅ*»#Ç6íVøË.twJÚÕ<öBCbÊH.r³^ßô\~U€ÆÍȵ–­¡»½pšéµ—(„e T$XuJÓ5ïoeõ^ŽGL>ÌoË\‘-Ù®¤7qp˜ô"òÙ zÜQý†bÏÁÞ”\Ý.ÆþˆI36†[/Û/Ä?¿ò2ˆÃ¯EÄN–´±®ˆÎŽTü*ǸtT 4Ô|Ыù-i÷pˆ›Ô©x œ´‚o†ot‚£·íOr `™8áLóÀ–Ðîó7_ËrV@¶ñ'êÒ'ÕÑ} ¥Ð²9æñ*µ!R¤Àäå;Ç#YH´áÆk:•úÒ…NüCû0}HIJ}´¸½ˆ$FßÏhƒ9"9IOPYÿ/XÂð–S‰å÷ÙEüµÜÅ^-‡¶ˆ:·öÝpÂF¦WÄFÜ i•¶À¢¦ÈñuG:ýoQpö€‰4òK¯´4Ý!A¢ŒA&Ê=A‘oîj¢“r·‚D(^F%¶(zQ+%1ÏžÒ³A|/“û¥õý|ùå A·[šjm†Î(û@fŽ kl*ݦaWE¢ý²¨þ¹9ÒjË&šbåOÑé»›™†Þõ&×\ðâås¥aûÉ×%?ü\¥÷[`caÃqo5û»2X\„ú$iL«1‡P¤Mïerа–î¼Xèî^Ô=×r/âߌcUùdô[YšÚG¿°sÚÀ:cöý@êÅ"ËA²Ñî„ßÈ6³¨>„Ñêɽõ8¼|^í÷ó:»?º/L‰ 5abf¥ÙZY‚ÞÆ^'ŠÀ†ÀXó*=°™¬„è«ÉVËŒ,öjÈeÄ;µ¤Â»Ví[/rF ¼Q³M‘ï95¤¬® àǤá.`Ô¿tÝ|^,וƒù³cO¹MõÙÈÓ]t£÷³pJ“ZŠx'ǃqÖš.ã™MÔ먈¦¤A‚kÉ[Ìi³ýd~ÏV9XÞ=*¶Ê8uKÖ¾æRè9¨~\ãxŽ„âÏa ¸#gnñ4̆±ÐF¸"a>W²‘XMÛ"集.4jŸRô}¢k»,µD„ã›>œœÊ@™äaký:_Ë•ØÂÎÕAJö¶¾ºfFbT/ž¢`Ÿ¤¦à­(\kù®W•.X>}>\(JѪã¡ÃäwtRùU—µYí¼LÇœÄ)¾yÇK'•LÄ—^Ÿ÷8k N óSŸ](‘V¤³Ø¬— k„6‹ÏDøègôDAá‹]bj’¶¼ ¿Á=TùZïûnœøÓ®7ôy;*ʶSžåÌwØ´•øÉ !§‡‹ÖKŽÙiÉ¢Ãu­°¹Œè²Î%LCX±ºjî½dvTžÍz‚¦ÐÅ#í g´ôÖY”’šAºš¯Fh>d9Îs2'•FZ¿r¶yÖŠ’ÄtMÞÜGŸS.³‹{ jp¢&ý"Ý¿ZG,3ÿ?ü üÿ þ?‘ÀÄhääbokädðá'úFendstream endobj 10 0 obj << /Type /Font /Subtype /Type1 /Encoding 41 0 R /FirstChar 11 /LastChar 122 /Widths 43 0 R /BaseFont /VPCRLB+CMR9 /FontDescriptor 8 0 R >> endobj 8 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /VPCRLB+CMR9 /ItalicAngle 0 /StemV 74 /XHeight 431 /FontBBox [-39 -250 1036 750] /Flags 4 /CharSet (/ff/fi/fl/ffi/exclam/quotedblright/quoteright/parenleft/parenright/plus/comma/hyphen/period/one/two/colon/A/B/C/D/E/F/G/H/I/L/M/N/O/Q/R/S/T/U/W/Y/quotedblleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) /FontFile 9 0 R >> endobj 43 0 obj [600 571 571 857 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 286 514 0 0 0 0 286 400 400 0 799 286 343 286 0 0 514 514 0 0 0 0 0 0 0 286 0 0 0 0 0 0 771 728 742 785 699 671 807 771 371 0 0 642 942 771 799 0 799 757 571 742 771 0 1056 0 771 0 0 514 0 0 0 0 514 571 457 571 457 314 514 571 286 314 542 286 857 571 514 571 542 402 405 400 571 542 742 542 542 457 ] endobj 44 0 obj << /Type /Encoding /Differences [ 0 /.notdef/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring/.notdef/breve/minus/.notdef/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde/.notdef/Euro/.notdef/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe/.notdef/.notdef/Ydieresis/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj 7 0 obj << /Type /Font /Subtype /Type1 /Encoding 44 0 R /BaseFont /Times-Bold >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /Encoding 44 0 R /BaseFont /Helvetica-Bold >> endobj 20 0 obj << /Type /Pages /Count 5 /Kids [2 0 R 22 0 R 28 0 R 31 0 R 34 0 R] >> endobj 45 0 obj << /Type /Catalog /Pages 20 0 R /PTEX.Fullbanner (This is pdfTeX, Version 3.141592-1.11a) >> endobj 46 0 obj << /Producer (pdfTeX-1.11a) /Creator (TeX) /CreationDate (D:20051108094821-05'00') >> endobj xref 0 47 0000000004 65535 f 0000004208 00000 n 0000004103 00000 n 0000000009 00000 n 0000000006 00000 f 0000060804 00000 n 0000000000 00000 f 0000060716 00000 n 0000058092 00000 n 0000045790 00000 n 0000057937 00000 n 0000045272 00000 n 0000038888 00000 n 0000045115 00000 n 0000036957 00000 n 0000033380 00000 n 0000036800 00000 n 0000031107 00000 n 0000023338 00000 n 0000030950 00000 n 0000060896 00000 n 0000009350 00000 n 0000009242 00000 n 0000004335 00000 n 0000022905 00000 n 0000018827 00000 n 0000022748 00000 n 0000012424 00000 n 0000012316 00000 n 0000009479 00000 n 0000014345 00000 n 0000014237 00000 n 0000012529 00000 n 0000017036 00000 n 0000016928 00000 n 0000014427 00000 n 0000017118 00000 n 0000023133 00000 n 0000031464 00000 n 0000031741 00000 n 0000037172 00000 n 0000037251 00000 n 0000045556 00000 n 0000058492 00000 n 0000058862 00000 n 0000060982 00000 n 0000061091 00000 n trailer << /Size 47 /Root 45 0 R /Info 46 0 R /ID [<3681BAA713A77A3C9F6EE37E14FA6C093C333638> <3681BAA713A77A3C9F6EE37E14FA6C093C333638>] >> startxref 61193 %%EOF cl-containers-20170403-git/doc/introduction-to-cl-containers.tex000066400000000000000000000373071306646076300245120ustar00rootroot00000000000000%% acknowledgments %% more text! %% hints and tips for the unwary %% lessons learned \documentclass{acm_proc_article-sp} \begin{document} \newcommand{\clcl} {{\bf{CL-Containers}}} \title{Common Lisp Container Library} \numberofauthors{1} \author{ \author{Gary King \\ \affaddr{metabang.com}\\ \affaddr{Pelham, MA 01002 }\\ \email{gwking@metabang.com}} } \date{} \maketitle \section{Abstract} Common Lisp ships with a set of powerful built in data structures including the venerable list, full featured arrays, and hash-tables. The Common Lisp Container Library (CL-Containers) enhances and builds on these structures in two ways: \begin{enumerate} \item By adding containers that are not available in native Lisp (for example: binary search trees, red-black trees, sparse arrays and so on). \item By standardizing the container interface so that they are simpler to use and so that changing design decisions becomes significantly easier. \end{enumerate} This document discusses the design motivations of \clcl~ and documents the structure and contents of the library in detail. \section{Warning} This document is quite old. I've started to update it but haven't finished yet. There are errors and omissions. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Motivation} A significant portion of almost any non-trivial programming effort goes into the manipulation of structured data. Many data structures can be viewed as containers. These may be ordered or unordered, associative (indexed) or sequential and so forth. The power and beauty of some programming languages derives in no small part from their ability to handle container classes well (Smalltalk comes to mind) and other languages have gone to great lengths to incorporate flexible containers into their frameworks (C++'s STL for example). Although Common Lisp includes a number of ``containers'' (hash-tables, lists and arrays) there are many useful data structures that are not built-in (e.g., binary search trees) and the existing containers have a fragmented interface that shows Lisp's peripatetic evolution. The Common Lisp Container Library (\clcl) extends Lisp in two ways: it adds new container functionality and, by standardizing container interfaces, it makes using them significantly easier. The standard interface also lends itself to more a flexible design and development process since data structure decisions are easier to change as the program evolves. \clcl~ thereby expends the power of Lisp and makes it an even better tool for both rapid prototyping \emph{and} production code. The remainder of this document will cover the container types available in \clcl, the methods applicable to these containers, information about the internal design of \clcl and examples of containers in use. As will become evident, \clcl's design borrows from the Standard Template Library, Smalltalk and existing Lisp idioms wherever possible. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Basic Container Kinds} The containers in \clcl~ can be divided into three basic types: Ordered, Unordered and Associative. The main examples of each type are given in table \ref{tbl:container-types}. The three container types can be distinguished as follows: Ordered containers store things in (some) order. The order may be based on how items were inserted into the container or it may depend on an explicit sorting. Unordered containers also store things and share much of Ordered containers interface. However, the items in an Unordered container do not maintain any particular arrangment. Finally, Associative containers store items {\emph {associated}} with some index or key. The key may be simple (for example, a one-dimensional array indexed by an integer) or complex (for example, a nested hash table indexed by color, size and object class). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{table*}[htb!] \centering \begin{tabular}{|lp{1.75 in}p{2.75 in}|} \hline Category & \vline \quad Container & \vline \quad Description \\ \hline \hline Unordered & & \\ & Bag-container & Unsorted collection of items \\ & Set-container & Unsorted collection of items ignoring duplicates \\ \hline Ordered & & \\ & list-container & Equivalent to a Lisp list \\ & stack-container & A standard Stack \\ & queue-container & A standard Queue \\ & priority-queue-container & A standard priority queue \\ & vector-container & An extendable one dimensional array (like STL's vector) \\ & binary-search-tree & A standard Binary Tree \\ & red-black-tree & A balanced binary tree \\ & ring-buffer & A standard ring-buffer (useful for fixed size queues) \\ \hline Associative & & \\ & alist-container & Equivalent to a Lisp assoc list \\ & array-container & Equivalent to a Lisp array \\ & associative-array-container & (not-implemented) \\ & associative-container & Equivalent to using nested Lisp hash-tables. \\ & simple-associative-container & Equivalent to a Lisp hash-table \\ & sparse-array-container & An array that only allocates space when necessary. \\ \hline \end{tabular} \label{tbl:container-types} \caption{\clcl~ main container types} \end{table*} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% examples %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Before describing the methods and implementation of \clcl~ in greater detail, a few examples should generate a better sense of how it fits into Lisp. FIrst, we use \clcl~ for a job that would often be accomplished using an associated list: linking one small group of things with another. \begin{small} \begin{verbatim} ;; a lookup table associating tokens with notes. (defvar *tokens->notes* (make-container 'alist-container)) (defun assign-note (token note) "Associate a token with a note." (setf (item-at *tokens->notes* token) note)) (defun clear-note-assignments () "Clear all associations." (empty! *tokens->notes*)) \end{verbatim} \end{small} The advantage of \clcl~ is that if we later learn that our association must handle dozens or hundreds of objects, we can switch to a more efficient hash table based association by making only one change to the code: \begin{small} \begin{verbatim} ;; a lookup table associating tokens with notes. ;; was 'alist-container (defvar *tokens->notes* (make-container 'simple-associative-container)) \end{verbatim} \end{small} A second example comes from a Hierarchical Agglomerative Clustering (HAC) application. At each step in the clustering, we merge the pair of items that ``goes together'' best. We store the candidate pairs in a priority queue ordered by their distance (closer items are more likely to result in a successful merge). Of course, there are many sorts of priority queues and the one to use will depend on actual items being clustered. \clcl~ lets us hide the queue implementation and defer the choice of implementation to the last possible moment: when we actual run the clustering algorithm. \begin{small} \begin{verbatim} ;; The priority-queue-on-container container ;; lets you specify which container type to use ;; in storing the items in the queue (as long ;; as it supports the necessary operations). (make-container 'priority-queue-on-container :key #'group-average-score :test #'(lambda (candidate1 candidate2) (compute-distance candidate1 candidate2)) :container-type 'binary-search-tree) \end{verbatim} \end{small} In general, a heap-based or \verb|binary-search-tree| based container may be the best to use for the priority-queue. However, if we believe that many of the items will have the same distance from one another, then a \verb|red-black-tree| may be the most appropriate because it will stay balanced. If too many of the same items are stored in a \verb|binary-search-tree|, then it will degenerate into essentially a list! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Container Mixins} Tables \ref{tbl:container-mixins} and \ref{tbl:more-container-mixins} list the main mixins used by \clcl~. A typical \emph{concrete} container (i.e., one that you would actually use in your application) will inherit from several of these mixins. For example, binary-search-tree inherits from sorted-container-mixin, findable-container-mixin and iteratable-container-mixin. As is generally true of CLOS class design, the mixin hierarchy provides generic implementation of common operations and helps to make clear the abilities of each specific container class. For example, the class hierarchy indicates that the binary-search-tree above sorts its contents, supports a fast find operation and can be iterated over. Effort has been made to split apart the various container operations in such a way that creating new containers is relatively easy. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{table*}[htb] \begin{center} \begin{tabular}{|lp{3 in}|} \hline Class & \vline \quad Description \\ \hline \hline abstract-container & Inherited by all container classes, this is a good place to put those pesky superclasses you need everyone to inherit. \\ typed-container-mixin & Elements have a specified (Lisp) type set a creation time. \\ bounded-container-mixin & Containers are created with a fixed size. Supports total-size. \\ indexed-container-mixin & Container elements can be accessed via an index. Supports item-at. \\ initial-element-mixin & Container supports initial-element and initial-element-fn. \\ initial-contents-mixin & Containers can be created with initial-contents (like a Lisp array). \\ iteratable-container-mixin & Elements of the container can be iterated over. Supports iterate-container. \\ searchable-container-mixin & The container can be searched (not necessarily quickly). Supports search-for-item and search-for-match. \\ findable-container-mixin & The container incorporates a pre-defined search function into its structure. The function must be specified at creation time. Supports find-item. \\ \hline \end{tabular} \end{center} \caption{\clcl~ container mixins} \label{tbl:container-mixins} \end{table*} \begin{table*}[htb] \begin{center} \begin{tabular}{|lp{3 in}|} \hline Class & \vline \quad Description \\ \hline \hline ordered-container-mixin & The elements in the container are ordered. Supports first-item, item-after, item-before, last-item, delete-first, delete-list, and insert-item. \\ sorted-container-mixin & The elements in the container are sorted by a sort function which must be specified at creation time. \\ keyed-container-mixin & The container has a key functin used to specify an accessor to its elements. Used by findable-container-mixin and sorted-container-mixin. \\ %% & \\ \hline %% Lisp Structure mixins & \\ \hline uses-contents-mixin & The elements in the container are stored in a slot named contents. This mixin and its three sub-classes (see below) abstract a group of common operations. \\ contents-as-array-mixin & The contents of the container are stored in a Lisp array. \\ contents-as-list-mixin & The contents of the container are stored in a Lisp list. \\ contents-as-hashtable-mixin & The contents of the container are stored in a Lisp hash table. \\ \hline \end{tabular} \end{center} \caption{More \clcl~ container mixins} \label{tbl:more-container-mixins} \end{table*} \begin{table*}[htb] \begin{center} \begin{tabular}{|lp{3 in}|} \hline Class & \vline \quad Description \\ \hline abstract-queue & The container supports the Queue interface. Supports enqueue and dequeue. \\ abstract-stack & The container supports the Stack interface. Supports pop-item and push-item. \\ \hline \end{tabular} \end{center} \caption{\clcl~ Generic Container Templates} \label{tbl:container-abstractions} \end{table*} \section{Basic Container Methods} Table \ref{tbl:method-types} is a list of many of the methods defined on containers. Many of these are not defined for all containers. For example, insert-item does not make any sense for associative containers. More information on exactly which methods are defined for which containers is included below. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{table*}[htb] \begin{center} \begin{tabular}{|l|p{4 in}|} \hline Method Name & Description \\ \hline \hline Generic Operations & \\ \hline make-container & create a new container \\ size & returns the number of items currently in the container \\ empty-p & returns {\bf t} if the container is empty \\ empty! & removes everything from the container \\ & \\ \hline Insertion and Deletion & \\ \hline insert-item & Adds a new item to a container. \\ delete-item & Removes an item from a container. \\ item-at & returns the item at a specified index (settable). This is only applicable for indexed-containers. \\ & \\ \hline Search and Iteration & \\ \hline iterate-container & calls a function on each item in a container \\ search-for-item & hunts for an item in a container (generally by iterating over all of the items. \\ find-item & finds an item in a container using the containers underlying structure (usually faster than search-for-item if the container supports it) \\ keys-of-container & Returns a list of all of the indexes of an associative container. \\ iterate-key-value & Similar to iterate-container, this method calls a function for each (key, value) pair in an associative container. It is analogous to maphash. \\ & \\ \hline Navigation & \\ \hline first-item & returns the first item in a container (settable) \\ last-item & returns the last item in a container (settable) \\ successor & Returns the item after the specified item in the container. \\ predecessor & Returns the item before the specified item in the container. \\ & \\ \hline Specialized Operations & \\ \hline total-size & returns the maximum number of items that a container can contains (only applicable for bounded-containers) \\ dequeue & synonym for delete-first (for queues) \\ enqueue & synonym for insert-item (for queues) \\ pop-item & synonym for delete-first (for stacks) \\ push-item & synonym for insert-item (for stacks) \\ \hline \end{tabular} \end{center} \label{tbl:method-types} \caption{\clcl~ Container methods} \end{table*} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Using \clcl~} \clcl~ must be loaded into your Lisp environment before it can be used. This is accomplished by loading the file containers.lisp. To use \clcl~ in your code, use make-container instead of the traditional Lisp methods (e.g., make-hash-table) then use methods like insert-item, search-for-item, empty! and so on as necessary. The methods you use will obviously depend on the purpose of your containers. You may find the additional examples including in the extras directory helpful as you get started. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Stuff that needs documentation} \clcl~includes some powerful and funky iterators constructs. \clcl~all container types and methods \clcl~installation \clcl~testing \section{Future Work} \clcl~ provides a useful set of data structure abstactions that enable faster prototyping and more flexible design. As always, more remains to be done. For \clcl~, this more falls into the following categories: additional container types, better integration with Lisp types and improvements to the existing containers. \clcl~ is missing some containers types (e.g., \verb|splay-tree|) In addition, some of the existing containers fail to implement (or implement poorly) operations that they ought. To ameiliorate these problems, we are investigating incorporating STL-like iterators into the design of \clcl. (This has been partly completed) \clcl fulfils most of its goal's admirably. It provides Lisp with useful and non-intrusive container support and it makes Lisp a better tool for both rapid prototyping and production development. \bibliographystyle{abbrv} \bibliography{\clcl~} \end{document}cl-containers-20170403-git/docs/000077500000000000000000000000001306646076300162415ustar00rootroot00000000000000cl-containers-20170403-git/docs/package.lisp000066400000000000000000000014701306646076300205270ustar00rootroot00000000000000(in-package #:common-lisp-user) (defpackage #:metabang.cl-containers.documentation (:use #:common-lisp #:cl-containers #:cl-markdown-user #:metabang.docudown) (:nicknames #:cl-containers-documentation) (:import-from #:metatilities #:deprecated #:defclass* #:defcondition #:ensure-list #:length-at-most-p #:length-at-least-p #:length-1-list-p #:maparray #:samep #:set-equal #:*samep-test* #:parent #:element #:argmax #:argmin #:best-item #:size #:root) (:import-from #:cl-containers #:basic-generator ))cl-containers-20170403-git/docs/setup.lisp000066400000000000000000000111631306646076300202740ustar00rootroot00000000000000(in-package #:cl-containers-documentation) (defmethod additional-markdown-extensions-for-system append ((system (eql (asdf:find-system 'lift-documentation)))) '(clcl)) (defsimple-extension clcl "*CL-Containers*") (defextension (list-classes :arguments ((root :required) (filter :required :whole))) (ecase phase (:parse ;; could syntax check here ) (:render (format *output-stream* "~s ~s" root filter)))) #| (mopu:subclasses 'cl-containers::basic-generator) (mopu:subclasses 'cl-containers::abstract-container) (mopu:subclasses 'cl-containers::concrete-container) (defun build-documentation-report (&optional (document (or *multi-document* (first *documents*)))) (cl-markdown::build-documentation-report (asdf:system-relative-pathname 'db.agraph.documentation "resources/documentation-report.md") (asdf:system-relative-pathname 'db.agraph.documentation "output/documentation-report.html") document (list :db.agraph :net.cluster :db.agraph.parser :db.agraph.serializer :db.agraph.sparql) :format :html :excluded-symbols (symbols-explicitly-undocumented-for-agraph) :docs-package (find-package :db.agraph) :search-locations (agraph-search-locations))) (defun build-summary-file (doc-root) (cl-markdown:markdown (let ((docs (sort (loop for info in *documents* when (typep info 'cons) collect (destructuring-bind (in out doc) info (list :in in :out out :doc doc :title (let ((cl-markdown:*current-document* doc)) (cl-markdown:document-property :title))))) #'string-lessp :key (lambda (plist) (getf plist :title))))) (db.agraph:string+ "{include resources/header.md} {set-property html yes} {set-property author \"Franz Incorporated\"} {set-property title \"Generated Documents | AllegroGraph {property agraph-version}\"} {set-property style-sheet styles}
# AllegroGraph Documentation " (apply #'db.agraph:string+ (loop for info in docs for index from 1 collect (db.agraph:string+ "* [" (getf info :title) "][" index "] "))) " " (apply #'db.agraph:string+ (loop for info in docs for index from 1 collect (db.agraph:string+ " [" index "]: " (enough-namestring (getf info :out) doc-root) " "))) "
{comment include resources/footer.md} " )) :format :html :stream (make-pathname :name "summary" :type "html" :defaults doc-root))) (defun agraph-search-locations () (list (asdf:system-relative-pathname 'db.agraph.documentation "") (asdf:system-relative-pathname 'db.agraph.documentation "resources/"))) (defun markdown-extensions-for-agraph () '(cl-markdown::docs cl-markdown::docs-index cl-markdown::glossary cl-markdown::links-list cl-markdown::comment cl-markdown::ifdef cl-markdown::abbrev cl-markdown-user:docs-group cl-markdown::ag-eval-freetext-stop-words cl-markdown::ag-eval-freetext-example-phrase cl-markdown::ag-eval-java-agraph-cfg-file)) (defun cl-markdown-for-agraph (filter in out &rest args &key &allow-other-keys) (remf args :root) (push (cons :|Content-Type| "text/html; charset=UTF-8") (getf args :properties)) (push (list filter t) (getf args :properties)) (push (cons :search-locations (agraph-search-locations)) (getf args :properties)) (let* ((md (apply #'markdown:markdown in :stream out :format :html :additional-extensions (markdown-extensions-for-agraph) args))) (push (list in out md) *documents*) md)) (defun cl-markdown-many-for-agraph (filter docs &rest args) (remf args :root) (push (cons :|Content-Type| "text/html; charset=UTF-8") (getf args :properties)) (push (list filter t) (getf args :properties)) (push (cons :search-locations (agraph-search-locations)) (getf args :properties)) (let ((*package* (find-package :cl-markdown))) (multiple-value-bind (main outputs) (apply #'markdown:markdown-many docs :format :html :additional-extensions (markdown-extensions-for-agraph) args) (loop for (in nil) in docs for (md dest) in outputs do (push (list in dest md) *documents*)) main))) (cl-markdown:add-documentation-strategy 'thing-names-property-p 'property 'property) (defun thing-names-property-p (thing) (and (symbolp thing) (db.agraph::ag-property-definition thing))) (defmethod cl-markdown:find-documentation (thing (strategy (eql :property))) (db.agraph::property-documentation (db.agraph::ag-property-definition (intern (symbol-name thing) :db.agraph)))) |#cl-containers-20170403-git/lift-standard.config000066400000000000000000000012541306646076300212360ustar00rootroot00000000000000;;; configuration for LIFT tests ;; settings (:if-dribble-exists :supersede) (:dribble "lift.dribble") (:print-length 10) (:print-level 5) (:print-test-case-names t) ;; suites to run (cl-containers-test) ;; report properties (:report-property :title "CL-Containers | Test results") (:report-property :relative-to cl-containers-test) (:report-property :style-sheet "test-style.css") (:report-property :if-exists :supersede) (:report-property :format :html) (:report-property :full-pathname "test-results/test-report.html") (:report-property :unique-name t) (:build-report) (:report-property :format :describe) (:report-property :full-pathname *standard-output*) (:build-report) cl-containers-20170403-git/tests/000077500000000000000000000000001306646076300164535ustar00rootroot00000000000000cl-containers-20170403-git/tests/dlist.lisp000066400000000000000000000003501306646076300204610ustar00rootroot00000000000000(in-package #:cl-containers-test) (deftestsuite test-dlist-container (cl-containers-test) ()) (addtest (test-dlist-container :documentation "case 207") test-size (ensure-same (size (make-container 'dlist-container)) 0)) cl-containers-20170403-git/tests/package.lisp000066400000000000000000000013141306646076300207360ustar00rootroot00000000000000(in-package #:common-lisp-user) (defpackage #:metabang.cl-containers.test (:use #:common-lisp #:cl-containers #:lift) (:nicknames #:cl-containers-test) (:import-from #:metatilities #:deprecated #:defclass* #:defcondition #:ensure-list #:length-at-most-p #:length-at-least-p #:length-1-list-p #:maparray #:samep #:set-equal #:*samep-test* #:parent #:element #:argmax #:argmin #:best-item #:size #:root))cl-containers-20170403-git/tests/priority-queues.lisp000066400000000000000000000015001306646076300225260ustar00rootroot00000000000000(in-package #:cl-containers-test) (deftestsuite test-priority-queue (cl-containers-test) ((q (make-instance 'priority-queue-on-container :sorter #'string< :test #'string=)))) (deftestsuite test-delete-priority-queue (test-priority-queue) () (:equality-test 'string=) (:setup (empty! q) (insert-item q "a") (insert-item q "b") (insert-item q "c"))) (addtest (test-delete-priority-queue) delete-first-1 (ensure-same (first-element q) "a") (delete-first q) (ensure-same (first-element q) "b") (delete-first q) (ensure-same (first-element q) "c")) (addtest (test-delete-priority-queue) delete-first-2 (dequeue q) (ensure-same (first-element q) "b") (dequeue q) (ensure-same (first-element q) "c") (dequeue q) (ensure (empty-p q))) cl-containers-20170403-git/tests/scratch.lisp000066400000000000000000000007431306646076300207770ustar00rootroot00000000000000(in-package #:cl-containers-test) #| (defvar *heap* (make-instance 'cl-containers:heap-container)) (cl-containers:insert-new-item *heap* 2) (cl-containers:insert-item *heap* 10) (defvar *heap* (make-instance 'binary-search-tree)) (cl-containers:insert-new-item *heap* 10) (cl-containers:insert-item *heap* 10) (let ((heap-node (make-node-for-container *heap* 10))) (compute-applicable-methods #'CL-CONTAINERS:INSERT-ITEM (list cl-containers-test::*heap* heap-node))) |# cl-containers-20170403-git/tests/test-containers.lisp000066400000000000000000000140311306646076300224650ustar00rootroot00000000000000(in-package #:cl-containers-test) (deftestsuite cl-containers-test () ()) #| ;;; --------------------------------------------------------------------------- ;;; out of range errors ;;; --------------------------------------------------------------------------- (lift:deftestsuite test-index-out-of-range (cl-containers-test) (container-class container) (:cases (container-class '(list-container vector-container))) (:setup (setf container (make-container container-class)))) (lift:addtest (test-index-out-of-range) (spy container)) (lift:addtest (test-index-out-of-range) (spy container-class) (insert-item container 1) (insert-item container 2) (insert-item container 3) (insert-item container 4) (lift:ensure-same (nth-element container 0) 1 :test #'=) (lift:ensure-same (nth-element container 2) 3 :test #'=) #+Ignore (lift:ensure-error (nth-element container 10)) #+Ignore (lift:ensure-error (nth-element container -1))) ;;; --------------------------------------------------------------------------- ;;; list-containers ;;; --------------------------------------------------------------------------- (lift:deftestsuite test-initial-contents () (container-class) (:cases (container-class (concrete-subclass-names-of 'initial-contents-mixin))) (:timeout 1)) (lift:addtest (test-initial-contents) (spy container-class)) (lift:addtest (test-initial-contents) (spy container-class) (lift:ensure-same (collect-elements (make-container container-class :initial-contents '(2 3 4))) '(2 3 4))) ;;; --------------------------------------------------------------------------- ;;; test-binary-search-tree ;;; --------------------------------------------------------------------------- (lift:deftestsuite test-binary-search-tree () (b)) (lift:addtest (test-binary-search-tree) (setf b (make-container 'binary-search-tree :key #'first :test #'equal)) (insert-list b '((2) (3) (10) (1) (4))) (lift:ensure-same (size b) 5) (lift:ensure-same (first (first-element b)) 1) (lift:ensure-same (element (search-for-node b 1 :key #'first)) (first-item b)) (delete-item b '(2)) (lift:ensure-same (size b) 4) (insert-item b '(7)) (insert-item b '(-2)) (insert-item b '(12)) (lift:ensure-same (size b) 7) (empty! b) (lift:ensure-same (size b) 0)) ;;; --------------------------------------------------------------------------- ;;; Utilities ;;; --------------------------------------------------------------------------- (defun concrete-subclass-names-of (class-name) (let ((result nil)) (mopu:map-subclasses class-name (lambda (subclass) (when (member 'concrete-container (mopu:mopu-class-direct-superclasses subclass) :key #'class-name) (push (class-name subclass) result)))) (nreverse result))) ;;; --------------------------------------------------------------------------- ;;; move eventually ;;; --------------------------------------------------------------------------- ;;; --------------------------------------------------------------------------- ;;; sorted-list-container ;;; --------------------------------------------------------------------------- (lift:deftestsuite test-sorted-list-container (cl-containers-test) ((c (make-container 'sorted-list-container)))) (lift:addtest (test-sorted-list-container) stays-sorted (insert-list c '(4 2 3)) (lift:ensure (eq (first-item c) 2)) (insert-item c 23) (lift:ensure (eq (item-at c 3) 23))) ;;; --------------------------------------------------------------------------- ;;; collect-keys ;;; --------------------------------------------------------------------------- (lift:deftestsuite test-collect-keys (cl-containers-test) ()) (lift:addtest (test-collect-keys) associative-container (let ((c (make-container 'associative-container))) (loop for (k v) in '((a 2) (b 3) (g 23)) do (setf (item-at c k) v)) (lift:ensure-same '(a b g) (collect-keys c) :test u:set-equal)))) ;;; --------------------------------------------------------------------------- (lift:addtest (test-collect-keys) alist-container (let ((c (make-container 'alist-container))) (loop for (k v) in '((a 2) (b 3) (g 23)) do (setf (item-at c k) v)) (lift:ensure-same '(a b g) (collect-keys c) :test u:set-equal))) ;;; --------------------------------------------------------------------------- ;;; associative-containers ;;; --------------------------------------------------------------------------- (lift:deftestsuite test-associative-containers (cl-containers-test) ()) ;;; --------------------------------------------------------------------------- (lift:addtest (test-associative-containers) test-alist-string-equal (let ((a (make-container 'alist-container :test #'string-equal))) (setf (item-at a "Hi") "Bye") (setf (item-at a "Hi") "Hello") (lift:ensure-same (item-at a "Hi") "Hello" :test string-equal))) #+Ignore ;; how is the test supposed to be applied in any case? (lift:addtest (test-associative-containers) test-alist-string-equal-2 (let ((a (make-container 'alist-container :test #'string-equal))) (setf (item-at a "Hi" "1") "Bye") (setf (item-at a "Hi" "1") "Bye Bye") (setf (item-at a "Hi" "2") "Hello") (setf (item-at a "Hi" "2") "Hello there") (lift:ensure-same (item-at a "Hi" "1") "Bye Bye" :test string-equal) (lift:ensure-same (item-at a "Hi" "2") "Hello there" :test string-equal))) (lift:addtest (test-associative-containers) looking-does-not-add (let ((c (make-container 'alist-container))) (item-at c :hello) (item-at c :bye) (lift:ensure (null (contents c))))) |# (deftestsuite test-priority-queue-on-container (cl-containers-test) ()) (addtest (test-priority-queue-on-container) add-and-delete (let ((c (make-container 'priority-queue-on-container))) (insert-item c 2) (insert-item c 1) (insert-item c 3) (delete-element c 2) (ensure-same (size c) 2 :test '=) (ensure-same (first-element c) 1))) cl-containers-20170403-git/tests/test-file-iterators.lisp000066400000000000000000000114731306646076300232600ustar00rootroot00000000000000#| (let ((i (make-iterator #P"Billy-Pilgrim:Users:gwking:repository:p2dis:lsa:dev:data:titles-1.data" ))) (collect-elements i)) (let ((i (make-iterator #P"Billy-Pilgrim:Users:gwking:repository:p2dis:lsa:dev:data:titles-1.data" :treat-contents-as :file-lines))) (collect-elements i)) (let ((i (make-iterator "Billy-Pilgrim:Users:gwking:repository:p2dis:lsa:dev:data:titles-1.data" :treat-contents-as :file-lines :transform (lambda (line) (make-iterator line :treat-contents-as :words))))) (iterate-elements i (lambda (e) (iterate-elements e #'print)))) (let ((i (make-iterator "Billy-Pilgrim:Users:gwking:repository:p2dis:lsa:dev:data:titles-1.data" :treat-contents-as :file-lines :transform (lambda (line) (make-iterator line))))) (iterate-elements i (lambda (e) (iterate-elements e #'print)))) (let ((i (make-instance 'file-line-iterator :filename "Billy-Pilgrim:Users:gwking:repository:p2dis:lsa:dev:data:titles-1.data"))) (iterate-forward i (lambda (e) (format t "~%L: ~A" e)))) (let ((i (make-iterator "attractors for semigroups and evolution equations"))) (iterate-forward i #'print)) (let ((i (make-iterator "attractors for semigroups and evolution equations" :treat-contents-as :words))) (iterate-forward i #'print)) |# #| Necessary?? (let ((i (make-iterator "hello"))) (collect-elements i)) ;;; --------------------------------------------------------------------------- ;;; character iterator ;;; ;;; UNICODE!!! ;;; --------------------------------------------------------------------------- (defclass* character-iterator (forward-iterator) ((cache (make-array 20 :element-type 'character :fill-pointer 0 :adjustable t) r) (current-word nil r) (internal-iterator nil r))) ;;; --------------------------------------------------------------------------- (defmethod initialize-instance :after ((object character-iterator) &key container) (setf (slot-value object 'internal-iterator) (make-iterator container)) (when (move-forward-p (internal-iterator object)) (move-forward (internal-iterator object))) (advance object)) ;;; --------------------------------------------------------------------------- (defmethod move ((iterator character-iterator) (direction (eql :forward))) (advance iterator)) ;;; --------------------------------------------------------------------------- (defmethod advance ((iterator character-iterator)) (let ((internal (internal-iterator iterator))) (setf (fill-pointer (cache iterator)) 0) (loop while (move-forward-p internal) do (when (delimiter-p iterator (current-element internal)) (loop while (and (move-forward-p internal) (delimiter-p iterator (current-element internal))) do (move-forward internal)) (return)) (vector-push-extend (current-element internal) (cache iterator)) (move-forward internal)) (setf (slot-value iterator 'current-word) (coerce (cache iterator) 'string)))) ;;; --------------------------------------------------------------------------- (defmethod current-element ((iterator character-iterator)) (current-word iterator)) ;;; --------------------------------------------------------------------------- (defmethod current-element-p ((iterator character-iterator)) (and (call-next-method) (plusp (fill-pointer (cache iterator))))) ;;; --------------------------------------------------------------------------- (defmethod move-p ((iterator character-iterator) (direction (eql :forward))) (or (move-p (internal-iterator iterator) direction) (plusp (size (cache iterator))))) ;;; --------------------------------------------------------------------------- (defmethod class-for-contents-as ((contents string) (as (eql :words))) 'character-iterator) |# #| (setf i (let ((i (make-instance 'word-iterator :container "attractors and blood" #+Ignore "Billy-Pilgrim:Users:gwking:repository:p2dis:lsa:dev:data:titles-1.data"))) (iterate-forward i (lambda (e) (format t "~%L: ~A" e))) i)) (setf i (let ((i (make-iterator "hello"))) (iterate-forward i (lambda (e) (format t "~%L: ~A" e))) i)) (setf i (make-instance 'word-iterator :container "attractors for semigroups and evolution equations")) (current-element-p i) (move-forward-p i) (Move-forward i) (element i) (setf i (make-iterator "attractors and blood" :treat-contents-as :words)) (iterate-elements i #'print) (collect-elements (make-iterator "attractors and blood" :treat-contents-as :words)) |#cl-containers-20170403-git/tests/test-iterators.lisp000066400000000000000000000054611306646076300223430ustar00rootroot00000000000000(in-package #:containers) (collect-elements (make-iterator '(1 2 3 4 5) :filter #'oddp)) ;;; --------------------------------------------------------------------------- (lift:deftestsuite test-iterators () ()) (lift:addtest (test-iterators) collecting-nil (lift:ensure-same nil (collect-elements (make-iterator nil :filter #'oddp)))) (lift:addtest (test-iterators) collecting-one-even (lift:ensure-same nil (collect-elements (make-iterator '(2) :filter #'oddp)))) (lift:addtest (test-iterators) collecting-odd-even (lift:ensure-same '(3) (collect-elements (make-iterator '(3 2) :filter #'oddp)))) (lift:addtest (test-iterators) collecting-even-odd (lift:ensure-same '(3) (collect-elements (make-iterator '(2 3) :filter #'oddp)))) (lift:addtest (test-iterators) collecting-list (lift:ensure-same '(3 1 3) (collect-elements (make-iterator '(3 2 4 1 3 2) :filter #'oddp)))) (lift:addtest (test-iterators) collecting-list (lift:ensure-same '(3 1) (collect-elements (make-iterator '(3 2 4 1 3 2) :filter #'oddp :unique t)))) (lift:deftestsuite test-iterators () ()) (lift:addtest (test-iterators) collecting-nil (lift:ensure-same nil (collect-elements (make-iterator #() :filter #'oddp)))) (lift:addtest (test-iterators) collecting-one-even (lift:ensure-same nil (collect-elements (make-iterator #(2) :filter #'oddp)))) (lift:addtest (test-iterators) collecting-odd-even (lift:ensure-same '(3) (collect-elements (make-iterator #(3 2) :filter #'oddp)))) (lift:addtest (test-iterators) collecting-even-odd (lift:ensure-same '(3) (collect-elements (make-iterator #(2 3) :filter #'oddp)))) (lift:addtest (test-iterators) collecting-list (lift:ensure-same '(3 1) (collect-elements (make-iterator #(3 2 4 1 3 2) :filter #'oddp :unique t)))) #| (setf i (make-iterator '( 4 1 3 5) :filter #'evenp)) (current-element i) (move-forward-p i) (move-forward i) (current-element-p i) (collect-elements (make-iterator #2A((3 2 4) (1 3 2)) :filter #'oddp :unique t :transform #'u::square)) (collect-elements (make-iterator #(3 2 4 1 3 2) :filter #'oddp :unique t :transform #'u::square)) |# #| (bind ((c (make-container 'list-container :initial-contents '(1 2 3))) (i (make-iterator c))) (print (next-element i)) (print (next-element i)) (print (next-element i)) (reset i) (print (next-element i)) (print (next-element i)) (print (next-element i)) (values)) |#cl-containers-20170403-git/tests/test-queue-delete.lisp000066400000000000000000000024561306646076300227140ustar00rootroot00000000000000(in-package #:ccl) (use-package "LIFT") (deftestsuite test-queue () ((q (make-instance 'basic-queue)))) (defmethod collect-elements ((container basic-queue)) (let ((result nil)) (iterate-container container (lambda (x) (push x result))) (nreverse result))) (deftestsuite test-delete-queue (test-queue) () (:setup (insert-item q :a) (insert-item q :b) (insert-item q :c))) (addtest (test-delete-queue) delete-1 (delete-item q :a) (ensure-same (collect-elements q) '(:b :c) :test #'equal)) (addtest (test-delete-queue) delete-2 (delete-item q :b) (ensure-same (collect-elements q) '(:a :c) :test #'equal)) (addtest (test-delete-queue) delete-3 (delete-item q :c) (ensure-same (collect-elements q) '(:a :b) :test #'equal)) (addtest (test-delete-queue) delete-1-insert-1 (delete-item q :a) (insert-item q :a) (ensure-same (collect-elements q) '(:b :c :a) :test #'equal)) (addtest (test-delete-queue) delete-2-insert-2 (delete-item q :b) (insert-item q :b) (ensure-same (collect-elements q) '(:a :c :b) :test #'equal)) (addtest (test-delete-queue) delete-3-insert-3 (delete-item q :c) (insert-item q :c) (ensure-same (collect-elements q) '(:a :b :c) :test #'equal)) #+Ignore (addtest (test-delete-queue) delete-3-insert-3 (inspect q)) cl-containers-20170403-git/tests/test-queues.lisp000066400000000000000000000011341306646076300216270ustar00rootroot00000000000000 (in-package #:containers) (lift:deftestsuite test-queues (test-containers) ()) (lift:deftestsuite test-single-queue (test-queues) (q) (:cases (q (mapcar #'make-container (concrete-subclass-names-of 'abstract-queue))))) #+Ignore (lift:addtest (test-single-queue) test-ok (spy q)) (lift:addtest (test-single-queue) test-add-and-empty (insert-item q 2) (insert-item q 45) (lift:ensure-same (size q) 2) (empty! q) (lift:ensure (empty-p q))) #+Test (concrete-subclass-names-of 'abstract-queue) #+Test (mapcar #'make-container (concrete-subclass-names-of 'abstract-queue)) cl-containers-20170403-git/tests/test-reverse-container.lisp000066400000000000000000000003771306646076300237630ustar00rootroot00000000000000(in-package #:cl-containers-test) ;; WIP (deftestsuite test-reverse-container () ()) (addtest (test-reverse-container) test-list-container (let ((c (make-container 'list-container :initial-contents '(1 2 3 4)))) (iterate-elements c #'print)))cl-containers-20170403-git/tests/test-set-container.lisp000066400000000000000000000004561306646076300231010ustar00rootroot00000000000000(in-package #:u) (deftestsuite test-set-container () ((c (make-container 'set-container :initial-contents '(1 2 3 3 3 4))))) (addtest (test-set-container) (ensure-same (size c) 6)) (addtest (test-set-container) (ensure-same (count-elements c 3) 3) (ensure-same (count-elements c 1) 1)) cl-containers-20170403-git/tests/test-vectors.lisp000066400000000000000000000006121306646076300220050ustar00rootroot00000000000000 (in-package #:containers) (lift:deftestsuite test-vectors (test-containers) ()) (lift:deftestsuite test-initial-contents-mixin () ()) (lift:deftestsuite test-vector-containers () ()) (lift:addtest (test-vector-containers) test-initial-contents (lift:ensure-same (collect-elements (make-container 'vector-container :initial-contents '(2 3 4))) '(2 3 4))) cl-containers-20170403-git/tests/trees.lisp000066400000000000000000000066721306646076300205010ustar00rootroot00000000000000(in-package #:cl-containers-test) (deftestsuite test-trees (cl-containers-test) ()) (addtest (test-trees) insert-delete-consistency (ensure-cases (class) '(binary-search-tree red-black-tree) (let ((c (make-instance class))) (insert-item c 31) (ensure-same (size c) 1 :test '=) (delete-item c 31) (ensure-same (size c) 0 :test '=) ))) (addtest (test-trees) searching-and-deleting-keyed (ensure-cases (class) '(binary-search-tree red-black-tree) (let ((b (make-container class :key #'first :test #'equal))) (insert-list b '((2) (3) (10) (1) (4))) (ensure-same (size b) 5) (ensure-same (first (first-item b)) 1) (ensure-same (search-for-node b 1 :key #'first) (containers::first-node b)) (delete-item b '(2)) (ensure-same (size b) 4) (insert-item b '(7)) (insert-item b '(-2)) (insert-item b '(12)) (ensure-same (size b) 7) (empty! b) (ensure-same (size b) 0) ))) (addtest (test-trees) find-on-nonexistant-item (ensure-cases (class) '(binary-search-tree red-black-tree) (let ((c (make-instance class))) (ensure-null (item-at c 1)) (ensure-null (find-element c 1)) (ensure-null (find-item c 1)) (ensure-null (find-node c 1)) ))) (addtest (test-trees) find-on-nonexistant-item-nonempty (ensure-cases (class) '(binary-search-tree red-black-tree) (let ((c (make-instance class))) (insert-list c '(64 83 68 84 97)) (ensure-null (item-at c 1)) (ensure-null (find-element c 1)) (ensure-null (find-item c 1)) (ensure-null (find-node c 1)) ))) (addtest (test-trees) randomized-testing (ensure-cases (class) '(binary-search-tree red-black-tree) (let* ((count 20) (randlist (loop repeat count collect (random 100))) (c (make-container class ))) (loop for n in randlist do (insert-item c n)) (ensure-same (size c) count) (ensure-same (first-element c) (apply #'min randlist)) (ensure-same (last-element c) (apply #'max randlist)) (loop for n in randlist do (ensure (item-at c n)) do (ensure (find-item c n))) (ensure-same (collect-elements c) (sort (copy-list randlist) #'<) :test #'equal) ;;now remove half the elements and make sure it still makes sense. (loop repeat (/ count 2) for n = (pop randlist) do (ensure (typep (delete-element c n) 'containers::bst-node))) (ensure-same (size c) (length randlist)) (ensure-same (first-element c) (apply #'min randlist)) (ensure-same (last-element c) (apply #'max randlist)) (loop for n in randlist do (ensure (item-at c n)) do (ensure (find-item c n))) (ensure-same (collect-elements c) (sort (copy-list randlist) #'<) :test #'equal) ;;remove the rest (ensure-null (empty! c)) (ensure (empty-p c)) (ensure-same (size c) 0) (ensure-null (collect-elements c))))) #| (setf c (make-instance 'red-black-tree)) (insert-item c 1) (delete-item c 2) (size c) c (collect-nodes c) (collect-elements c) (delete-item c 1) (trace delete-item) (trace delete-node) (trace) (delete-element c 1) (find-element c 1) (compute-applicable-methods #'size (list c)) (compute-applicable-methods #'collect-nodes (list c)) (compute-applicable-methods #'iterate-nodes (list c #'identity)) (compute-applicable-methods #'delete-item (list c 1)) |#cl-containers-20170403-git/website/000077500000000000000000000000001306646076300167535ustar00rootroot00000000000000cl-containers-20170403-git/website/source/000077500000000000000000000000001306646076300202535ustar00rootroot00000000000000cl-containers-20170403-git/website/source/images/000077500000000000000000000000001306646076300215205ustar00rootroot00000000000000cl-containers-20170403-git/website/source/images/containers.pdf000066400000000000000000000633361306646076300243730ustar00rootroot00000000000000%PDF-1.3 %Äåòåë§ó ÐÄÆ 2 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xÚ­}Év9²å_Ë× Fa¶]§{ÿNå²7Tˆ•É®¤”)JÕ•ßvÍ0˜GÉ SU'Ew wŽÁ`Ã5߇ÿ>üyøÛߟÝáô|°ôwx>\ñþ˜s.‡”,.r;÷'ýs !ÄâQ™9´c-Õô“.o Ãí¨Ñœ:!‡có.9]D‰—•MÚi5kQjþ*ñʇž¿þIýà¤/þ<8”ÏUp;CÍ/Çx8=þç/×’?¿<þö¿Ý½úË?ÿõüÇï÷Ý}ÿöðð?¿üßÃÿú…z}oþþ~Üþñ÷—ë;H¯åœÔÕZñ--ýÏ›~_é>ÕZÕå#u8}i‘'…zWšv:”àŽ±DçÕäVÆ“³ÛÆÈlÆèë·ïŸïN_¿|¿üòðGj½Ñh–Ô”b‘Ñý¯»§Çÿ<~™ÃiæòÁqÍéШžÔ}ÅÔŒÉÕƒ÷•*n¥гÞGן »“ñÞºcÊÍɯNæùæýIC'}ïÓѧH+e–bZȪÜT ø×Õæõþæ;xm˜·×5…Ö^³©wþk‹ÃHÇÿöpÿÇY·óy×z0X‘æ0q“§Ck +¼Ïr=¸D,#¥zdRÈ™Eôr“<ÀVªÉ–^È…jÊ®OÛÓaL°Þ¦ØyûÜ­žŒ¢ÒªM‹Ö]ú=Y?6¥–ÇÎ0i4H͹cM9/ª¡ìy‰Š¦÷ÏE¥]°Ê*qnµ¥©VNªúšYâ•ï6·nˆÝ26þ«ÌÖœoˆ2Îf³Ý –~³£¡¦ÅM¬«?ÚCð²ÀhazÔEjVGˆ¡™PÂåò·4%-j™¢K é˜mI‡’G¿­7i\»¥—šWTçãe‰‹Ö”D4©ÕN!f–XÝ‹fÝ‹vZ­4êÉù5ªÄ+ßýò,0ç«æc©7ID|{üúíñû_wþxøñp÷õ‹šf×jçià1‘1T5&쀦Ҋ÷´ÃÕfE  R˜µ¦C¨µ³÷F’R,…§Yìh×+²dºÌc­3©ØË‰²CTeR­›…„˜]9Ä9¬k°¢ênH6¥Ùì•8iÔ…ñí`#¿öQD õbf,ÚI5kRjþ*ñʇÞ.0ëzÕ¶Þ2=>=~¹ÿö×ÝóÃý·ÓoZp6{fE¨9Ç¤íŽÆ³Âó—>+< ­âôAÖ )ál{’–‹±B¼êµY>#šwØ…Ñk>ªMo±Ђ+¤Œôß©Y˜fx¼a4ê9m"¡„d´¶)‡å‚UOa±p´Ã0A·}qö=·h-¡ïì1ö±½a\ÿõð±ýO÷¿þíùáûOYòÎÒî^y‡—ËXa¡&ÚD<¯’(XéQgiSÀ5­úà,õî[vë%¹«v¾jžõlÖ; C€ÂpAã2k‘ЄñÖjúµÏ#ó†âBk%õž…BöJÏnÔ—§û/Ý~{üýóÝ—¯Ÿ> 2¹@ë…fÕa\ÆŒÎ"eÏ'â‹…È´!¾ > ™GÓ–ú„pôîxÉÈ]Êü.s³ÞZŠ):oOºÎA5ÒªUÎhïèäWú6åÎĈŸƒ™·&,wë/_¿}~øíðõ67NÙD,HKü¦Æ€±&Ź¡[z ˜ÓßòRáà^}=ðåZ¾Ñ’m¤>òz@OËzpÞÒ6c«¬êRµŠú-Oa¹œKb½Æ3åõ%1+â¸kIŒö]­sy"•·Áåh]«ŸÃ^œ-¸¤) ¢bÐH¾”oÙn©eÑ+]­ÚPiÚR“ñ)‘Oó›h©3TôJgÉ“FeFÒUktA?ZíÓy•¨h³ç6O’L‘ÐhUbÛ³ª{Ð ¾g¶r=©¾f–xå»ÕŽb^7Ddž©®ë¼>Ú†7“»O¤?ü4ûËÕIó—U ÆOÛdã¥ï„.™ú6ìÑÞŠÍ—6†5L7¤’ˆI‚S7¡< B´&ÖðiCÉ$gzZ.½ËóRÔ;M¡ÁiOúÉ4†S•¨h£ÚÓ¢jn>Ê’V%–rY÷ 6­œOÒ‡è¶z»Ê /µ^Œ æ†Å}“¶hn2œŠ(åIm}[“½®ºvô$&V›ë¦¡µ/-ÚéP|=ç‹SÔÜü|²8IužÔ#ÉÕÎWQ$w«ê‹¨³I|?ÛlÖûÛïR2Ç›ÆRRšsâÿ cñBÈ_>ßúýáEƒ©ƒù±$o®ÚKwpbb¿¦…28q#Õ¤oQ6£"mD®uÙÌáû[ñÂîñî|‰KÂ'¡Ó<”>Tï¤.5ââ¤kÁÜ„ñ–‘ÛPn‘A|RúTéW›gÿ§çïßîO߯ÏXN™Èú2ÀÈšÑÒz¡¥)w¡C1·iuKÜ0±Öܘùµ@º“C—8¢Ò5‰8§í™ºìû®’mVê²êa›¶0ìX6‘BŸª¿Ô`'T_Òæ™8ÉæIW.K´U÷IS]·…©Á)Ïë^´“j¥zr~*qÑTÝ·²Jy¯ÖÌ« óÏ÷ŸÏM/+q/êË–øVž;`-õë`Fà1“lG]ÅžnwK«Õƒ›…U1ÜD´Z¬LGLÀ¸lð óaNO,Ä”m“ÕNoˆ•/ò0-êa^ûÊÌ‚–>-Ùê,ìïÞ Sà+¬wtµÕNhaŒæÛšÆêÒ$Íà ~SNÊ£ Q›Fíý'iÛxq6Û¼ƒß;Ÿ±§ë²–¹2¯Àm¾|¾»¾ûíþù·ïÌûoåé/Î4âƒÿÔÎhHcÛrÖÆí!¯'µ‰{0a¸6áÔ톪b·ü<œ’š÷îðÆ´|±]±‹cZR=±Å¾»×B+ Å#c)àŽÔƒ1ÏÉi鎹!=íÙ¢@wÑÙ^ ì щ¡Ñ mqÚ-×,S8KÞ-‰rQILëb¥ÇD|gIòF‰vSºg{zK{»7LmÑBïjšÃ>  ¾³óY|“ÙpAvUsȽYã­ÙÞ×ö€³ñ1ȶq“ueŠ ?Ãn[zÒlÏ-˜»u… ök0vì†&¸õ [©±ÃÛ±#&7À-¢TSiF°Ñb–uÈ ô/7Ø9|ðœžXÐ¥HºX‚fF݆¿ûóBËøa\dzÀ’vŠí¶ZRèÙhm}‹¡ÁUõZ¿‹l^ãKZ‰z£ß¢]JÊãmQ×DiFmµo*,æEÃLž¤æo2õ³uæÓýóãéîñËã÷Çûßï¦üð~5pëém¼¤< iu<"χ4o1• –Åu; ‰Ô(ÓÉ;îšxØ1ÆP’¤±Ê ¹´^+ˆ¦Î»°M\0ì~î¿P‡®×ŒÜ1ØF.©·y°Ô[͹<\œtM H3úkf¶ïm¥Ô“ì̸< _>?ü礔³öXH*Ê×Rf/«,‡V– H§²"‚(’““Q/¹ï…ì5ƒM±Ê¯ 5M~õ ŽkÃìÓ]BíÖ‰Uh­3}K›Í:æãN{:p ô-®êøÝÙõ»a4-bakBª2Et9¹lêaÀÎl‡a‚nû(âì{Þœ4¦QgÓf5ĺœþ÷§Ýÿúp±E›}~ޱܡ~“ø!+ùlRáž²2ÊÔY¸ËcFìZé æƒÄÐ2¹,bF"]4“È[Jˆ«rq"• kóQîcl]Q^ïNš}ÚZ–AYÅd›¤|\œVÍF~áf·f{ß^ùÙ¦É+ÿMgØç‡çÛ8¹¹Í †Yήç`жÏP”Áµ»Æß—wJi &³Dïêƒäjg7Ý+vÑÝ>5 ^]]‘’…`ˆqc$aqÌ$>çÈL½û DŸ·p:û£gŽ<‰°‘BŒÜŒ*NýGÏÔÛËÿÀ5ÌÛÓj†ÑqËG1gòöw‰8°Ò7¬ñ±á?üþðDÓdͳSNôƒùŒdŸ ¦ðÀ5^Çl‡ÞŸcŸŽ¥(ëÕÜNŒ¦ ü¬-È´1¼{v›ŒguÞáØiOÚ·‹Æ»nê[KƒQEœlżóÛfZ eàTÀÔ Kn k{,z0zŸ„Ûè넬Ž­@òQ÷•UÚ›V!-KÙeáQ'ßs{Æ+³o»lÊX}½Íc»U%Ö£p8Ú–&ÚšY|¹Ï6: ¥M ,ªîŠ¡¯Œ]¦<]įG뎤l aö§™Cžàø¼wG¡•È€ ˜×Õ3GAî³ '–ÀÙØØ¬·ý§Ö%^ØÇË“&…Ÿ4Z~76Îrð‰R¬é•§6~BÓæ‹«Õ·°Ž:Båü£+ù‘ÒEZ1 ÀU%_¡ôÝ®gnÌU¯“y·7Øë ,aÁékçö”5‹ò)f$‘L#XH|0sx=CÀ#±¹ÌN|†¤±ƒ¶3–¾÷{¶.Rá0(2Kd˧ç³MžJV¬‚þ2ÄÒÝ'/Dü(†ƒÚm‘$BY†;ºà0Q1æ}êó¡ež6•E=“»Õa¨Z-žŒ\ö°VR!t­MÔWÆaB±­1çÜõ9VþÇkrר‰Ë$#^¿•\W¯”ª nÆ|î ·ïU ]ÑZ¸™% Æ×}¥@íGZ‡Óvç®9g'>–%–a(1<_œ˜_23{tÃ~˜Ø$;eùJÜ«Ä+éƒZA'F‰ÀY3¥ÏôîÁMÇ+†o؃ÊWݵªß åÏ%±;VÕ@÷\yÅŒ6Ý¢öŠþÂve^6ÁÅöSL,ßÈnÄ¡@À¶ÝÒt#N½q5¨y¾qhw¢¯÷;¦ Tk©vz:ør"Í¢ZY/^6ŒÀºƒå¹‹¤‡,ª+nÂ7³†S¿o¼îüzà·U…Yw'ÝŒI•vR¶_ñ¶˜â“ëcîl´·lK_¾~¹»~þzz¼ÿþøï‡»—äÃ1‘ºÙ»a[{+³-Öüè®B2HE–ç±È&Zo9ö„T™?àŸY‚Ñ4YƒŠG¿­b0»T-ÕJ” ·¢ù]µ|–°ýšwdêqõ*ÎþåÈãû_¯.\óþp…zá =ÖÀ¹ÌaÄŠž—ðø2qŒh{Ú\œƒFZ0‡Ò٨и•1 Ôi€:ÆþáŸõ²Üú*C…ë(¡ÀF¿˜6“AìKª^ü¬ZݥظÔps,ÐÀÑ{gû®y¯ùðýç ýHTd¦õ$Û%¹R.œgh¹;*Cߊ¸ÖÒmuB©퀣OÅê(×¹£}Ê{¯å%½žômð®Uâ¢Íj‘VcQ]GA«ÑqÛºí¤[9¨¦Ù,lû¡ïˆ ‚D[Ú;Ðíèê7Øb£_ó>Ö]‚lo,6ºÊÑbV@ÓàõEâÅœx‚x?d$ôÌ ŽÞÑ} €‡³vM>îò0>‡§îÚɨŽu†œÄ×I‹ Z‰@àÎ÷äŽÍÈr9¬Ìó-*°¶Q Û¨G]A½%ãÅÕÈóUöj­aðèÎòh}z|YQº(p¥Õûð³¬Fôí/ þrˆ Œãr¼‰„,¼ïïÅå‰1ڙңū$¡À4êtÞרX\xĈ*ûíƒíÍ7¢±aÝW;ÂlW)isPÁ6BZéÞ Eën_k7™Ÿgr¨Ž­Œæ¸«ày·¥¯N€èO‡àúZe×›m $/ß¿kû°ô=Épf*ê+¶¯ó å+`g§å¼'î5Oš:’ ³Ô~¤µRuÞaf¨•¡¸µvÌ¡f’ß'ªÐà£DESIƒu¥^%ª4ijn•°XµR=9¿F%,4óRÂâ×VmÙQ•¼öÊ8|þif+¤ÂpQVhà+dVá¿ìzØ­' k’qè—6+¶ÝLI‘mè^|?ñ|™ý‡94%ïåhç$I9qèEžð vÄB¥ËÒËÅ›óÄ7—Xj°͉¶f2.âLF¿Ñ8V"Iæ™…ª=²|hY w#Ç V ?`ãg?äòLž‘߬{J”—åÌÉ3R‰Mš æƒrÁv2‡  \ 7`Ibwâ8è€Hexq­Õæ9¦¬D¶Gc³ô"Í1×öуŠkÍ4Û3ÓIŠ ms4‘E†¾Úè?$6²­'6Ú•!£‡TÉ$êÝÍò~¬ò¦3ãùÔÌšr»]Í ´Ï½3 ,v9cGr%n"¥æ-ÏÈjÖ8ëÞ ÒNff)¼­:-{ Ãæõê6u,pnÈ|Hš:ÊÙ~Ê{b÷á'ûEº'r-³…‚¨¥£÷!‡i VÚ0µTW¨ªæ@±Ï [ÎY‘Ù°¬f7"¿Ç€©ÕÑaÁršEa½R>#Ýx¨ÇwÑzÏ7Þ¿k–£$:šX"h°Ýbör9)ÃsÚ`‡tû}‰•2¦äÆ.\"cXYw»‘—¥Ë5jõa=õ¦¤™Pn­1%Ág;?(Û&!%Ù±SWøý¦ã-§(ïҮ߿N3ö¥ö—Älº·Ž9Vé!/‚\X&¥ØŒ[ìq,ØvŒ„ªÀËÎÆâÀj«ÝÎ;ÂrŸp1ÐFI ¯‘Hœ ä•¿©< -B hžÆ;ô D>a>$>ðží9Œú»P=9`l¤)ØìT¥#çÆ+iIgÈu-uo‰¥®ÿžëtÍ"4Ãd4Á‹ÚcT9~Äҳ è¦ú©J§/õ¼©?…uÐÏ;`8Zz~øóÇ×ÓÇÓT%¿¸Xßñy#÷…=& ± kólÌÈEåþbc†xD2gúõaïôpl’E&yAak—'FžÙ½×ó)ó§ù¥}+ÂøÎ?Á¨^“ÛÊò“\{ŸÅxW¾—‰+N;Ô$GòI+nóâlå á‚à_]•+õæ-íǗǯ_î$åÏA=†!¹dQ—ǽa9‡sƒQ- ½©jøcâLÀГkðBàW7v¸ùú$™,(çùdRzZe •ת!³ö½êÇýjà|}û 7¬µ2lu" oèû_¿ÝÿñÛOÉCI*g;ÎCtÎ÷”ÈÃyÄ[ëÂ{‰y·üh+'7®S~´}¾qTÅáqCT]iSYpŽ·ü<ÝZàãÐ-xßwa®¢\†âyÛ’ób//2§!))âÐÝê8ö6ÇÕqÔ¨š±=¡ÒZüþŽÜnö÷$wü½0ÝÒ‹}ÆF}È/œˆsôžì4ÌQ«ÊvÔfJì‘ùøiCEÞ&Iüʱ:_¢½L=7i'‘ƒ*"eÕ“º J4³ê>mžÄ•´w«Ä‘Y×=3#›ÙJý¤úšYâ•ï¾ýÈ¥40ë·¥mèÏO|¾úâ>Å [gÎàt•“ ËGÝ&u{% âp¡ä4c4µc¥$â<ð.SµÊ š¤AÌÇëÊ¢Ò.JT´^7§A\Ô2 T‰uÀÚTÝuB=f+zR}Í,ñÊw¿# b[yüÞ¡*þä`b“ÖEþ'dLæì' Óv:sÊ%÷h¬;ô<ÝUÅp§ÄQŽwÙü¨¥Ã© –VòeJ etþÆA5*Û¢“(¹*)TE…¨ü®!ÙoÚP]­õ3Kœ´MEMÙu‰sŒºÍ&co¥~RãÌßxå»ow`6Î.ùJêFsC*‡Ã©v‚m“(0¼-A›£Ý.2·62{æÁ4;zöÓA° ’}Ã,²gGuÀNŒ “ž±0)–¹íCi/nÝ*o ßîTjkÏBá%…ùÈ\»¨9uñÛ‚å„åi|ãR ú#M¦Öؽ3eÔiø›*Ò¬ù´¨Fu‰ÓV¶p^µ¢t#'u~‹*ñÚW¿ËO[ ÛZoR5æÉ"/úgƒ˜Ð~–n×–9?2'¤ï‰ì9ÆƆºÛ¼À¾à/ÄP K:³aË”ƹì+æ:>`sR‡hM%ÆÔÍY•“Æ/ˆÒz_Ñ60µªšâ8Oa•²‰SgþR£p¯Ú8Þ7ÛïxEú‹î|=gû?¿~û÷ß>÷豯ß>d©hˆף»åÐŽûeº/ÊÇ`ØCQÂ\l’"f`Ù(Wó/ú!r|Åi5¤lëüURžóÔO^etPg‡Qà–]ïO?£#áq6öÖ\†ùñì<Ö÷›þ— _EXžª¯Êi …c«êoOÞH6øêµQ9êÄdÞ~³6ÿº­õw%^¨è”îTà‡šD㌠;ô/Ò ¯:†Ý±KR2ÕÐE?zÔº¬Nܵ‚©ìÇÑT¸f›ÍÓŒÆæÐ§~ÂpŒ..ËøçÐu-9¼Ã!Ÿ\w§XÄvQÛþÆÎZ&éÍäz¦7óµržßL¬‰…Õ)oqzq©Ï\Ù¼(·œ|L®W^²õbpÖH™’½MUÇ Í¸1ëÅÙΫÜÝ\$”W.3I|5my®G€Þkû©iËY§ê½ÎÙqMã^ÇUqãkw™›²]±%5¶„’u›H.Œ$z™N ®u’Ü­…W… 1øõZ¿ãŒzrÙ’xÔ[ê¹<Ï¡n½¦˜…Àálãµó¶Ž£ã_a–¡P·g¸¾í}ž—¡Iö¯?-/CÚ ðv0¶v`MOÀðÈŸø`×ñŽïà€¤|`9u|öÄC’rØÂÛ¶¤ƒÆÛØh*Tˆ‚3üôi™û6ãÐG16‰fá_F~RW&CN•¼R²_f"cÞ™Kyzz»<ŸôV¥Ÿ}(ZÄòìL1 ôÑi¡ ç.£ß‚ƒ£C8'B ^Wå”*9wYÂ÷¹ÃÑÃ|±ñ³p(}’DÞ 7‘qZËS)1Ä•mŠìåna¿ƒuAŒz~ÓPܯê²Ðåòî8öÄÂh/ÞÆi˜b?W ÆÌL“ ŽÅ‘XürŒ[áôò­?$þ]N"Ví“ xÕJõ$S §I¹žž_­‚È YÁÖÆÇÃqÎ{â,‚Üd‰¬µªÓQZÏhx¯Íò!åØ;Ÿ‡MwÅm•豆ûñ 2ª2ÿ–gÚeæ´| Ï”ƒ+Û=2-Ά¼~㊗l™e2¿d ûP#DvËY°v7sÆÔG‹å&ËI¥Fßû ~-q¼K–ÄôvFîIÔ |@ÄÃÇ⛄¹Wƒ.dºr®Î‹Î›ÈŒ²Œ58KÖ«t+Ôf˜Õ3-JLdCÈF™R5ÄN›‚ÚšzG>㮊þ ¼†žÍVøNXœ2J¶ `àzö¶ááÏ6H;6H«9¸ãÓD¶ìE­r0+Í3Çäd?ˆХȹ‘üHu?¯ËPÍ Þ¶yÍA@ÊÁ³ hí%•ÛÚL™L8‘YAm’Ÿ—öŸ‚áÄ [˜1xí³–¸ËÄê´ñ½†s•u&#öcl¿”ÕÓ’út#ë ¨u âéˌ´ë$Èã– œ~ŒsˆOრ“£BWîŽõ©µzu"Të)»žƒ?m#‡Øå?šsÂÄê×A¬óœ=D+KÕ‡´±­èáØM?Á@ÿU˜!\SfØ6CR7Ö°‰ÂÍ…cÎw‹asWÂï°ãàydUfóG…$}ì(E-s±ùf‡ v9{qÿ«}ÊÏ”¿*æ~¤£9!éyÁŽ|/h½·²IÏ[OÏC:Y¿r–J;“óð­“ä<¢Š_Éyä5^r«ÐÄûºª”Wí꘳ƿ#ŽÞÇùíæh[Ñìÿüñðã#mòbò •Ɖ…  ,Æ€£/ŒF#ÒdÐ]‰ ^Ÿ}ÐVéÄøÛí{ö8D”#þq•Ç)ÉÞuU?dI1dIߘ»âØÂ:s÷Ž×‰Ïûš÷&ÔÚ‘P«Œ¦Ý¸;éú[‘¦{‹Í»NA9P’@Cn;™÷ôûýóó# h¯&h¬|²¤ÿx>ØJ<}ùÄçö. *ŸÑºØg¹¶Û”'ï«!Q7H̺«Ã@B-I3z˜²ç ¡á°ë(zòÊEªxÏžcäÜd1z&I8æœë9È6FO>è+ ³CJ(`"êˆÜ@O»8ÜÀ)ä2nù¼”>¤rà/îaµu’$ÿø톘(°ÊÜ#δ Þ¥‰@'¹Æ[Á@sÛn7£ÛýµnÒƒƒÍù´™<Ò§vlœs  ¯†›«¾ŸˆÆ¾ÇyhËÞi²9Ë7ôkj@W%Óxw†¿´™&‚÷Z@=,qDSŠˆˆ°®Ýhg¯ÈúK?{\Á³þÖýß<µÛ•®Æî§´Xä:×þ /Òv^æÂÀZ …Å/ûiJ»±„ᮡî”d v¸Ä¾â›„q ñ’’³N!jž"š72»-Æ5—]ðíþ𦄄ò¬ÄÎ-aA)xxUÇÓ™h Ÿ«‚%¦ZÝDEoó#åC´rÞ}ß<}ÜŒ¼ì:Ù¯Ôø¬X@#%Ín$¬IYÎr,ø#Ø+ÖqL7 I±èhTc’å·_úù¥dˆò¯(d{(ð¸/»òé6+€rq*œ,4é k댂ƒ_ùD+ÚçÅäÐyBÏ9äÏRUFñI˜F‘8ö¡í•‹üjœ—D`‹àz¯JÒkõko»Hx=i'NöF’5ªùä²&Î5ÍK^°E3/Ø*,nò‚áø‡Þ,ÃÝò0ƒÕm=o ÈÞT€Œß‘ìe1ÚÜlhìÓ1"F¿/…´1 Š!s6e«zìÖí,`sWà$Б1[·€`±¼ÌNDÎv|¯ù ì3JÓMiºâ>/|ä×ÈÖÂ:î:)ÄÀ)­adhô×}̸À ¹\ûáU`\¾öa³?V$Y•y&˜Åü䎤óÁ–’#œ“åõ7©JÔݲœ9éWÅöLÂt!±–½Vù¡©—fSoIú‹¼Ãv`xn<½lDq øG:íÀ@žA Rw§BáÐ'9Ò–¿)ȾAfy36bRWÅK%Ï0ä±*çLô|h±óR(ÝU ùtQ^ñZÝØ,_'eéöш‰žVnÄcz¶¯àÀ»µnc7Ò<µ¹!’: APv'©±»xeôSÌw܉€–ñ±à=¨ÑÊæËÝZ°“yg°g†ÙܶâX¹ Io0Ùí‚D`iãÒejÙUË8ÏùiQM„/½‡gØAò—;Ä´bð†IfÑzz`‹”°úIZ’ª0øzV§NÀê”l ³ˆdýEe“fNªYêÉõQ«Ä+ªÌAæ­D»ßÜÄ8è§ß‘Y'B}ê)\âH^° ¡%ñIÝ|$Ö{^ÏæíD=³u_ú‰]$Lñá¡AšÂ‚çÎGb_ÒøÕúó׉âT÷r(-Nß…„Å+[/ÈÕÜ«Î÷·_ÁüÜÜfØaÿr–Ë G¶}ûúõ; ì»ùz©ÿñ äÏ{Rv$zAv°Pº }gÜ‹·E¢ó ·±l·O¢8Up¿É t%L9@Ó2;!x•5²0À&ó¡ CRaŒ¸›Ò +_I)_?E ò2˜RBƒòt¿²ü/-u¡Ùa騼g4_EøDe}ÍsM¥wØdÛ:5çDIM¥íéødY5/NŒ®«iŽóÖ¸ÞÑnÿ6èePп°óŽcákÉj<åè5Ú jDuÐ ²²MJËWœ'à&MI±²†Hþéq\ôζøÐMØ%vêøX\ÉNÂé¸9=‰s À–ØÈ÷&(9“W}cZiö²|ÏVE­°Ó%ÀŽ"Δ,ìKâ'C3Á™…ÁgmÅe2A"³’éÓ‘¨.ö2*rÒ‘ æQ˜ŸÌ'ë8 d¨i£Ö“ÑT Ì›Óåùd“vÒìDÓ?c”uö™·;¬k‡è¼ ŠÞ»z¼6N«¬A;Àè/N0踎fOSa^UÿýÖÄ–MNçxb<2c+á\7# ½X*$\³‘aSø¯ò)2ð“ÂÓ`JË"h›2îmžç´dk¯dÝ4”Áv»õÉæLS>.Y›Æ!ÑêIf“ ¹Õſٛٿ͗M6ŽŠ„É3ñçhšœKv›¾öÄš‹AB¹ÌjMÏGÞÐÝà.bÛÆ³ ®&D5ÞËC‡üôZw 7 œ8)X¢jÏë¶ ¨ fx6¬sI÷6Ìã[ë{5«´@û8·i55xÆiN† EÚï†u9§CwØrèy8²Áñ_v‡…9›U¿ážÚ x› {³-ÐøöK´ô“ ÿ%xI6޳âEN´ e¸ŒÙÖËÞûÈ‚gØçÝ"~ˆ%и>K<ÒW–·\ú敞 |‰r:÷^×cÄѬ+‚;!êm)ÙÓø Ñ Î…Ø>€Ð®ãKq•ÏÎlîè7ŽY \«àR}Ñ.\ÏZ~Ødüª ­ÅÇÕÁÚkÙP~€éœ8ËID(#Ó+ŸÐ&Ã<çÿÅ)µËÓá@%fÉçKf9xë$¬Ç9>éÚ$½ª<ÀΘ~¨ÞÁÇŽ.hlµËÍšPÒn*˜›m=T¸ièçXÊù[FY$-ì°Ý[‚ƒ`†9üpÁ&¡1Þ9UÆÄ€Å®­±=.ˆèB ªÕê:ŽZoZ¬øðÊ2 Qÿýÿhgg€ endstream endobj 4 0 obj 12861 endobj 1 0 obj << /Type /Page /Parent 7 0 R /Resources 3 0 R /Contents 2 0 R /MediaBox [0 0 2613.3333 2662.6667] >> endobj 3 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 5 0 R >> /Font << /F1.0 6 0 R >> >> endobj 8 0 obj << /Length 9 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream xÚ}’OHQÇ¿³%B¬e&RðN¶Wí`ŒÝõoʶ¬k¦²Î¾ÙÞÌn%Bˆ.AÖ1ºXÑI:†‚b]"è(‚—í73»îˆÚƒ7ï3¿ÿ¿ß{@](mšz€yÃÉþ(»;>Áê7P‡A+­Xf$‘v™lqdí}…䜛áãõÿ] ‚U€Æ¬ÇמöxÀáû¶iO:¬äÒb“¸M¤’1âWÄg³>žöq†[ ñ2ñMÅ'"()Y'æ±ld4ƒä—‰»2–’'&ßÀSg^™öÐ}8õ¹&›°€åwÀ¥Öš,Ô \V:k²Ý¤;©iÝR;;\‘Œu?ÊåÝV þ°ÿ¼\þûº\ÞC9¾u¥(J•IÒÀëÃ]ýÜàBS˜s_ QP5ûFz¼Úë׋Gõ%«t{3qW°D÷0vz ¼ü \}\ø$€Ôu¡ºmþÀÍ+˜…–ÍÙ¬C–;XØ9:Y„^g±BÞ,Ú\°ACioci]g®©Å·¸(ñL;òz±Úï9ÚAnŒŽÐIó ¨Üê­°4“I÷ÐÝ x#Ã{zwA¼¨j}ƒÎ…Ðþ¤Š¾Q¥óš=˜ò8Ðmèñá Ã(Äo{1±cÚÑd5¾Ué­ÊgÒ·t¶üÆlaȱi"ßÐ\.5æ±”šËÅâ^Å8tph0èk€!‰~D† TÒhd¡‘”»6‚ØÂì±–:>f¤ß&Ÿm×çŠäíxÝA4Ž…¶ƒLþ&ÿ–·ä%ù­ük±¥ªiÄ”¦¬?ûCqÌÕ¸m¥&/¾By#¤Õ‘%iþ 'ËW©¯:ÕXl©Errð'ñ=_—Ü—)Œi7Ò¬›©äê,úF|ÙNšٮͯ6×rm^™Ü ®ÍšUáHWü «Ãÿ5;¿?ÿͰh endstream endobj 9 0 obj 706 endobj 5 0 obj [ /ICCBased 8 0 R ] endobj 7 0 obj << /Type /Pages /MediaBox [0 0 2613.3333 2662.6667] /Count 1 /Kids [ 1 0 R ] >> endobj 10 0 obj << /Type /Catalog /Pages 7 0 R >> endobj 11 0 obj << /Length 12 0 R /Length1 13756 /Filter /FlateDecode >> stream xÚ½{ xÕ½ï9³j×h—¥‘4ÒX›%k±,ɲe{lËŽgqv;‰ƒM²@HB‚K(@ ¡@ e§,½”R(7N©C)äÒh mJ¶aé ·Ô·½ï&tI,¿ÿŒäúxß{÷ûÞ÷fùкËv\ràŠÈïÒÔ"$Æ×¯]óÁ-׆ª€>rë¡@çÕÜù=¯]¿iûU›Q—Bþ;ß~ÙæÕ£ÛV]ó$B òÅM£WmQ ²¿‚üJÈ —nZÛ}ÏÍoAþùý-›·m§Œ4$@°rËk·ä~4úJÀ|˜¡ #y=òŠfÐïˆ@ÿÝ‹¤h†U©5Z¤ÓŒœÉl±Úìg ý¸Üüÿ¹ ½t?òÀã$ïA„¦Ï$<,wB=Ô•¿?ý6é…Æ‡ä‡(·Qñh'º¸b'ze‘EÐïqä¡è×hZŽŽ¡Ùè)< íEóPm­¨¿r¨=„^€7v Íж}ùá­ç¦_‚²z M OyP+„^¾‚î›>†A@g¦þ#Ê ¡Å[Ó¿CIàʯM\(}nD[p=±}z7jƒñîEÏ¡÷±}º ÙP#*¢Z‡Ö£Mèrôe¨û>z ýËèÔ£ŒÓƒ–¡[Ðè4Ž^Æ>üEüuJ=½~z#Z 3ØïÝ«9>Bÿ‰MøEüÊ4?}hzÆQêTêD_G¢oÈ+A¯À} MâEx)’Óúé†é³ÐÞ¨I¨­„76¡k`%÷¢¢×àþ5ŒÁ9¼oÁ»ð^ü ÑIZ(–ž7}ÌRx·Â=æ¿ fºÝ>ž†ûè瀼‹D±‹8MšH‰Z@M_7½ú…éŸEhdüûឃ¶£«Ðt3Ì÷t½„~ ´ú šÂ,æ°æp¿‡?&a"¢ÐÛÉÍä^r?…¨©÷è6zwùñò©éuÓwM¿6ý7X=XÀ>‚òp7ÁíhZ„†ÐÀúR…?îCûÑt°{ Dï¡)TÆ^Xgwâåøjü/ø>ŽÿJGø`Ì(±›xî£Äqâ-ÒEzÈ™&W‘w““OPwÒkè­ô×èÌÇìžòêòšòXùšòóÓýÓ÷Lgú(ÌÆ³‘iÚ‹ú`µ Ðb à%èjë½2/Á|žAÏÂ}fõ=ô{!âÇD/Pb'~?H}ø¶îwá–àNíûÀ°N ‡‚µbÀ/ø¼Þíªq:ì6«Ål⌽N«Q«X†¦H£x·Ø3"Œ‡FÆ©ØÛ[/çÅQ(½ `d\€¢žÏ¶F”fÂg[JÐò’j)UZJç[bN(¢b}\è…ñ×K¢0—/„ô­%qHŸTÒs•ô>%­‡´ß/ÝÎõ%aÝã=cë÷v” »#¦©cZ¹ãqÔ5ºs½"¹E÷¸K,u׈%¥Ž v®X0Ø]rûýCõñqܵZ¼x‰ãÆXõuù=š.„±ëãäù£[tkÄ5·LHèâ95ºrpœ'Fä1L±q‡Xw\ýóÓìLªû+TŽÁžÑµ{{š[z+Ù97úÈõ/ [âÆ¡Áq|ãPeÊÜ+«X+vË%#…qµØ)®ß»q0G º$W·8ZGƒk¤%S?â¼¶Å ©ï¨ïã¿óÚJüÑ—*åoÕ*íŽýâþ…çqÁòHbLs\X­ "Â\›ä`mÚ»º šÁ5„a•ÆÕ]#{¹fxkœr¢°÷ B‰“úlÉhµ„ rgœ”Éyž# ¾šž@áxÿR Àø¶¡ <}ã*yŽ€†!/ZÕ™6”àmÈDãPPç‡T]\èY÷Ètö {ûÖìz„õ@p*¨ÄP±vïP–³hp„‹ýãÒû|ríÐP3ô“û¡”~öA«=lTz€¦ Q<Þ… Žï*¹Ç¥Ò@üst`pü( 84­êÏÏâœÕ9'`ÎõuHVzY}@C{÷Vr¢üèÞ½î½ò>¨ä'0úç©Z0”€U&ð®¥j—èwË¢_ôô†J0T Øk†¼°i»ˆ¾ldp×!÷ÑÌ^*ñˆbûH¤¡©>’$\j†íèF¥þØß³Ð‹Í;]œ;UœÇ}RœËMQ{qªÈ† ʘü¦0<~zlâì?èþ<;A¾s.¨Xaø6ba€±IƒZIì¢Q EOàýÏø¿´Tîö÷!JÎL§,~›ÿµ¬& »”w©é÷‰$½Þm“œˆ$ç› $V!Ih«==‡ë?qàëÐWÜ™¦Ö^ÄæBa÷ÜDl'÷Ãt g°ˆ_[Sn¹„^ÿ1ÙÒCýÓÿIÞLBZX']òÇÐÙÁ†{B'Þ¯¹¿ðmÍ·µOèŸWÿXýZòµÔ»êwS'ÓRO¦ŒËTñtƒ÷Y}(c4bc_C"WHÇÄXUÖLM´å´ª¶VmÛQsÚdG”ÞMÖí¯#ê&$iºœaw)ÐI•¤ èêL?=yzê÷ÉpñC“¹0U<•Díí“òm2; P4–vN‡DCNuíZÚÚňÎY"¨1!s¨bÛ(/²Õ:¼Èî°„8/GH aŒ Fº]åE¦°Õ‹Q,ƹb Õëz¸Ð0Þ:Œ–±YöLC.[›Ï³áË@£°Œes™Ð/¦J«¼QŠÃ•(‹‰þmýûŠáTçŽ2úêJl±.Í$š ÍSŸzú[/uUú¨Ã‚MÍ¥VrNnÅÂ¥×âD](1´uEŒŸ]¸t´¸nÉ%‘.—;©+¨šìú–Úžû®íþrys³=lp7†kBƒ­BnÇ01‰žf§'Éïƒ}ìçV©îŒ3:|¿‹*|Ò6€x¼Od‚,ìƦ%‘¿M˺W›´Þ’a‚ $M8f’Ö£6l™s Š eŠL"…ü øèÌä9|F!“tœ ó†0ÏAàÓûCØctƒË‹aPNK¶ g«\@‘ ‘©1$"aH›‰½â0K¸W^uç‰òÿxwóÛB3VïmüÊîkoµ‡ú[À%1ÌÔéXÿß^~³üÆ`œò7§ÏŽÖ¿q×]S˺ÊDƒ$`ÐOîG°t¿-õÝâxLuÌô¶émçïLzÙ¬¶[»T»Q½Q³Á¶Á~µz‡æjÛÕvmDåp²Îá$N «ÑÓú ûN ¶tðZ‘è}N€è™ WòÉܬ•¹•ûÄ\™trÄÀq S0â~¤`ãöø5fp;=\ühL^K}Hf?Ì) ‡‡Ñ0Ld¶IâPXÁ ¸äsyG•›QF$®~6‘³:^ðç®øúÓw®_hæ í;~ð/˜y5Nî¿~®¿J¤²vÛ+ß¼ç/¥ðÓU=7}òóŸ‚tP°I6“ôXQÍèiÓ½‘oG^‹ü(þûøé8ƒ6%®IÜ’x ñTì;‰çbßK¼;žx¹éÝØ;‰·š dlN”UÚ“Ô€†×î3yÇ€‡÷ÞáoH§’”ƒ „’¢ƒ¤›)s½ 7fêÙæ¶pد PIsXr`lúÃÅ|é¡:\'CXl‘Ù 0>­ÈQî<‡9@,GˆS¸¬U˜-[ˆÄ³ñ|"äb!Üm¾€Ù¶Ê܆v‡Iá)6›oÃ2ެÛHku£q8«KdÍs.[i,ƒN$Z#AwFgö-¬_à‚ [BèÖÚµÌ-_g›¢}#Oþ|ê»ÛFné¼ö+w}< Ø‚¸­5A~›Î¥£ Ǝ–s?íhÄ„ŸHµ¨¿ØêªÇìÓ¿ÂùsO¬Œâ§o¸ô×ÿòè9½‘é?€—ð$ø¯æéîÍÄ ]múYO‹¿QŒ»lžþHÇd×Ôµ[ÛÕ²·O¡\¹“| ä™<Ä¥àõŸFû:{»né¼¹ëI7MG輺ËÕUèÚH^Öô¸õq§ºÃÂ%zã1eÜDh×Ñ †<]ª^ÐÐ%–fz}ÑùÑ£dtÖüÌ2—PÃmòe!ûœûB„ˆ¬ uCt&' %Z»ÃvË~C2,*qö”}Ÿý;e—uÄÐ`òøÔð$0üs xJf$™§ÚrcïÉ•œªªðÊÆVž‚¬ÂeÍ …Xþ“•¬¹¢]åšlíŽ ¼á@E' ržªèàv bØä=¢èè ù£ï_ýø‰Å_ . Ø/vê’©ðÚçžì_`[bÑ=mÖ˜¾ÿHM‡ç¢žDÆ+ï)?|è±£™þN]ÂéÞz&XÝzqÐ2¶JUþ/iÛâ.»žÀà5èv)G„ï¹ònrA¯¹ñŠÕû£Æ“|à¡çoì«í.µèÌ&_$8´ÆêM}á¢ÿN÷^ýÑüj~ýts –ìÝvüwV;\¥Ⓘ!¶ó¾ |Vj Èü›j]í¼Wcí|RgÄnTŒÅ¢¢ËD2áÅÙŒ(ÜfcSIŸWS+&k\²ˆmà±$EÊÔiHÃ>WxQ±Åâ§"öS%.[=@e«sÁݲ×z±Ãt„½X1ŽªRUa÷ªPmÃíØQQæŠ$óyö|}µÀ¼0ãiÒÚôñëkFˆöôà%ßhÒsÊó—5t,ŸwGã’ò,^Ûr9y´)Kµú ÊËNÝß(îé½²¼~£¤áy]óåø®Ñ«¶˜Ê–-M:¾¢Ã`ßÀQ 6ΰuÆvjEAp Ü€ƒwÞÁ >ÎHñAÕ]âÙ`­&¬Xœ‚ö.:ìÞãŒòN%e»øöCyŸ·ÏU¬ÌŠªá΀K§ÌŸnë,©,.\U)òÂg–ýD1kmÅ‹».mRSZ[Cl7¯"ò£ekkUjÏš4Ù+ñ{5QÊà3<:V5ÕpE³Š¯œÒRÀÓôVÔ„ÞÆzj…1ÛM¶Çm¬ýG-K !!äÏ yÿu(µNؘºÏ¦ñ³5 Ú¬b@ ,2ûÓV[:eKYÓé”ðƒ…òVXƈ¼nžgP.J†ø¦|XcKC=éSD¸Á3Þ>&ÃÍy™÷´Öt²IО< ÂPf æ‚¬£O[œ{sø˜¢š…ÖdRö.ŠSŽb;ÈÆÓ“çL•R(gUœ+æâŠ+ž“  š‚PØ gý66b00P¾Rˆe‹òÔHkªÞ›–¯ë³ ‰m^[}3~tËžk9rÛ¾å.ÑÄkÔåg¼}e?Ï6,"ÿ8+D¼Óí4Òêsß=ítÉólÿÜ_&v°.žÀ:ƒÖ¢Ã÷–oëuäìƒ ?]ƒh¶$ØÙ…x‡Pk̺“T³–×í3›(’‚Æ»¦øèÉœ$)™ƒœ )ì̽uò²K.ß0Ã,uÃZk«Á_³û–,®*󼺰ˆüYgMÃøk‹:ëÙË2,/óø§L#ùš‡þ!ñ¹šF0 ß2ó£ó‹×ÂÍõÍ#Ûóõ]|ô|Œ] ¼ŠsT3âç µµÍ|Dóí|‹ ö5ósQ'а¤;Œ]}î¼Ô×Û%åsõµn+MéºçYŒ Ýmކ6ŸÏadçÍ-¶D#šyãhÅÚdâöúõDoýž%é{¤\>Ùq»tB"z%(ùne ÷%i•ùIEæŒvÊÞñLâCEe•:—›ä&ÃQ5˜«6^Å3%ððp:%ŠP¿À’Þñ`9ù<éSñÑØ.š)ñÏsEÂõ6›¡7|¦‰Õûæ¬kl³ó­~4çk_Xn]–·/낹ÂÊrö¢F«ÿÒÖ±úìP¹àb-že=;AÑ¢S_Òv/ïî uô×¶}iö#åÑY•‹Wåáý£‰…±š|-XLº\ºÒØyóÅ]¹©÷æ4cWõÜü=ù¯(ƒÑw¥¡×\q·áq(ŸŸkðe’þv?lçýB@fÆŒPË7ó‚ ‚­ß “°Â•ÆD}·P$›1£mް‘Í4øM#Û &)7”ûnÎN$I’’7s.+kNQ²{-{×29Nƒmcš‘|2üô0UQáˆÓq†ÀÀs…k¢Ÿ*ƒá­Ÿeïv,Så£ ÎSgt–µÅ½oK®lœ·¸ÔtYs©¼¤¯YZÚÒÈIÝå~ü.¯Î®.vÁNu >úÎ¥B:<çåú^ ó¼¦õüÔÒ­GvêDošàI5Nÿl¤'A'8Q ºCŠ¿¬þ@MÜÍÝg„{Ê~FCÛ‘•r8–hst³Ê™©!XsF¥­±•j´4˜Æ‡ÝÆ’Q‹µ²uìvUsA1ŽÁ6Vàˆ#‡>¨ÃÆr¶6©!ea!e@ζSpsY¥Z9Puç° XÙ¬„@Y$(fÅæ!Ä|ãÔ+/cêÜ«GËŸà¡æ5Þ¾eÇýw‰{°¥|î—¯”Ob×[ø¡Æ¿>X>þ“o=Š2©›ðÒ“†rêœÿîšû‚O¿>>Vi‚txv|¼w× ëÒ󙓵‰.¾á}Ñ)˜%éÖi5$àÑL½Ï¤ÓЄ׭jY7K¬Žj3 ºR޲^`"ÓQs2e/<-Šö ·îÎïåŠÇV!Y2B‡0[ &Bˆ ªB¸ê°ÉÞÚÖáÚ OðgÆyæ²+‚Xe¨Ñu=—Ý÷ð†ÙW—_Z• f´óEô1šîlX~ÑÞWþülSTÊun.›¶wýâèÄáñ²zê)¦ÔGo͇Kjfw§ÐôññWËÏlMå#k*±ê'¾››kígÒMÌËÇÈ»âßNIOüŠøCâ“8;7Ž›TÁ.Þÿ~À­lPRÔ;VÒÍ8Rî`?dU‘WãÔdR¬“åÚê´~ÁÀ„ƒI—äÆnÅXÓ—®Çõ2Û)Æšâ¶ÿ °¦ ž± «¸FbIÖb 1}i“¨MŒ[¬†8Bº„·h¼2âêñVÕ«Í]°e[Ù Ò€öb[Uó*»÷Ó“-SVgýÎÛvß|íŠFqÖf5HO‹gQ™ZÖ“Y¼aç Œ_¿”³¸"yüøüøÀÇ÷8I–,ºH'…)J{VʺÂ*Þ›×àÝÞôG¿ù NÊ:N `œ£h4ç˜çØŲԋ‚úê’Õ—V ÚÁ޹ƒ ø¼d¬¶6Ê8jõX„],xRÂs—‡ ;XPV»\س„k+æï¡ýÀ`uÉãÊ::6,c:÷ÔñÉ­àöš Ís³âó+·Ê~Šâ©X‚Uó6oó«Wƒiß\¸ÊÑeIé RFJCsíâ%Ãe‹_•À?X½„¦üÖ:µÅ©áZÓšˆ6õl-–[—vþ ¯­Ÿž$~{90)ù-È‚íDT_Я×mÐïÐîÐíÑi¢ªŸþˆ?xgõHƒ&öKÆ@“¯ù™äæý.¬^®ƒ¬M®‹ùÍz¤QÁŒõŠöeÌ,©Ó6]øÏ®iáêQu4 T‡ø¿$…·15’ÆÔˆ3ÝØ›ÎáS“`û,;6¼ÕYˆ¦Oõv«ëON×é†1¤&!5©¹œ§?Àœ«uñÉG¢‚Ÿ“™*ªòbÁð"6B{‘Ÿó)G±xæìÕ’±;ªÒ@v¦ÏûùŒEœ9óáO©ÁŠx£ßîÙÝ¿¬¡}Ë·?²#{ÊÌ1NÖg ´]Ù3°÷Ëo¸½x¯Ag¦]8ˆ[®hݲ¨³n^Pê¼iÅ–}¶ü5K›WöÎÚ~ÿØÝ“Ž<¼Yti¡Ój™T§6aw€°o€‘´~Í,¶Í¨•4~m­äõ£‘´º’)n7ìø»®W]ï¶srSÇŽC’{Ô>5ö¦Ëùª«ýøTQ9¼ÆÀl6‘¬žËÇS²hËšDeÉò¡•Ìx„ú8¡wöÔf.{ãöÜXcM«Ý­[õ4yïÔÑ9áî@ÐîíiÞPXK¬"Z£µfÝKé?‘yË<=I¾z1†âè i^?Ûï[Î.÷mb7ùv°°øÔ>½Ï@xTšfÞ ˆ¡f>&ˆVð¢,¼u_ _òp53 ôd›_gù°&iŒÇƒœ‘ölád0$ë…D½âlÁº~Nb² +e_ÿ3*Á¨%(2DÀþk ¸ "¢*G¡¸r [ϤxÊn3`0$¡V¬H%(ùÀ Ä­–àêRG0T\Ž»Òóó­®Aš(5-¹hÙÜy{/þ3ùÐÔ®RtN}Mœ¨›¢ýSR)CòF£UP3.ÛZ÷ì€ÛÄòò'6(˜ E"ú¦´*¬ ÛòÚ¼mPµŒ[fZæò y׫ÖqëLëë=_PÁ~•w·z·}÷>tv¨X•Z]0«v–]döz=^VmWÑ5g!1o’¡ ªXµÚN˜'ð¹Ã³^V$<|vÖ>ƒ©ýòðØ9§ÃTxolÊ©ˆü—eK ¼-Y^±48Vªb5’, Ø€w¸eµ©€"ûT,– |©\‚'cjí‰CzGÐÂ|:-ÿZ¥Qk ªòO‚u5)òQc p~ê,þ±¿×6©IŸ*¬›JY ñî`f|_µnúOôm€O3VI7…ØPª`+¸ þæ£fU•QeU§œhà ÖÝVu˜ç’Êy2O1 YW*U0קܼ›Ïº¬6 ©J~¬œb™ÜYhQ_¿Èøõ©lƒXý¼Mï4#MÈ@›øæ0ÇøœÚ¢UEظ‡‘b—LIúY6^  ®”"å¡€ !>POøC~(yv–¡–äË[`Ì÷8ù|jk%=vn¸’z»rîw!àE–;v,ÆceÔs ®œü·Ê{!îÌ Ba² «ÐE>¾‚†ùFå´+ë''ŠÍzíáƒ:>/מòQŠatÄïÊ'XZG”ßJ I|E"u¯8DĬÖL?JÞÀºÂ¶zo9ˆò+AãñСYç>V«ŠHNýœf!þíŽ D¬‰z¶v —OátÖM±z‘ªÒL ÷ ÌIG>b1…(ŒlÈŽ£D’HyrƒþÁÀ 8fßMí¦ó‡=?d> ›{Ø^c/7ËAå²y1«Q1š,ãPi4Y»Íe`iŒ#j‹Dó"„ðäòYM^´ÌšhÁœ…fw3ßd3o3”#ixòb>ŸŠ›†Q54c£™læ9S ‰O²tñ|*Mº5yFc£ZL¦¾¹m‹‰q§eª5]L¾üîËÃ2’cI…z¨ÝQ<ç(VB¹ ‘`é†"™v ù¸c*’¬LÔ*E• …ž3„ª)ΜRà N)*§•l…ðŠÁ”·2EñÉP6ËÇZ<éºîÌ ºŸÂªÌ¬DyµÇá ™kM]ŽG=_cù—¹ÆØ¿mŽÏ&ïá±ÅkLt-H̶»Ì$ÏSÉð_Ë[æ%ž'§ÙÒ!äÝ#³õ^EÇò¼6Іaq™Àò ãù²D¾2> ¶ê7¤Ë—×`VãpFê¢ñÙê’{v|©{}|fOüÞø‘ø/â†Þ8Ç4ñì~­¶`v‚yªV/2Ç㱸Zë¬:U2H˜md’· &,ñ†›š©K©­h—[|»€…d›õíác\• ¦¦ŽµÿóÆ‘å =³W,~›òËêùí’Ä ¬uoV‚Ð op&4ú?>Oêky¶D£ÆòÞ½­éâ–z×:{Ó5 U>È4àwÉ{|X¥<ž©¿ZU“Æå$ŸNDϽðË—šZ#p@âj—†84;É&+û !ªŽ¾u¢7¥u>U¦OžTïΓµuí|â¤Xìâ;NŠ,i®)šýuú@)XÌÔ‘T¾³…¼xî.KFƒü@‘°»ίv»kX¦³# ó×e“Áp«ÔR\D‘wÒ5]¥ ¼ðÿÖg”ï æÊZs÷ÉÜÓ õïš4¼W ­øYAº˜ºh…߯VÏx;šlŽ.¢_HëCªH/ž¬œŒŸ¬õ6óAŒ5¡Ä\6Ó`☖š´‹÷Æ"^’¢SP”¦òŒËmæÂ5æÿÌgŒá¥ ÅP3©¤ÐDÒI>ìuµµ„cÌËuuàJ…ÉšÖ¶ <÷ÿKU²œrLr§ª”™¡‹ükÐ驸SÕsôO°À&>O¾©Ye(Õ*J«Ò©ô*ši2´xQ³*ïU軀0ù\õT ÁvØÐĈ«ÄPŽ¿üUWÙ ÊïþΑÄmûh¥QÌÌ¿¸c7Çè˜Õ*-­¦0™^\ž5Ç*ï,.+ç‰#¬ÑX\‘q›ñ.žËŽ×¶^Õ<Ü— d "DR˜Ñè—ŸÝ?¯A rÅâ]B<15§£•å© óÕí}Uöˆr=öÎÞèEÆâlR)ùïu>Se‰i¤åošÕ3íå˜AeHèX)‡ýÞùš™ËC¿‚üÄ“h€( мõS±'!NCº¤s𘡜¦ 2䇴ü4£–ÛC[5éA롾FnOú¯ƒX„‡§¶¡vx:åï¸ÑbtÞˆÿD\MJäo¨Åtý.ÓÃRì«Õ«4ÍKÚ’ŽÓ]¡×é4ì2®á(î'¦»•xÐVD¡»a¥âàNäÿÀ¼eXYµ¹ºNFþͧ·£{vߢØâ ›Ön«_¸yÓèå3ßdO¯Ek?÷g<¼[BݨÍR¾ ­| ;ÍGhZˆÁ –(¿¢!´­@+ÑQôo(“ŒêŸ.ÆÆÅ¸ýD?¼Kz|¦”RBA 9%Dò™¿\´Åûü—Žù„¼†?$„G ùËóq<Æ!õ"¡B$Ú©ý"ÐÄüÈ©ë`9×r¬B·CúvHï"hˆUˆE›¡d3”l†’ÍPB¡‹ 7#\¤ô8rò¨ó•\ ríK)¹$Œ–„\RÉùÕA09ŸÃà¹xá³FßK[ ¾çq?ž‹.F>œ>xÓ|ß øq$ =¾] o ‚þ}ARÐß.è¯ô/à[>=¾L ±dÐÿr@ß5 oÐ7过[P*HÉÑ?¢Ÿˆè¿Ñ_ÑEôõxûA¿¥„_“„Ùú¿ÎÖ¿:[ïlý³õWÏÖ_2[¿˜=¥wóú |íaãÆ}F¤†ä¡}ú;öAÙ™gÒI_xÜÏf|±xÎ7o>¸8Ñ—.~Ê×aÃ×£(Xb>¼ E 9¾•”xN)ñU8¥Ôá`2 ¯m;ØöD[¶8.E ¥rãÁÌ)(m:¸x•¯C3Õ>PI%ÇõÛî„꺃ñ×}&F „âZ”QªE”Qšª1spqšÓ‡`¢ÓÑ ŒúÊ{&|Øw6¹Ð÷Ib‚‚’3‰ D¿NOô½—„HrøÞI®òýªm¶ïôðƒÅ§|/&/ó=W^øvéy¹wôNáû%­ï›É;}%oö}£M©~$£ôw÷b%º+ …‡}7C7ÛxéAßy­ïRèqc¼ß·Šï—Œ¾D<ï[”üžoAò ßüÊH}%%êM>§,ç¿$}‡ÇבôøZÛ^÷µ”`%}ùõƒ¾ÆÊà eyé¶9¾,:ì«[œö`H,Õû–¬c/b—°y6˦Ød½¬‡µªÌ*< H}•ŠQQ*à[•ubú7RL V†“#†R~ñSÒ1ó?° ¬"€µäï=Çñ­ö±vg»¹ÍTè)}N0R cŸwyÆïî_48þ¤gh¼ANL{†údzòǵGðGøƒîÒü¡ AÞ?ê^¨”ûKCCÎþñ9ƒøÃî P±at\’+?„‚qiô/UúAQ(*A‹åú!r(*÷,›SšÝ\i–„^ YIŽäf§PRi–$N)Í^—›Øí.ˆF•&tíQšì¡r¼2ó¼Z:L*­4ã8¥Ì;¥W:ò(e2Ф-#79Ð2 JuòÓêx¥za¥z¡R½âÓêD¥ú‘Jõ#Pût­íü¿k÷ÌŠ®PþÚyDì^ ÏÈø-cëã».„×?Pý :4rñêõr<ºvüqmiüz±$XñàçT?(W¯KЃ݋<(­-\!­P>’~æ¦[·vf¬›ÏµõÖÏéìV¹³­òX7uNu·\}“> endobj 14 0 obj [ 333 722 278 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 444 500 444 500 444 333 500 500 278 722 500 278 778 500 500 500 500 333 389 278 500 500 722 500 500 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 556 556 ] endobj 6 0 obj << /Type /Font /Subtype /TrueType /BaseFont /HAEJIS+Times-Roman /FontDescriptor 13 0 R /Widths 14 0 R /FirstChar 45 /LastChar 223 /Encoding /MacRomanEncoding >> endobj 15 0 obj << /Author (\(gwking\) Gary King) /Creator (libdotneato version 1.12 \(v7\) \(Mon Apr 26, 2004\)) /CreationDate (D:20051109162926-05'00') /ModDate (D:20051109162926-05'00') /Producer (Mac OS X 10.4.3 Quartz PDFContext) /Title (G) >> endobj xref 0 16 0000000000 00000 n 0000012978 00000 n 0000000022 00000 n 0000013094 00000 n 0000012957 00000 n 0000014018 00000 n 0000025430 00000 n 0000014053 00000 n 0000013192 00000 n 0000013999 00000 n 0000014148 00000 n 0000014198 00000 n 0000024443 00000 n 0000024465 00000 n 0000024694 00000 n 0000025606 00000 n trailer << /Size 16 /Root 10 0 R /Info 15 0 R /ID [ <1be88c7b0a50617dd8dab419ec788ee2> <1be88c7b0a50617dd8dab419ec788ee2> ] >> startxref 25855 %%EOF cl-containers-20170403-git/website/source/images/iterators.pdf000066400000000000000000000344561306646076300242430ustar00rootroot00000000000000%PDF-1.3 %Äåòåë§ó ÐÄÆ 2 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xÚÅYKs7 ¾óWì1=hÃ÷ãÚL{÷ØÇ^”«c+InÚ_|a][Zo2Se2KÐKü@|°ß†›áÛðþÃI nIÿn?@— ý,uuÉž~޵¦ÇAIi„Ò~ÈÍA)?Jc’K£Ò&A?ÒÑs¢“c ^y’£ £„Ÿïë½Ǹ1Y¥ ×bmÖωM b^[“×G*ï‡[Ø?í~:•ÝŸ¦ »W0X(qË¿Þöü÷ü¸{Þÿ®F‡»Ïûíq¾Ü÷Óæ´ûö´;L»Í—ÝawÜž¿îþ~»7+ ÖIjj6Ä”¶rtJGÂT© Ø ö=ÚtþƒôlT ܬH 6 a$}o(Ëyߺ¾Š/Û¡x§µ .ƒócüaÞm.ã*×áfÝ®¸JM[JÚ¼ÒíåAÇâÍÓÀRI‡”Mæ‹…¦Á[Øyвô+æ(‰¼êoÀ³1`_Ì6ñ9@¦ùÛ˜º®lõlcÑ:j‡ Ü`·'0ÑóÿVðÄT Ëà¹l…%=Þf1³Jò©R (œÉAÚaHpÔõ¨ŽQ <Žà]ïLTåhChœJ+Uºªc•"ÍT4VIL|¾þ[gÕ5_û_ããÞÃλÄáî·§ûÍyûña··ûal&CÝdÑaS6ŽA:o2Ô© mÓ¨“5Áçn&Mä6ª}"cÁÞix1-×Ä„‰Ïß  ˜’ù.®;ñmqíóq{8}þz|ܾt¼Ñgú0``¸Õ|r‚†¿Û<îÿÞV:±2 ™#(~æ}ò£‘ÒYBœ˜„,ám}J6[Âkn¯+úÔß ccÔ¤‘ÏækÀÓŠš–,-Ùü]OïS”ùT\ŠÓ–i‚g1Ó´`',­¾ËŠ›mÅ5„áæPÙÍ`²K^&z°Íïý‰ÝlÙ¼—åØ:7o'‰k¬CL” [‹mÃù‰Ùd-Q&¸šÈEÝQõp'ã!—‘ÜEÈžÜEb0Ö$î"°¦È´ D.‚~âÛ@PIö#éSb/F‰m@^äE™ó¤‚Ë‘¼cQ¢¶{Ø~JàÖÒ¿€{ð6d V¥CÆç¸ýQP«¥6cTeu® UX €ê´$ëÙuAèL­–Ú°1À·¤‹x·ÎarÿlŒiº®Fvqaæ* ]ý /!/:—JD­†€3¦œ3DÇÉšDÚ ËqFÙ‚§õZI”9Q«!ÀÆX›ujlìÇù[ ®ë:j°Ò†ÒËØ‰ÿfˆˆ¿oŸÖ¡'^>sÀ4ŠU–¬Î¹¤¥RÆ+¹¤Xáë|‰`£“?°z9ÑíÁ+”Ý"Î#œÓØûü\CV1ªó"¦µ »Ô‡d!"rÔJ¡×>ÄÈ‚ôÑÔ)P¦Ù똶ªëyvT©àf¢ýŸ"ZRµ~ ¥«Ú#Æpp"F*òÄ~5å;On& r9Ç•\/»!R/÷®*è8¸¬À€%ÃÁ©4eõ%íT²Náeí3­ªìS+¬Û!N®rz…išóeBAD1u™(oâªb"ÆTÀÏÄèИŽ=L+(œò­T‡Ù¿ƒQ<œçµAq‰± X’1´CGk¬#t1bNñ»ÄX޽2Ó1›`$C®Z‹u´+ªžÑÊa6d¶âzç;£ô’y{Šà:›Zt  ‡¦ðg®µãt]%1±eôw`µLË ;Zàí†ê¾‹ÊO‡ý·§Ýæ¯íÃÓ³ºÄ°&¤ -1"¢éÚ¤ÿçªZdºùÈ:Ñr endstream endobj 4 0 obj 2097 endobj 1 0 obj << /Type /Page /Parent 7 0 R /Resources 3 0 R /Contents 2 0 R /MediaBox [0 0 1746.6666 421.33334] >> endobj 3 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 5 0 R >> /Font << /F1.0 6 0 R >> >> endobj 8 0 obj << /Length 9 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream xÚ}’OHQÇ¿³%B¬e&RðN¶Wí`ŒÝõoʶ¬k¦²Î¾ÙÞÌn%Bˆ.AÖ1ºXÑI:†‚b]"è(‚—í73»îˆÚƒ7ï3¿ÿ¿ß{@](mšz€yÃÉþ(»;>Áê7P‡A+­Xf$‘v™lqdí}…䜛áãõÿ] ‚U€Æ¬ÇמöxÀáû¶iO:¬äÒb“¸M¤’1âWÄg³>žöq†[ ñ2ñMÅ'"()Y'æ±ld4ƒä—‰»2–’'&ßÀSg^™öÐ}8õ¹&›°€åwÀ¥Öš,Ô \V:k²Ý¤;©iÝR;;\‘Œu?ÊåÝV þ°ÿ¼\þûº\ÞC9¾u¥(J•IÒÀëÃ]ýÜàBS˜s_ QP5ûFz¼Úë׋Gõ%«t{3qW°D÷0vz ¼ü \}\ø$€Ôu¡ºmþÀÍ+˜…–ÍÙ¬C–;XØ9:Y„^g±BÞ,Ú\°ACioci]g®©Å·¸(ñL;òz±Úï9ÚAnŒŽÐIó ¨Üê­°4“I÷ÐÝ x#Ã{zwA¼¨j}ƒÎ…Ðþ¤Š¾Q¥óš=˜ò8Ðmèñá Ã(Äo{1±cÚÑd5¾Ué­ÊgÒ·t¶üÆlaȱi"ßÐ\.5æ±”šËÅâ^Å8tph0èk€!‰~D† TÒhd¡‘”»6‚ØÂì±–:>f¤ß&Ÿm×çŠäíxÝA4Ž…¶ƒLþ&ÿ–·ä%ù­ük±¥ªiÄ”¦¬?ûCqÌÕ¸m¥&/¾By#¤Õ‘%iþ 'ËW©¯:ÕXl©Errð'ñ=_—Ü—)Œi7Ò¬›©äê,úF|ÙNšٮͯ6×rm^™Ü ®ÍšUáHWü «Ãÿ5;¿?ÿͰh endstream endobj 9 0 obj 706 endobj 5 0 obj [ /ICCBased 8 0 R ] endobj 7 0 obj << /Type /Pages /MediaBox [0 0 1746.6666 421.33334] /Count 1 /Kids [ 1 0 R ] >> endobj 10 0 obj << /Type /Catalog /Pages 7 0 R >> endobj 11 0 obj << /Length 12 0 R /Length1 12500 /Filter /FlateDecode >> stream xÚ½z xÕÙî93#vvYiF’µY²$[–eÙ²=¶å-Îâ$Nb 6IÈ! C(@ ”44ìei);bBêP–\š-¡M)P[itóßþº$–ïwFN½Üçùÿç¹ÏÕxÎúÍYÞï;ß2„B:´ÑHZ¶vtý¶ö‹ å0Bؼlì2ñžÖÖ”ƒÃ_¸~åZêÖ¬EHq ê¡•oº°÷w—C¿¦!ïòU+F—òÍÍíE¶Áõ« AçÕì€úA¨W®Z{Ù•ç=Â8¡~ êË/^·ltÉ“çÃ\Ѩ׭½r½j€}êWC]¼dt튡]ßzê÷’çׯÛx­bn…:o`ý¥+Ö×ÿtΓUYR¾m‘ý!¬Dÿ³FÿóE3 %«RkÒêôdäLf‹Õfw ÿ?çƒFq¢}È·“¾YšþÜ“pÿ±œ"}¥ç§ß¦½@¼ÜT©5BˆG›Ñ ›Ñ‡(ƒ(‚~‡[ ¾A¡ÙètÍBOàn´ÍE9´7£JüªGè>ô<± ­Ú.ô-䃧ž~ ÚêÑh}ŽÔȃšÑ Œr3ºkúzý˜~pú(nŠ·¦‹’ •7# ¹PÆ\ƒÖãjê²é­¨æ»=‹>ÄöédCu( h%Z…Ö¢KÐ7 ïyôú5æa7Õ(ót¡%hº ÝŠèe,à¯áï0êéUÓkÐbXÁxnìæú ý'6áñ+Óüô¾éi˜;€P»Ü/úz}—ì½×14‰â%t€®›ÖO×NŸz# &¡>t.<±] ;¹ý½×G0k×ãEx=Þ‚·ãW¨vÚÂ°Š¹Ó×Ã*U€w3\ó`ýa¥;ÑnÀðQô\?F¿äÕ8@µQ[¨ã´‰–˜ùбék§÷L¿0ý àˆÿ>¸f£ËЕhº Ö» íG/¡w€WES˜ÅvÀöáðŸ(D™¨(Œö3z½Þà æ^æE‹bkéáÒ±é•Ó»§_›þìžB,`AY¸`ŽV4-DCh9`}‘,w¡=h/:ؽ…Ž¢Ð*a/ì3‹Ûñ9ø*ü=|Ƨ(Š£˜3Jm¥î‡ë u˜z‹vÑ:B×ÐçÑ·Ó÷Ó2·)–+6(¾­Ø«ü»­´¬´¼4VººôÜtßôÓON„Õø`5„§=¨v; /DWÉXo'²ëy=×~XÕÐs ÉŽ Ñq¹S€ƒZÆÁ H¤pçq ¬³p/îÃóððg Ä£x ÞŒ¯ÁßÀ÷Âõü ìc\ððkøþ5\ÇðŸáú;¥ XÊI¨%Q}p-k”ZF­¢VSk©[àz˜ÚCí£&hD·Ð]ô(\Eú ýýkú#úŸŒ‹¹Œùó¿˜ÃÌQæó_Ìç N‘R,R,V:•9å˜ò!åÓìEìSìQ4ÿötöoÚDÝNý ]CuÃ9{ÒϨàÄfü4~ú>Èm\ïÃ%ÁU—®ëÃ*) Vü>Qðzx·«Âé°Û¬³‰3ô:­F­b• †¦0ŠwºFÄbh¤È„==Õ¤…†Ñ³FŠ"4u}™¦(ŽÈdâ—)% ¼ðß(¥2¥t†sbå«ãbg@,¾^ˆøœùƒP¾¥‹“ryŽ\Þ)—õPöùà±Ó¹ª ñˆØYì[µ½s¤Ã0MuÐ’‹¨ctó*'d„¢³è :‹‚ÜG;G—ûçvÜ>ßPu¼ˆ;–.(¢@{Ñ›yœ<'é‚A˜»:¾š¬íÐ-,ß1!¡ FHiôÜÁ"=:T¤FȦXÑ(W}âü¢zºÔyóYE*Ø5ºb{@³£§\!µÑ›¡Ö·P„a©†‹ø†¡ò"äµ—w±"ÐIZFÖˆEu =°jûšÀ-wI®ÎÀha¨ˆúÇ+¤ ¹R?༦É ¨n«n#y“ÏyM9ÿìëåö7jeºC¿¼oÁ\0™)Ð Ë,ŠËäI°Ö’¬h@Û—5ü†0ìruQÝ1²k„§ŠŠ ·Ÿ@À¨À䟿Ü2:Ó¢ r')vž‘èŸ)O p¼o©û÷büÍ¡ <}Ã*x€…¡Ï?º#DVài¨DãÐPåƒRU\ì‚Uw¾‰ÛÅí½Ë·‹]â*`8”sèX±}( ÛY8¸ÒA_QrŸ)®j„qbdFgûŒ°ff„5ò0ÀÅã}Q¨pþ`qKÁ]” C ÈÏÁþÁâA@qh¨ªÏ¬òÍ«3kNÀš«« ,²Æ€!†¶o/×¾âÁíÛÝÛÉ9(×'0ú÷i¦aÉ€¨Là-ýr×–€ÏM¾€–5T€©R ^§ÙK¼лHqø 4èàŽ}îU('ðb‰G ÛK#‚é¥iÊ¥V²½U¨Ôòu-pÆbsççLåçrŸççpSyÔšŸÊsÇ!©I¥M>SnŸblâä¿}ÿzf‚~ïTPöÂúñ7©nÊs‰’5ÓØ¥@ŒbïyÚ÷õÅdØcܧ(9g²&eñÙ|ýøï%5eØÏÒ¨oú?é›è}H '¼ ë¤ ÿ:¢Øp—’ÒîÖÜ{Ló˜öQýs꟩_K¾–z_ý~êhÍŸÕ“)ãU¼¦ÊÁ V¥Flì­MÔçjâF RZUÖtM´ÔkU-ÍÚ6¶-æ´É¶*©fS4Yµ§Šªš ¤ép†Ý;S&(¼·£=yøøäñ©cÜçÃùOMæÜTþXµ¶N’Ëdvä i,9ìœ< …†¤&Õ±Ijji DtÌRA}H2‡° !¶…ñ"[¥Ã‹ìKˆóâp„Ö¡ÆÈ`T´ª¼È¶z1ŠÅ¸<—a¸á¯ü»~hoÆJVi³:ìéÚúLe¶>˜© ‡~ÒZŸUü¡L]}ºl€©L•µ)åæp9Ë`ªocßÎ|8Õ¾©„¾u.¶Xý¥ MÐæ©N=õÈKA•>êðÅ`Cc¡™ž]¿tÁâkðfª*”Ú°4ÆÏÊ]4š_¹èÂH‡ËÔåT v}Se×]×t~£´®Ñ6¸ë¡Áæv±~Ó05){׈ž¤ŸÖ ~È-RÕ VêðÝzP᣶~Äãe VÚ´4òµhY÷2“Ö[0LP”¤ Ãʤõ  Û@/ì ‡€#Ãy‘I$ó€? >:1y ŸYàäE'ê¼!Ìsz_{Œî|1T†Ó’iÁiÀª>  ‚ˆ@dª Œ0üJ›‰½t?K¹êνò¶#¥ÿzÝÛb#Vo¯»yë5·tocþáwIJåÔý©Xß?^~³ôÆ`œñ5Öœ­~c÷î©%%ªŒA0è£÷ ?x£I½;©™Þ6½íü­éS/›Ñvjkר×hVÛVÛ¯RoÒ\e»Ê®¨NVÃ9œ”Ãia5z…> ̾͂-m¼6@µ'@ôt+DZƒ•DZ¹ÏÍ9"¤“ÃpT›28€÷S·Ç§1ChèáBÈàƒDcòZBÈ(êCDü0' FÃ0!b“Ä¡°Œ…pÉÖg3ÒT‡Òêªg©@F§Ó‹¾úK¿óÔm«æ'ù\ë¦ûïý+V¾§÷\7Ç—K%R»í•ïßñ×Bx‘éÊ®?ÿÕ/pU›ÀfR1žN#zOZ{gä±Èk‘ŸÆ?W¢µ‰«;÷$žˆ=™x6ö£Äë±Ã‰—Þ½—x«Á@ÇfG©€J{”é×ðÚ&¯èè÷ðÞ]¾ÚšT’q0þpm2à uŒ¹Ú„ëÒÕlcK8ìÓú™¤9,9°ýþ|¶p_®"曈x†ÃÇe]Ç‘0ˆI†8YÊf²²°er‘x&ž ¡\’úX]7D϶ DÚÃî0É2Åf²-˜àȰ¶ÎT#gd`©L9m®Ï”‰ èT¢9t§ufaAõ9~.¨¤0E‰Z»V¹ã;lC´wäñ_MýpãÈŽöknÞýmz¯h â–æEûl:—Na Vç65úE[¦|TªIýµfW5fŸzgO=zn?uýE}ïÁS {#Ó¿Oþqˆ1yˆîÞ•†W«ÖèÖ™/¶}ݤºJ·Ùt­y³u³í”ás£~‘êBÕˆéóŠùMæSõoªfˆ¡NZ­¡ÔZéÈq4¦»i%Ï/óXØ]Êï*)e›^ëq–¨v÷ Öéè÷8½à-Kï°9w|rF~'gôëÔé3B\ep#…-è YͲFu#§W8:„ì&Êƨ”¹l8­Oå£O$ÛçÅw‡Ï س>"èYê‚7§nмpýêÍèÇß{îõÿxñɼhÀkÝ5«éÇüôïß¼d…îÚw0৸²wEý‚å5ƒ½`÷"`À8åºBÊf5X¥®ÐDŒÝŠøÐ‡•¾V>øa€ö)B»Ó´Û™ÖbA‘ózX¥2ÔÐ^1‚##© _’M€ð4 '‰ÎË>1œã@*[óy¨µNNšÊº¶çä9kRäÌ‚deLLºnF§•Ïo3áÁi[Àdµ;l¾ÈšŽ'žˆ-xopGÊï©ò˜ !ÿl·ñä?›¯›ú¯è\G]ßqßÚ_v5ùêq—ÍÓi›ì˜ºfC«šDä ª/µÓ/>³@·"ó#Òho{OÇŽö›:w+EVÝáêÈu¬¡/nxØú°SÝfá=ñ˜‹±‡ün*4›k«UCŽ.Vϯ­R‹Ó=Bt^ôÅ(íž—^â+Xª%gX²$dŸ=gè"Z7¤H׋C‰æÎ°Ý2ß ù œ=eßiÀÎØ‰Lžža‚¿ÃoNLA"2Õz{xŒHTrjÆ„—¶|çˆ '0šË  '0ù#FÖ\¶®¤§ ÛvGÞ°¿l“ERgÊ6¸•A‚yÙŽÈ6:Mÿôù«>2P÷­à¿ý§.™ ¯xöñÞâ|Û"‹î)³Æôümžó» Ÿ{Géþ}L÷µëŽHç†Áüè† ‚–±óT¥¿I:ìz CdgP´JõTøî‘Ëßè¤çW u—¾¨¾@Oòžûž»¡·²³Ð¤3›„Hph¹Õ›ºâüÿ®é¹ê%ªäÕ òú ØæÚ/Ù;íøŸ¬v¸”KÅ%…hå… |RjòùM‰•®VÞ+b­|R œV»Ñ@, ¸L´2œb8›…[ll*)x5•d…‹¨ØZ.K24áNm œsÙ€çe›Ï¡b¿0âÄë6ÈG †ìνҋΠ#ìŲs4£UeqŸQª-¸;ÊÆ\ö€ˆœgÎôÏ4˜¤= Z›>~]ÅÕZ3xáw›ÄšÙ¥yKjÛΙ»«nQ©›×6]BlÈÐT¥>¨ò²Sw÷øóÛz./­Z#ix^×x Þ=zåzSɲ¾AÇ—mœ{Ê8jÁÇ–B±UÇÅÊ€(:E®ßÁ;wñ¢À>¨ÚM!ž Vj²Ç)jw+‚øg$'=”$¾5Èí§äœ·Î‘½Ì²©áN€«I™¿8ÖZÞ\xƤŸÞö£ùx¬¹9Ïo¹¨AmLimµ±=¼ŠÊŽ–\Šú–f¹÷¤I“¹ÐVe ‚!çѱª©ÚKU|ùMjPÞÓÕÈfI¢ шwˆ•vѬ;Ê4jyÝN³‰¡П»¦ö²ÏdNÒ Ù…SÞ…¼Xþœ³—Ÿ={ÉõÙÚÓ ®n×Z› ¾Š­/°tþ¼Ï«s é_¶WT)•¾Ê¼Îzrþ’4Ë“uA£¬£EsÑ¿$¾¾¢N¤Lâ#j^t^žâš¸9Â\º5[ÝÁG_À'Áá’ÀÃæQ¤x¶ŸiDü\±²²‘ˆl+ß$zù9b@'*úaK»Œ½î¬ÔÛÓ!eë«+ÝV£ëœk1Öv¶8j[ÁadçÎÉ7E#š~Ây¢Öçp“ܤlç3NÛŒŸQŽL <<\“"LV,gy L2p2¾ê”ãöß›N·øæº"áj›ÍÐW(¨e;g¯lm³²ç/{°^h]Pj^’µ/n“‚õ¹sK™ó묾‹šÇª3C¥œ‹µx–PŠY Fpê ÃÖs:»Bm}•-_Ÿõ@i´;­rñªú…xÏhbA¬"[Bóh—KW¸;ïn¼ £~êƒÙØ5ŸÒ¿£€Ò¨ýPªpÍqQ·6€2|\­NúZ}Š`+ïýDÓb%ßÈ‹büÍZ²TÕAÞÂÐlÚlŒ¶8ÂF6]ë5ul](˜¬cÜ¿b˜)+¤pÄéŠ8Càd¸ÂÑ/Òð†/‹w+&\ù¿(¤3ÜÀÁîœÎÒ¤¶¢wÇÒçÖÍ(4\ÜX(-êm”75ûë¥ÎR~ŸWgÎ)v…(* «4êÛ‹5áÙ?.U÷H˜ç5Íâ'oˆ82SGzj(¤QÝôÇ`§½äDh—Yý‰šº»Ëþ÷„ý„FaGVÆáX¤à*gº‚bÍi•¶ÂV¨Ð*À=Ûï6ŒZ¬%šÛ5ã›s²ƒþ™ G9ôA6†ƒ¶…°I % %r†°„Ó˜CȪ„DVìå –èïaˆ,²Y©€e1’fÙîRlÝÔ+/cæÔ«KŸã¡ÆåÞº~ÓÝ»‚ÔØR:õÎ+¥£Øõ¾¯néGã¥Ã?ä)\›—c ðK~~ í—Ò"MÌËÆèÝñLJïR¿O|gçÄqƒ*ØÁû>ô»e¢UA½Óa¥ÝJGʬò…¬*šá*œštŠu²\K•Ö'”á`Ò%¹±[6húÂýÕ¸šÀ"49f€ÓMTÞdkkYrˆkaJãÓ^F,&É%Y‹9¨ cúÒ&!Q›”^Å qÆt M³— „g^Ì»Êú³ä‹øf8í  ¼XŽ÷OK×Ñ…æRVgõæon½éš¥uîuj8ÝÏÂ?´¤+=°zóŒ_¿ˆ³¸"Yüð¼xÿŸîØ{”.Xt‘v3Œö¤”q…U¼7.Ç›;½5Ÿýæç8It°ÀÞ 8GÑ6iö!/Îú±ÅäTFA½võª™Vpvq~ÁKÇ*+ý`,¢VEÜâÁ¢'å¡<»=\ØÁ‚2Ý⮘%\Yvöí ©J–Õå¡a‚éœc‡'7@hšãKqqf4â—<,±-e8c-g\€¬Í§>7¬ÑøÌ¹+µ––®ÒRM04Ǹ°¸dñ©júñ—-R0>k•ÚâÔp -oNDº6äKÍ‹;(_Ùæ¯šž¤~JïE5¨Ó’Ï‚,ØNEõ9ý*Ýjý&í&Ý6&ªJñ5¿„ã ÏLào= e°>Éè¯rò¿”ܼÏ%ÀîITm¤/æ3ë‘F+Ök…®5³Št•¶ÖèÂqM»(W—ª­¥Â8\çŸÀ“8^o|ÀxÐH»PD¹ÝØ›Îác“Ü›Ù䨡á Ιkú®4»þìtÿdCiJ“r“Ëyü̹š'¡P>Þ|$*ú8"TQ•‹&¿±…ù8A~]…O¿Ÿ²¤íŽ™÷&$à8ã+gÓ–Àé÷þ‚l¯ñ9Â][û–Ô¶®ÿÚelÊ\«2sJ'+Xý-—wõoÿÆ[{oÍßiЙ.ÄM—6¯_Ø^57(µß¸týΈF[úÃhýòÅçöt_v÷Øí“Ž>²Y|ibÓ¿DªR›°ÛOY©œ×¯”´>M7ÛbÔJŸ¶RòúŸJZÝNÉ·‚«zø}׫®÷›9¹©C‡¡È½ j{Óå|ÕÕzx*/¿àà l¶=ó~„ð„ æ’·L{"x”ú0¥wvUfü.{ÝeõcU޵ …ÚÙÙ¼A¯ ïî™:8;ÜéÚ½]«s+¨óh¥B£µæºïdôŸÙ2OOÒoÞŽ¡8zTšÛÇö ç°çkÙµÂ&ööA-èåQiyƒ5ò11`OÓÂ[wVð!§Q+b¤=ÞâÓÆY>¬Iãñ g„p=“@8 ó—¨–òµ¿Ûáe”ŠÏtï `p_;åt˜rŒM9e•ÿ2ñ$¦y¢¯XãTù™Œ™°%îpƒ–’#ÍŒ …‰@…Âä•[8ƒ'êbjí‘}zGÐÂ|M,ZúH¥Qk ªÒσU)úAAiõs~ê$þ™¯Ç6©iA`r+§RƒÃD½?$š•BÙŸ¯šþ³â›€O#VI7†ØP*g˹s¾F¿Rͪ *£ÊªN9ýQÿÖ­Vu˜ Óa&Keé,£¬Í¸R©œ¹:åæÝ|ÆeµKUªœÙJJÊ…æZw(ª«šý~Ÿ¿:•©uÕÇÛôNS0Ò€ ß攂S›·ª(—â0â07§$}·M 09WJV„¤EÌá\ˆ÷WS¾ZžéC8Ô”|yLÀü€#1ü†ryìÔp¹ôvùÝÈÙ€çYîСwˆ%¨bUР"%À‘س9p§O3 ¦Ë(²2_Hˆ„Ù:ù@ÆGOäõÚýã:>/UˆžÒAF©ÔQ¿-ý“b:ªôV˜Ä—&j¢Îà¥û¨˜ÕšNàéëYWØVí-ñ8¿Ôt)=E¨ûÔŸÔ*%C%§~¥`!ÿxSŒ&VD=Ú†KÇðõ:ëÚXu€™ácüä·è;P椟±˜A F6dÇQ*I¥<õƒ¾Aÿ``̾•ÙªØÏï÷üDùiØÜÅö{¸nSŸÉ2•R“Q:TMÆn³E•°5¥#j‹D³Há®Ïf4Ù€-gÖDsæ Ý®ü¾r¿òm%ãHšJ¸³l6 8l¥ª¶Ít#Ï™šh¤ô$kiϧjh·&«Ôؘ&“©·‰Ð6™”îâB5×ä“/¿ÿò0áSr,)sµ:ò§ùrJ VãbÃCFx'³;¤b¡È¦Îp”–e~žfTùµK™sFŒ½˜øFÙ™sücËŒ—¦¬…&ÅGC™ kòÔT…p{zÐýV¥»¥e‡2Wš:z B]éúºØ6ÆgÑwðØâµ &:æ'fÙ]fšç™døï¥õsÏS”Óli³îÿÉj¯Æ¢cy^ëoÁ q`‰,…ø’D¿:> ¾êw¥KΩÀ¬ÆáŒTEã³Ô÷¬øb÷ªø6Ͷøññ_Ç =qŽiâ18ýZmÎì÷T­^hŽÇcqµÖY}ªd2Ûè$oAJ°ÀRlêt_JmE[¬ØZ+l">ëÛǸ€šš:Ôúï‡è)@ûôY±ølòŸÎ—$>[a6÷f‚;95A?\ëLhô|ŽÖWò¶D£ÆÒOܾ±á‚¦j×J{ÃÕJ¦tП®ÅïÓwX¥<ž©RZUƒÆå¤(AP$¢§^x祆æH:„™¸Ú¥¡öÍJ²Éò9hEˆ©R\‚ÚÑ›ÒJA•nå“GåÀ°ýheU+Ÿ8ÈwðmG,m®È›ê|Uz!˜OWÑL¶½IbÎ/òÜnKZƒ|À‘°;Î.s»+Xe{[Ö®J×%ƒá*W¡)¿¡oSTt&ð‚§}ž–ÿ/:‡X͹ÜçsŽƒñZ€Ð"ù-ü Bç ¥è\tp…c’Qý‹lÀ­G¢øþ,µéñIXJJNE9åäá“’–4ídñN%þkÛ<Ьý/ éAŠ|‘YÄÓ¨¥)¢Ñ(í…î§ÈMJ×Â6®¥H®B·BùV(o¡«‹ÖAË:hY-ë …AçC­f8_qÔȬóäZ j­PKɵ$Ì–„ZR® ”j\˜gñ'x^ðŒQxiƒAx÷á9è$àšñç /à‡‘ˆôøV9½^2ˆúEýQQ«¨¿VÔ¿€wtz|±œbÉЯ§_ßѯoí×7öë„›P:hÉÑ?ÑODôDôWGôc}užÞ ÐãGäôÛ’8Kÿ÷YúWgé¿a–þªYú gé}³ôð ÷ôn^?¯ÙoÜeÜiDj(îÛ©ßµÚN<]“Ú ‚{&-Äâõ¾i| Ù×ÇžÚlø:Ë.à-(J‘üjTóM8%çWâ”ÜÅx2 mo¹² ã-ÇŽ‹PBî\3ž>­ ãç mjœž³T$¯o¹ º«Æã¯ m&F „æJ”–»(-“ûgråø@Èû`¡ÓÑ ŒÇ…Ò¶ ïN&Ÿ'&h9‘˜PAöqt‚zb\ø ™äÞKž'¼Û2K8#üxà˜ðbòbáÙ¸üÀc…çÈèèQœÂwKZáûÉÛ„‡’7 ßm‘»HËãÝ> g»£Ð¸_¸ †Ù˜˜À‹Ç…KÓd­pŒ¸&Þ',ƒæ»%£ˆg……É ó“— óÊ3õä¬'ù¬¼¿Iú6ЖôÍ-¯ MØÉ¸# uåÉkòöjZf 1س_¨¨ü0%–ª…E+ÙóÙEl–Ͱ)6ÄY/ëa­*³ŠZ§Ò¨T*¥ŠQܪ¬Ó¿‘bDX•É” I¹ÌQ$¥ÊºÂ* D‹|UÄ·ØÇZ­æS®«ðÉÈLûªŸ§x{ßÂÁâãž¡b-)L{†úŠòÑÙüþ¤³pJ²!¨ûðg äv_ahÈÙWœÝ?8?í\=«G‹éüŠÒ(ôËã (4€ÚüT‡ªGQ2ˆl½LvS™, £Yd„ìJÊdIê˜Lö:!Û»-ÚYØÊ$ŠÚ&“lS$ ^^y -ìM&e*M§äu§4Ey > endobj 14 0 obj [ 333 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 444 500 444 500 444 333 500 500 278 722 722 278 778 500 500 722 500 333 389 278 500 500 722 500 500 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 722 556 ] endobj 6 0 obj << /Type /Font /Subtype /TrueType /BaseFont /DGYEUN+Times-Roman /FontDescriptor 13 0 R /Widths 14 0 R /FirstChar 45 /LastChar 222 /Encoding /MacRomanEncoding >> endobj 15 0 obj << /Author (\(gwking\) Gary King) /Creator (libdotneato version 1.12 \(v7\) \(Mon Apr 26, 2004\)) /CreationDate (D:20051109162732-05'00') /ModDate (D:20051109162732-05'00') /Producer (Mac OS X 10.4.3 Quartz PDFContext) /Title (G) >> endobj xref 0 16 0000000000 00000 n 0000002213 00000 n 0000000022 00000 n 0000002329 00000 n 0000002193 00000 n 0000003253 00000 n 0000013734 00000 n 0000003288 00000 n 0000002427 00000 n 0000003234 00000 n 0000003383 00000 n 0000003433 00000 n 0000012752 00000 n 0000012773 00000 n 0000013002 00000 n 0000013910 00000 n trailer << /Size 16 /Root 10 0 R /Info 15 0 R /ID [ <22c5e99fb868d858b3af52338bad60e8> <22c5e99fb868d858b3af52338bad60e8> ] >> startxref 14159 %%EOF cl-containers-20170403-git/website/source/index.md000066400000000000000000000127471306646076300217170ustar00rootroot00000000000000{include resources/header.md} {set-property title "CL-Containers"}
### What it is Common Lisp ships with a set of powerful built in data structures including the venerable list, full featured arrays, and hash-tables. CL-containers enhances and builds on these structures in two ways: 1. By adding containers that are not available in native Lisp (for example: binary search trees, red-black trees, sparse arrays and so on). 2. By providing a standard interface so that they are simpler to use and so that changing design decisions becomes significantly easier. Here is a slightly crazy picture of the class hierarchy for [containers][8] and for [generators. These are PDFs.][9] [8]: images/containers.pdf [9]: images/iterators.pdf {remark [TINAA][10] documentation for CL-Containers is [available][11]. [10]: http://common-lisp.net/project/tinaa/ [11]: http://common-lisp.net/project/cl-containers/documentation/ } {anchor mailing-lists} ### Mailing Lists * [cl-containers-devel][13]: A list for questions, patches, bug reports, and so on; It's for everything other than announcements. [13]: http://common-lisp.net/cgi-bin/mailman/listinfo/cl-containers-devel {anchor downloads} ### Where is it metabang.com is switching from [darcs][] to [git][] for source control; the current cl-containers repository is on [github][github-cl-containers] and you can clone it using: git clone git://github.com/gwkkwg/cl-containers (note that you'll also need to get [metatilities-base][] and [Moptilities][] to get CL-Containers to work). git clone git://github.com/gwkkwg/cl-containers CL-Containers (and friends) should also be [ASDF installable][18]. Its CLiki home is right [where][19] you'd expect. [18]: http://www.cliki.net/asdf-install [19]: http://www.cliki.net/cl-containers There's also a handy [gzipped tar file][20]. [20]: http://common-lisp.net/project/cl-containers/cl-containers_latest.tar.gz {anchor news} ### What is happening 21 December 2010 Moved to git. Minor cleanup. Absolutely nothing exciting. sigh. 24 October 2007 Lots of little updates between then and now. 25 Nov 2005 Wrote a mini tutorial and published it on [unCLog][22]. [22]: http://www.metabang.com/unclog/publisha/atinybit.html 14 Nov 2005 Added links, tarball, etc. 10 Nov 2005 Small patches and corrections; links to the mailing list. Nothing exciting 4 Nov 2005 OK. I changed my mind aboust waiting for ASDF. CL-Containers is ready for a release. Things are pretty weak-around-the-knees however, so the release party planned on Carnival Cruise Lines has been canceled. Sorry. Today, I hope to add CLiki pages for CL-Containers and two other bits of code it relies on: Metatilities and Moptilities. I'll also finish with the darcs repositories, and have things ASDF installable. If I'm lucky, it'll actually work! 6 Oct 2005 I've decided to get cl-containers out without worrying about ASDF. This means I should be able to stick what's needed up on the web site by the end of this week (oh, oh, I've almost made a commitment). This includes: * cl-containers * metatilities (everyone needs their own set of matching utilities) * moptilities (everyone needs their own MOP layer too) * generic-load-utilities Most of this will be released using the MIT license although some of the code comes from long ago and far away and has it's own (quite unrestrictive) license. Once I've released, lots of good stuff will remain to do (asdf, testing, making sure it's platform compliant, etc). As always, stay tuned. 5 Oct 2005 I've got most of cl-containers under [darcs][23] now and split away from various unneccesary dependencies of the rest of my code. The next steps are: [23]: http://www.darcs.org/ * Switching completely to asdf * Adding license information (cl-containers will be released under the MIT license) * Getting basic documentation ready * Making the source available If things go moderately then "real soon now" may actually occur "real soon". Thanks for your patience. 29 July 2005 I'm in the process of converting cl-containers from a home grown defsystem to ASDF, of cleaning up some unnecessary dependencies and of trying to create a bit of documentation. I hope to have cl-containers up in some form real soon now. You can drop me e-mail if you're interested, would like to help or want to be notified when the code actually appears up here!
{include resources/footer.md} [25]: http://common-lisp.net/project/cl-containers/shared/buttons/xhtml.gif (valid xhtml button) [26]: http://validator.w3.org/check/referer (xhtml1.1) [27]: http://common-lisp.net/project/cl-containers/shared/buttons/hacker.png (hacker emblem) [28]: http://www.catb.org/hacker-emblem/ (hacker) [29]: http://common-lisp.net/project/cl-containers/shared/buttons/lml2-powered.png (lml2 powered) [30]: http://lml2.b9.com/ (lml2 powered) [31]: http://common-lisp.net/project/cl-containers/shared/buttons/lambda-lisp.png (ALU emblem) [32]: http://www.lisp.org/ (Association of Lisp Users) [33]: http://common-lisp.net/project/cl-containers/shared/buttons/lisp-lizard.png (Common-Lisp.net) [34]: http://common-lisp.net/ (Common-Lisp.net) cl-containers-20170403-git/website/source/resources/000077500000000000000000000000001306646076300222655ustar00rootroot00000000000000cl-containers-20170403-git/website/source/resources/footer.md000066400000000000000000000026061306646076300241110ustar00rootroot00000000000000 cl-containers-20170403-git/website/source/resources/header.md000066400000000000000000000013201306646076300240330ustar00rootroot00000000000000{include shared-links.md} {set-property html yes} {set-property style-sheet "http://common-lisp.net/project/cl-containers/shared/style-200.css"} {set-property author "Gary Warren King"} [devel-list]: http://common-lisp.net/cgi-bin/mailman/listinfo/metatilities-base-devel [cliki-home]: http://www.cliki.net/metatilities-base [tarball]: http://common-lisp.net/project/metatilities-base/metatilities-base.tar.gz
## CL-Containers #### More fun than kissing bunnies!
cl-containers-20170403-git/website/source/resources/ug-footer.md000066400000000000000000000027171306646076300245250ustar00rootroot00000000000000 cl-containers-20170403-git/website/source/resources/ug-header.md000066400000000000000000000010011306646076300244400ustar00rootroot00000000000000{set-property html yes} {set-property style-sheets "http://common-lisp.net/project/cl-containers/shared/style-200.css" "user-guide.css"} {set-property author "Gary Warren King"} {include shared-links.md}
## CL-Containers #### More fun than kissing bunnies!
cl-containers-20170403-git/website/source/resources/user-guide.css000066400000000000000000000054721306646076300250600ustar00rootroot00000000000000/* @group toc */ .table-of-contents { font-size: 90%; margin-bottom: 1em; padding-bottom: 1em; } .table-of-contents h2, h3, h4 { padding-top: 0; padding-bottom: 0; margin-top: 0; margin-bottom: 1px; } .table-of-contents h2 { font-size: inherit; font-style: inherit; position: relative; left: 2em; } .table-of-contents h3 { font-size: inherit; font-style: inherit; position: relative; left: 4em; } .table-of-contents h4 { font-size: inherit; font-style: inherit; position: relative; left: 6em; } .table-of-contents h5 { font-size: inherit; font-style: inherit; position: relative; left: 8px; } /* @end */ /* @group anchors */ a.none { text-decoration: none; color:black } a.none:visited { text-decoration: none; color:black } a.none:active { text-decoration: none; color:black } a.none:hover { text-decoration: none; color:black } a { text-decoration: none; } a:visited { text-decoration: none; } a:active { text-decoration: underline; } a:hover { text-decoration: underline; } /* @end */ /* @group Reference */ .reference { padding-bottom: 1em; } .reference h3 { margin-top: 2em; font-size: 110%; border-bottom: 1px solid silver; border-top: 4px solid gray; padding-top: 3px; padding-bottom: 3px; } /* @end */ body { font-family: Georgia, "Times New Roman", Times, serif; margin-right: 0.5in; margin-left: 0.5in; margin-bottom: 0.25px; } h1, h2, h3, h4 { font-family: "Lucida Grande", Lucida, Verdana, sans-serif; } h2 { } h3, h4 { font-style: italic; } .hidden { visibility: hidden; } .documentation { margin-right: 1em; margin-left: 1em; } .function { } .documentation.header { display: block; position: relative; border-top-style: solid; border-top-width: 1pt; padding-top: 4px; margin-top: 2em; } .documentation.contents { top: 10px; position: relative; } .documentation-name { font-weight: bold; float: left; padding-right: 10px; width: 125px; } .documentation-kind { float: right; font-style: italic; color: gray; padding-left: 10px; } .documentation-arguments { float: left; width: 350px; font-style: italic; } .documentation p { clear: both; margin-right: 1em; margin-left: 1em; } pre { background-color: #ffc8ff; overflow: auto; padding-bottom: 5px; margin-right: 1cm; margin-left: 1cm; font-family: "Courier New", Courier, mono; } .note { border: 2px inset gray; padding: 0.5em; margin-right: 2em; margin-left: 2em; } #footer { margin-top: 2em; border-top-style: inset; border-top-width: 2px; } #navigation li { display: inline; border-right-style: dotted; border-right-width: 1px; border-left-style: dotted; border-left-width: 1px; border-collapse: collapse; padding-right: 0.25em; padding-left: 0.25em; margin-right: 1em; } #navigation { text-align: center; } #timestamp { font-size: 80%; text-align: right; } cl-containers-20170403-git/website/source/shared/000077500000000000000000000000001306646076300215215ustar00rootroot00000000000000cl-containers-20170403-git/website/source/shared/buttons/000077500000000000000000000000001306646076300232175ustar00rootroot00000000000000cl-containers-20170403-git/website/source/shared/buttons/allegro-2.png000066400000000000000000000004151306646076300255110ustar00rootroot00000000000000‰PNG  IHDRPD¸½6PLTEÿÿÿ^‡µ‡§ÈN‘¬®°ÊÎÒöùû¯ÂÖ;j£ÎÝêÞßÞPPPÚäîéîòfff‰Žyÿÿ€@L¬š÷’IDATxœ¬”ÑCD'™x5ÛÿÿÙ»ºQWË}¨2!äÔd¡"U øê’—›ô‡f K)‰@‘4ËLè¸h¦E¿y4cÂh¢éˆ^l aT±0ÂÌ ¡‘ðH-¶¼KØg µÛ2&Ó=Ûþ ýïaµ®$ w‚G»ÞHž¿å¡¶Äñosÿÿ­r8x~VihIEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/allegro.png000066400000000000000000000004241306646076300253520ustar00rootroot00000000000000‰PNG  IHDRPD¸½3PLTEÿÿÿ^‡µ‡§ÈN‘¬®°ÊÎÒöùû¯ÂÖ;j£ÎÝêÞßÞPPPÚäîéîòfff‰Žyÿÿ{ñ‘œIDATxœ¬”A Å DBÿ¢”NîÚZc±ù]Ô åe"AìÉÂŽ»ˆI9 =äâ=΋;QÍtXp°ÎumÁöglW\æüU€R”ÿ@\ãú@.ÍŒwv‡!°•Ì ä‘Cþ ‘£’áïÞ¢7lRæõá½”Õ‡¤ñD°®9}X‘‚9`×™bú·9ÿÿ—ç+(Å>ó§IEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/allegroserve.png000066400000000000000000000015541306646076300264240ustar00rootroot00000000000000‰PNG  IHDRZ(Œlðû0PLTEÿÿÿàæøÝÎ=aŬŸld,)ƹ š®ëª­?_Œ‚j|n÷ä2Ìÿ7^÷IDATxœtÔ½kÛ@àZ4™,4¤!4ŠE³4Ðz0n2¸K¦!I‡ÖB³\«›' ÉTHþP2µÝLæ–ÖƒcÇsتâ£Ë÷í«cY²nÐ×=:Ýï=Iç,º™sÌ&§Æü1k½£nÚ:3Ô¼>¥=NDIçb¦ 9ÎäxBV ‘˜Á‘–®éírÁäSˆ)‚¨ECÐí㜢³–¤<ñípS0Þäµ¢ h±XKjq1MLÑEã?¥áÒ>òŠ$òDÒô¢¢·æ–$2¦­ &Ñ}ÚÊ Z„c"—ÀñtƒÌk‰6AÅ1&É$þ”ý&nþJ‘u4x¿ÎÕpóêG¤Vt¿.Uœ¹‚êÉÏÄôG§iÖåçþ®›£“ïÇam½¤›æG=ÝïÑ+¯0á>„Øú È5ñ|xhGµA~ScGoÂÈ‹é´3§ãú÷l+9ÇœðNe¶îøbŽ ß¡³çÁ~¹þ‡®ÌÔëØíéòkZŸUïÞöÚ1wá…·)]ë/ɶ$-€ 5ÿð¿(½»kwÙ1zH)=éŒÓ‡1m¼Ã…¬§z‡*òrP»•V©­ûR¡ô,ôÝíýô^š“’ž»Šunجâm HÃmÁʧN†ûÞ,ã¨ñáÍš;%èÆÁ’i= ÝLÓÖx« ý8ÀëÀÌIÆ+Ü@4*@ö`/:—ÍÙòôý”.xZ¥%¨YT.lS[w+uûê-mú¿ÖñßÇk–½œ%ûh×Écá: "5¶­ªïŒ^m-}*³“öÂrX擄¦^¥P7ª[MuéhåæòéÉiX»½ky³‡¥ú|y½rÀ:ÚŠ{{ŠKPS–:e™Ò ‡î®[áSP§KlqVJ·mgZè?|'`T=;Åßn„†çvÎôd¹‰ºýJäLÀÚøšI>Ä[zãÕ†·åH_wf/peðÿÿ—Øp˜ÎðlIEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/cl-markdown.png000066400000000000000000000004361306646076300261460ustar00rootroot00000000000000‰PNG  IHDRPü«ßØåIDATxœí—±ƒ @CÏOò›ÈܥЅ9ÿä?Ù!=ŽK‚¢Wõ®ø¦CHuÞ{艈èê0N–Ž›FÎ4Åé@^Ï7<®ãlî„fš´\*Mxز~4KAؘ~<¹Ä®0§·š¤€ç³Æb ¥Rk²eÍÆôcfUË3c'ìpœiÚÚÉ8 ÑÌjµ*Íô¨ÝèETϰȶ1y7WfÕfµ2í,{kmZ[·÷2:&¡»€ßj¹§ÀZÓŒóÞQ'÷0"Þ×Ò¿óý´ÜqDØfÎÄõö·ôùß›òÀ WIEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/cssvalid.gif000066400000000000000000000021101306646076300255100ustar00rootroot00000000000000GIF89aP÷^‡µ‡§ÈN‘¬®°ÊÎÒöùû¯ÂÖ;j£ÎÝêÞßÞPPPÚäîéîòfffÿÿÿ‰Žy!ù,PÿH° Áƒ*\Èp ƒ‡#JœH±¢Å‹3 ÌÈñÇ CŠI²äH0à€A€*˜Y€Áƒ @4ɳ§O‘(@ p ¥L  à@ &Øù³ªU )‘ P@QV0@ Ù:†Tû‘ê·W{…؃€ ©ƒˆÒGÃoׯ½:W0X¢"p) © E|˜óbž.Pì 0EMQsb×m?ËÍš€}OëøaÌžßrv W6ÉЩ e S9ÑP@ ¸ñë‡i#  Ò€ê|%h `À`¶ØÓ¿ÕžZbiü–¨^=rŽøóë×ß°¿ÿÿ;cl-containers-20170403-git/website/source/shared/buttons/hacker.png000066400000000000000000000006171306646076300251660ustar00rootroot00000000000000‰PNG  IHDRPD¸½fPLTEfffÿÿÿåååñññðððÛÛÛÁÁÁjjj‰Žyþþþæææ 666555ÐÐÐÔÔÔ“““ÓÓÓççç444!!!ÚÚÚ   ³³³ÑÑÑ´´´¡¡¡ŽŽŽxxxÝÝÝeŸ`HbKGDˆH pHYs  ÒÝ~ütIMEÓ &/lÛ8¯IDATxœ­”ë …Ç»”U&¨S7{ÿ—œYÑ¢¦'ýC _O !ËÈÅHõæeU ÎsŸiþPä²ÅVtÀ*: ²ÛkÓɃˆ€lÆ/XȬÛо9£Úr| ÕÒ@XÅÀ‡•p8ä¿ux<ýà0ìÏ—ÎhsÆí ãIÆ3L¶|ÃiP¨† -Í-;ÄñþGDGœíëªÖÍ4@"Ñÿ5 o÷ö„ôIEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/lambda-lisp.png000066400000000000000000000003251306646076300261120ustar00rootroot00000000000000‰PNG  IHDRP§  PLTE}fff‰Žyÿÿÿð$‚H pHYs  šœtIMEÔ  T\IDATxÚcÅêÿc€¿  `µ ¬ 2À"Èc€E*¸nõê_ÿà‚<0Áu«^c ®~…Pi \µëºàú×ë_!À´Ÿá'aú«ß±…Ρ\Ø«“IEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/lisp-lizard.png000066400000000000000000000030431306646076300261570ustar00rootroot00000000000000‰PNG  IHDRPü«ßØtEXtSoftwareGraphicConverter5]HîÅIDATxœÌ–{LSWÇùsQgæPç˜3î/cC䑉(ê¦[2§ÃÁ­ ñ•‡ 8E¨‰ ,ÒR(-H¶…–7åe˱-R R|@Ÿ·÷qvî­cjŠÓm¹½½÷朓óù}¿çwŽËþw/Jù‚7í"”bÎ`rò£Nœ)).yEKøo3ãa' ÀØ£I;px'Ã'ê"€mªÞÚf%l‰áT~ÃQ%^8ý,«kþ%§à$ƒ™ÊPvÞƒ}á€ÀNæ°K¢ËÛ¸¦aôñ%ŠŽ; Ù f“²§«©µEÿ`f¡«o˜+ª—·h D•ã&¦†øþ£Ø_„Žg Ãà€§Îs•#]Q癌OÀaŸe`¨Ñ­nMYMËm­¾¤¬<—]È‘e7ôÜìmVŠØføµ‡Ï¤ËÌOËf &Ÿ1‘Ì/¨ú<­Éd’ÖÝJÉâœ-È55KevÄDzg»ýoÀè‰ ôúÇ›vÇ6é*¦lUSM¢6v\æ-ÚP»T¥T7´+cÒ®0¯3ËåRJ^ G’G¨ý¨®K=:ôÀ 3!lhã·”\/«&=c·QfüM~éËó¯Ó¾ÎŒ’‹”Z¸`[xÊšÀã¢vá„¥IÔÄ<”ÞÑ_3ôTÁäU4÷öÚ8ÁÎ?{-ÏŒ#‘)œ 0íÐÃ\¾,¿¢¤®—£ÐðkTåE’â$æoÂ:~DÚÍ(\íŽ4Áä èüŠ–N™§ ¨Y™PÅŽ3òæzïþÈÓ?…}Ygl6*»ÆK[ÅE™ €LAA€w·_CΛ¬c8ôm§V{‘Ó7²G¬Šòv=õôŽÈèzbRö¯b[m¨TW!¤Ã§¨¼ÂôâÎjÖ¿Px&ÁgÆi6–Ø7e }¦{ý±ãHLšªDc¨)®0X¹•*qAUëi]óÄÓ'å X\™ªâµ±cBz4=k©×þ9+ƒ?ô:äê½o¾{€›ÏÁÓ…Y9¥EF JAâ@Ps¢ï?~a(Læô\bí}÷\=B“ óãOÍù×=xõÑYÂ2¥ZÓ÷Ðømx²ëºÃ+¶ì KHÉÈc[¨r0 ¶À7~i¡Î¤çkÔ%s¸Úˆ¡kè‹¿Üîºv÷g_xß#ü=Uþ{ã.0Ê›‹»'äãxóc¤Öh«ÑK¥·%ñ¹ÙkvF¸y†¸yî9w &2{ÀÒØÑ½Â'¸H¦|hAQéÃãyŽÍ 'l`–÷aÜNê gƒØ «ëïv{oOXîöñÚ§~'ÝÖXä2Ïë «ïŸàÈ€èÈФäÇNûìŠ^ºn×Oÿ…kƒÜ6Ñ ¥õ$«½eÌj_¹õà2¿qYWywôšuwܷЃŽ0¥nVQÔ ,V²X[u”xŠØ8Mmù‚òûCjíVZì’õ!‹6Òæ¯ [àúm7mžmÉæˆ%>»öÄ0îJ;œ´+ ÖªÖž/¾?²lþ°¸L)ºQ7fø12Ù}gä®Ì2ižU`gAÙÏ÷L+œ,Ü2¹ç6úb¿¨¥ë÷-ÚL_¾>Ä'ŸÉïÒ ;| 0rÈ#EΓ*„µÊËœbÅ­S ÖÀØ+å!x¶ùŽžáš“š-”+~ïë|l´¼üöâã[펣Š’‡hVûĤuolÆ'¾a¾]Ú‘î¾Á‹9<'IË"&ã$$çݬ†_útC[ÃÄr4¼ô3z_;À•«Ò®]¿šÏcKª[U`øÝ ±D˜~éÊ×þ{¯²X"‰øõ;J$âàÉGN¦þmË?ÿÿæyuõ‹îIEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/lml2-powered.png000066400000000000000000000004361306646076300262410ustar00rootroot00000000000000‰PNG  IHDRPü«ßØåIDATxœå—1Ã0Eq峚9K† C—ΜÖ¨…¢4J*ùMØ!?þÆJi­ÁHT ¢«Ë8 D¬,‡¯Þ©?ž÷×ÝÍ<-p»ºŒ³Np5ãN]Û[%ö9ç‚íÚä<)3ó´øØ¼è×IÁ–'ª<þ‹¬"} D€©uu¨ÓÒM.˜ÕÆšùQÜùÌ~nÇB§Ää‚!So¬°»cû ßîXyEð–í29[ޱAêÖÎdz“ç*““Z@SZkD4È=ŒˆÃ]Kà ~Ÿá ÿ‚é.ÿ@íoéM”¦€¡|ssIEND®B`‚cl-containers-20170403-git/website/source/shared/buttons/xhtml.gif000066400000000000000000000005271306646076300250460ustar00rootroot00000000000000GIF89aP³^‡µ‡§ÈN‘¬®°ÊÎÒöùû¯ÂÖ;j£ÎÝêÞßÞPPPÚäîéîòfffÿÿÿ‰Žy,Pþ°ÉI«½8ëͧû`(Ždižh*¥ìã¾p,Ït=;ëg,:@`X`< ÈÆl:e¸(pè ‹Ã! 8 Ibù,›¡9¬€PT ‚ÝÁ@hÐÊÌñâ?ü€z}.~P†ˆ…im  ]!1|†€„…ž 4ŠŠŒpT¬>c#P{dƒ…ƒ¤7hR °p\Æ$½Ÿ¹Î¸¸§¡Ó}iÇ•ÅJp™ ³ˆÍÑÓä·}z£¦ÖU BïT˜ ègüNQ"’t@v€’  Ø$¨ŸC&ÿD0QAáD<ÜX#"‹ CŠŒÒ¡¤É“()D;cl-containers-20170403-git/website/source/shared/lambda.png000066400000000000000000000011111306646076300234410ustar00rootroot00000000000000‰PNG  IHDRísO/ pHYs.#.#x¥?vûIDATxœbøÿÿ?ÿÿAøÛׯ\ë×®*)-íÞ¼u›÷—/_¹ÿþýËSƒ¬Æ E úׯ_¬Î5ÌÍΚ’’–>ëò•k:þþeFV¢‘٠Ȧ‚¾ÿƹtÑ‚Xccã3S¦ÏÌüöí;'º­(.@wÈ«—/éx{ºo‹O\øèÉS¼`sÞ‡÷ïjªÊ[-,­ŽïÝÐñÏŸ?̽€lúo`XlÚ°ÖßèŽî¾ÒÏ_¾òüýû‰h€ð[7TƒüÖ‡„E®º{ïI.áO?ò57ÔÕ›˜žÙ²m§×ïß¿Yåñ"ˆ~÷öPOg{™Š²òºÆ–ú?ñc5W ®_·&°¶¦¦ÙÙÑaŸ_À¦ë7o©#{g:i^½ryXCccý‘£G­A®022>»zí†`PBÃëæËGæççMܳo¿Ó·oß8Øgomiq¬´¼ªóí»÷B.@¶yÙâE1 ññ V®^úùóžÿþ2=}òX:)!v¾«»çÎ —®èÁ4£¸àÓÇ| ÍÁAAk§“ïÛwï„` ¿]1sÚäLCCÃs —,‹ùñó';Š TvñüYƒ˜¨¨¥ M-uOž>“Fq&PþÜ™SÆ~¾Þ› ŠK{_¼|-ŽìÿÿdüŒ¾WîÉIEND®B`‚cl-containers-20170403-git/website/source/shared/lisp-flag-with-hand.gif000066400000000000000000000044461306646076300257570ustar00rootroot00000000000000GIF89a@9÷ 9-'%169" !%#39#"""$)&+++!!023/333;;;!W !O1;^-,r-0j5=g>m<=t=?@@=AYA#L(X/l9t> x?!OK'Fm?eD#ix?wm9CCCLLLSSS[[[\ZrHyBWB]xWbbbkkk`cusss|||87‘EG¬XjœLGËOJÔPQÆSRÔWXÖ[\Ö]d×`_×acØckØjnÚfyÊesÙjtÚm~Ój{ÙwzÜADH†LKŒLN‹PMNT‡LUYQ”QU›S\’`Y¡V\£Y`”ch™kpžsa¨\j¢_g±_i³co¼du¡xx£{p»g}¼nt³pyÈm~§mƒÚp‡×p„ÛrŠÜ}„ÞyŽÝu“Ýz•Þ{œß–à}£ß~¡àˆH&ŒJ&–P)ªZ.³_1ªu=µ`2¸b3œz@Ëk8Ño:Òp:Ýu=àw>ƒÈzÓr„Ðx†Ùs‰Ûv‰Ú{æ~ƒƒƒŠŠŠ‘š’““›››‹¯Ž¯•¶—¢¢¢¬¬¬´´´¼¼¼„ƒÞ”àŒ”áˆá–”ã•›ä‚¤àƒ¬àŒ¥âŠªâ†±á‰¶â”¦ãœ«å•²ä’¸ä›½å¦©ç¤«è¢½å£¼è¨¶é³»ì´»éŒÊ„’Ö…”ê˜ï„›ëŠšò†Ÿð¦Á¨ªÃ¬ªçž¡óŽ£ò‘«ò›³ë§´ó¦ºñ­½ñ±Áæ¦Æé«Ãê¬Êê´Ãì²Ëì¼ÌìµÒì¾ÑíÆë½ÀòµÄñ¹Èñ¿ÃÃÃËËËÂÓÃÈ×ÉËÙÌÕÕÕÐÜÐÛÛÛÃÅðÇÉñÄØëÍÓìÌÚìÃÔðÃÚðÈÕòÍÜòÑÖçÕ×ôÔÙôÛÝöÊñÁØáØÛãîßèïÖãõÛåößê÷áß÷äääåêåìììââøèêðêìùæðùîðñëñúññññóûõøüþþþÌÌÌ!ùõ,@9þé H° At’p¸¨a@€,¸H4IÁ‹3j4 G A @2@HIÛȲeAIBV¨‰ºx8q¢[Ö¨†‘,(¹ŠqÒO)¥å\Ê4'´D@ZXF´*º [Pjʵ+L4,Ve)i “ºªåúN„ŽÅ8ï€8Öêåš®HEs Îswë^œŠ\Ö[@Àça¥ íÝáx“BÜ¡p™ÙÛé®pór¼wþL°¶ôe®Ò¢>žk—BéËê²³Aˆ6—B‰BÅŠ˜5q¯qJ#pUIp•šŽ·L :˜|[‚d š5˜:þÁ‘ã©”±q8™9¤:ÙŦqÐtȪyÜÑ,YC®ÜøT¾€Š/×Ä ˆÕVyM‡S}ìAëxcÄÞ­!6r´#<Å|ÂI)êÐà˜K“@:Æ#M˜ƒôœ‚DwhÄAÏ*ÀÐ3L0îг 'œx sдôQZ-6BB ø  =lÜèÝ(ôŒB =D‚’sÌáÉ"´ÀRŠ,´ˆj0ðÃ4í !†h3©ÐcÌ'C '£ÀÑITÌl“ª£!Ï4Btç7í¼Ç6ôÀ ("~IÌ;ZFÒ ¥&u#‚ôh)Žþðlc©¿ÀC9 pbŽ@Ø´‘A „Cs§îPG ô` =F¼ºDô3+'Ÿ£''ó`ƒM´iÐHFI×"„x\ðC7ßDº„%K„B(ÂÀ3 ‘Ÿ¸cN)ô¤Ç7óÄq„ ¡cªš/ƘÃóÈÃÎ<rÊâ˜x¬õ"Ë kÔ½0o fz׋L"– ‘ ± thõÒ #hظ@­…Õ:Q“„$¦pÈIÀE #³UQÇ$ñ D€~ ^ ˆ­6 ;cl-containers-20170403-git/website/source/shared/metabang-2 copy.png000066400000000000000000000056231306646076300251050ustar00rootroot00000000000000‰PNG  IHDR K÷LŒl ZIDATxœì] ÔUUÞ‘(¦«RB0¨tÉÒ…¨K,AÍÀÃ´È úµœQÌÍy©d€‚RIY9eN8,• Ì¡R[).G£TJ ÅÐÎçy·ÿ¼óïsï9ûÞÿ¿®÷ïo­o1¼w¾³ï½ûžqïóˆ …B¡P( …"1üºá݆ÿ2|Íp‘á†=j´KÑMpáû^^£]Šn€Ñv¾Œ_­Í:EËãD*vÀéµY§hyü’ŠðÆÚ¬S´ÿ¨a›áã9†¼kxžáz9õ`Ëf¶áÛ9:à+dóP«Äþ†/2u½çÙ³¦q½„õŒkhºu,#ûÂÁ!p}Ù‡Ž0üÉvF^e¸‚Â÷òÃÝ…×’aHŽþÖ%µ?h^ŸóDïr>GOäàóy²!<>ÆMjŽÕeاäõõ3¼ÃÓ…ÈöÚɰ7Ù Ñføµ/°n›Xב†ïPÚ5f¼?¡lþßê”]jx›áM~V'^‹‹>9v’Šâ†Ïˆf‹‹ˆ†ý¯÷Zº·r z¿ñ¹ÛŸ@7´ñ ŠZBðÏ$ï’ÑÒ<ééaÝ*¯kBË÷{çZcZb¼p¾“K3Œ™døµ·nþø÷/Ο[êÕqeÎ÷‹ðwÆæÕR1ÌÒ®c}Âà"ôv¤üÖ Nºv„œòGLùG(½¼ÅÓ˜›Xþf§l^Ú!œ/ŽßS¸Dw‰ ­NÀdaÙ^bbãߟ)°g†£‡º6‰¸· øjD™¥Ž×õB ½èåŒhÆÙ‰zgtð– L´ëaFgÏ£¼²pàž åÿáMŠ(3Š:Ú ÂZ‰uû8ÎÓœY®±g¡ ­‡…ZÿZ¥§á—Évµ)èÍ耒%ˆqŒÎÙ‘e1&ù·Wöx Ù80ã-ezRG»—êv±+uœUÇŽå&2öÄ´œ®d´nj5a#|P‹'HRö¸iÿo"ËNaÊn“P7ZàÉÔq6»,¢l¦î¿&ÔÍáo$èœ~QhwBÖ/„ZM8ž–n-d´Ú:hIüYó=‘eý‰8“ìrÒæ na¸Ù‡1–ìxì»d‡þwÙ/¢þw½2÷EÚÍa€§µ’ìša,8ÜIh — ^É¡DÜéG' µng´vj-ót–D”ÊÔ_%w°aµW¦L7…Ö½œ³ÞÔuÉ6êx Û m9„Ñú¾P« §2ÂG µîd´¾$Ôòw-Ð%í|‡©ÿi²ëÈc†}Ù­²sÈæ± 8Ïð ÃkÉÎxñ"-$»8ŒuHÌr±;ô‰»ýõ²«"ÊA2‰óúãXp„ІñŒÖ·„ZM8ƒnjq3%©¾Äh-zr“[ ë—€¦.ÿ”î#4”¦PŽd´*Ùö7ÎAé>ì]Œ–4iÙï‚cÛÙ‰·U…¾Lý]qp‚;0ŽE î|¦¸ÌhI[Ó&Lg„÷jýÑ-Ôú'£Uä€÷3e¤ËpiF'Ö‡mCÌú³{…]ÆÓnÏ€±þ9ßçz·Á%êÈÑyª„NæRu¸ˆÑ#Ôâ‚,‹»–ß ë—€[’®©ú@À‚ð奢 ×-aƒ Qf½ Y¸TÈuc…Z+­¢(åIL„uÕLx2SlXZæŸÏ2!¢ ò…v¸¾"Ý®í."Fê€n"NFéZ‘?à]Qfc¦~05²GŠc˜º«Èû­§‰áIL?7¼*s”š›<§„N® êÐ#d”æ#ø{Áo•°e»b9æÛLݱQ“ßûI²p¡ÜVìõ¦l%Á™üpöT¦n¥qA b†uILL.$;aÊžÁ™½M©8 Ö'Zn<0^”Ó Gþfäµ­í” ä œS’¥Æ!åã-¼™)‰æpjŒ7òt0öÀnÅ3‘:p(lùa¼nÄ5ãD„U vfD^Ì^ú>p=¡|ë—PþÙÉ‘:¸‡þ/5"Î1u§ ÎôPѹÐYð)š\œ†€®Ùô˜ ã¦ÁAðƼLÍ«î\LÛYÞwàX,}Œl7° ¡›âîjø‰æ7=MíoãòF8Ö¿Ñø cÆ7ã ¼n,D_Fŧ½ƒˆ,ù ®Àõ¡{Ï;2#«kjD]hÍðìB©¯¸ê„R_á,#u¡kÆZê²ÙzÉÀA8NlÆfoy76 ¡Y”÷‹‹]?Ç®¼¤l°?5ÍÀކXAJáÒñP°XÉWL« tS˜AOiè£^,£EÃrHjæ!Öð#K|‹m¾íª2V¡P( …B¡P(>LÀáIXÆñvX19Ò’ä 1°dÃmÙâœÂ#j´KÑ €…ê¢Ý$ýÁjE§Yoþ!—±Ñ»&- .¼,įÔd£¢…‘÷5>õk•à @-beª EœóKòÈ‹æQ(Ä@dP‘†bŠÒ@¤b¹P6,Ï T/5ªG¡HÎÙF(bFqöä~K¡P( Eýøÿÿ$Û´Ëú)ÑIEND®B`‚cl-containers-20170403-git/website/source/shared/metabang-2-40.png000066400000000000000000000027331306646076300243720ustar00rootroot00000000000000‰PNG  IHDRU(I¶E¢IDATxœìZiŒE.%¸ ‚ñ@eÁE£xlÖ#ˆdÃ/ðH”E#òÃ+BYEIŒ‚·ñ fD‚üÀkñ6câã1BTT¼6Š'Dq¬ïuM¶^OwOïìd¾äûñ¦«ªkjª{ªzQ‰%Š‹æ÷̘O0Í×Þ#˜;,>—«GÀ™”ê'¹zTœAé ®ÏÕ£àxJõµ\=*FR:¨m¹zTÔP:¨­¹zTüEÕA½9_wŠvªêUùºS |HÕA½ _wŠ×©:¨“òuç¿C3sÕÿ4:(Ôñ±ŠG3‡©ßý™'0'3aîêÐÙ™LÉÑÄœÀÜ·70g1ç’é^ˆÐ©ena¾×ƒùvbŽ`ÅÜ+RgU5³÷¯#S"t2ÏgdÞÅüÝ2ôó4¥7•ù%¥Ë÷™‡G8Ú ²ÛÈÔ}‹˜‹™k™KÅðà>¹þdÞ˼ƒyŸÜÇõ½ã˜1?cnP÷÷óà _ï¤ê{ô> dâÓ–ð2æ:æKÌ[„pä;Gà[äú:¹‘䦰ÿ¹_C“ÉlÈn$³B4ýO‘ x?k Ùü#¥¤æßÌÝ,½Ì_˜ó•_xhOŠÎ3_k•ýmâ£X÷[}MfYØÄü\ɵ‰¾É2‹=ó"Óp„ös´Gf ¹ëÁidVQâÇ£Ì1b«'JûY: EöRǹÑJnfÄœ•}+QÓ™ ê\%·‹56Míãœ}•Ó{  7’Y%ºÂЦä¢jT].„–õ…Jî €ÜÕäêlŠËŒ†*'uCoæ<2åØr2%ÝteËWÂ}¨kuD%ÃÔ‹”܈€Ü<òUgû¸ç¨S6#uÎ"Smàã]“º~ª²5(ÃÆf2•M–S\PuY12 §_|}­±ñjìŠX-4P÷ ²ûû»”®š”­¬ Ä'”±N®¢¸ ÎRr£rIéÕéC«»EÆÑõuRA5kÛL†ùâÙÊÖÐ [¯0ߌuòŠ ª^þu¹äÅ×áOjPðî€d¹+{j•þ%}`œ’ã_©ÆëÕu×Ã^M¦ËÄ2ýsÌrZ¤ä\]W½G» n\ûXÉwæÞ¹÷ÿÝs{ç9ç÷u¾Þÿ<óÌ3¿;Ë3ÏLŒsÎv27À¡l!sÊ27À¡l!sÊ27À!¿ø÷ßÙ´iÓØ)§œÂöß¶ß~û±“N:‰=óÌ3ìŸþÑ–ÉÜh‡üâúë¯g&¹ä’K´e27Ú!Ÿ˜?¾‘lžÌœ93T.sÃò‰»îº+–pýúõ •ËÜp‡|âÒK/5ñŒ{èØ±#§å27Ü!ŸÐŽS´oßž+"Ëen¸C>qà 7ÄNl¸"²\æ†;äÇ%œ %'âç=öX$Ù€aÆq"Žpé0cÆŒXÂ?žq„sH‡… Ænúô霈#œC:¬Y³&v ·`ÁNÄÎ!¾ÿþûX­^½š+"Ëen¸C>ÃùòåËGnË–-\Y.sÃò‹ªU« 'ÈÈ)¹"²LæF;ä‡~¸‘pUªTáDd™ÌvÈ/N>ùd#á9Y&s£ò‹³Ï>ÛH8AFND–ÉÜh‡ü¢{÷îF 2r"²LæF;ä·Þz«‘pW]u'"ËdntYÄsÏ=ÇŽ9æ¶xñâÌm)÷Þ{¯‘p·Ýv'"ËdntY"ô{챇ì¡þýûgnO!xòÉ'„3f '"ËdntYÂ_ýÅš4iâ÷ÐÕW_¹M…àÕW_5îé§ŸæDd+ÅŸþ9»øâ‹Ù³Ï>küÍgŸ}ÆÆÇÄPÊ®¼òJ6pà@6}út¶qãFëüþûïlùòåòšÙ€XÏž=™øRØo¼Á¾üòKy-­4½ ,`}úôa­ZµbGq;øàƒY›6mä(„)í+´øF•+®¸¢T ñ矲>ø€½üòËlüøñ²ÿ0ûí·EÑ¿dÉ#áDŸ%'ÜüÁî¸ã èÔ©Sàïÿý7›4i;òÈ#™IvÙevã7²_ýÕXÏ–-[Øu×]ÇvÛm7£È ïA³S¦L™ÂjÕªª«\¹r{pŒƒvÀ'iêyíµ×¤NUjÔ¨!?0A±¯¿þZ~Ü+W®dK—.eŸ~ú©ñ~gp£ªk×®lß}÷5ú²^½zlÖ¬Yù!Ÿp}ôQ2Âa¸¬[·n@Ûé§Ÿîÿ](”#­rÈ!2¥…Ö3gÎy‰6‰tëÖmÛ¶­ g}÷Ýw¬uëÖ½°·‘æÍ›Ç~úé'ùAø¨j×®-ƒè:F$u=òÈ#l×]w55GBÒ¬Y3ëzV¯^ÍÎ<óL¿lÍš5YÛ¶mY‡Œ}Õ»wïÔ>D˜Ú²~ýúÙ´„ƒƒÛ·o¯5‘eüÙž»ï¾{àoÉ*T¨`rªü]–GŒA€eÇÄtã?>õ‹‘ä°Ã èC3jªÁÈÖ²eK¿­6#->0Jj"ôÀ[+6Ë’§žzŠíµ×^ò÷½°œ¡þÁ‡Ò¨Q£€nŒºQÓ’Žô¹ß1£ÅCdÅŠÞÙsÏ=å…{ï½7»üòËåTñÍ7ßÈÑ üꫯػï¾ËÎ?ÿ|êP_n¹å¹~`­4vìX9… Ã1…@F ü;ì„9´òÒK/%vÐæÍ›Ù¡‡Ð3räHÝoC"ÚÉñœ£aAoºé&£içè|äI¥J•Øo¿ýf¬¾ºæšküßwÜqr‰bú=þ†‘O• .¸ 5á:è P›O¨ëô„Ã.êœsΉu’0oÚ´‰ŒðE‹ÑÊèXrÇŽ±¬ƒ»ï¾;¤çØcM<ÊuÖYõèÑ#–hª´k×N½g¬$Æ(JgÕ—búã⃒™±3gÎäXÜO:UÎb—'û6lˆl>^OP×_|ëOQ&àǪU«šú2ˆ'R~ˆå­RO8^òÅà]ÙÄâ^«ÈÔAƒ Ò¦c´ÄhçO„]¼qãÆ!=b­ií¬‡~8Ð ;¹ˆzMìש,®^쀩/Å‚ž‹ÜÔÜ(ñõb¯ vÙ6¾kÒ·oßnls°«§A?™lÖ*Á¨Ó Aƒ€ Zµj\L:EF‹o-áÄ”ªk\¤ˆé;¤gÀ€VŽÂ.¹råʺçž{‘ ðÖq^ýbÄŒ­¤¦¾¬S§N\sM"u¾ù曡]/Y‹Û‚Ñ“Ú#FF+?R`:¦„ÃÈmªß¨¨W¯^ƒ1ÝZ9ƒBÌó!¢h®Å6¸dÐsÑEY9 ëD*~ø¡ŽlÚòùzè!ºÛä5jÔˆ­KjwÆ ã|韣Ž:*ÐìN¹þã Ù£Î÷çûï¿ëÈ JR×e—]f´Á¨_?uRÿþý#`©§žú¢0¬'Õƒ‘BÙÕJ=-Z´°*O7 ¾}ûÊxѪU«$>þøc¾lÙ2&œÏfÏž-×S÷ÝwŸŒÒVmœØúÅÎ6àËæÍ›'n¿ì²UÙgŸ}dÌÎVŸŽpóæÍKl@.DK]ýúõ3ÚaT¤¼Žã;Iü»TNBÄžêzûí·S9ÁRU™š´eÖ­[§#KÀfØ%ƈ,'¦·Ø6`ͪ–‹švâ€Ñ›;„g°+Uâ‚V:W¤íX´hQ*[üñ?Fe´Ã¨hÈ!!E>ø`*'qÆ!]ï½÷^*]äT€‹)N›;¯b„ !¦Ô¯_Ÿ1B2c|çwÊ£§›o¾Y.¾q¬†°Ï…^È:wî,c“øp0Z#‹8 Â5:uâ[·nmWuíÚ5UûU ª ü+} «²õíYºti*[^yå•PßNž<Ùh‹QÑí·ßR¤™­ŒÒídᬈ¸Õe 2z ‰‚RÄÔ™ª-: ý±EÚÁ=zô(FýÖv`Ó$ˆ`\è®ôÙg³´?Lç¨<Špô ЦM›–ÊI8£F‘K²Ö T¦TkÂiNNÔuWR;â$TæÇ Õ¯{è¥hu!ëPŒÐdJÙ³qãÆT¶àdŠê"£e@ŸQ^/¤Šf̘‘ʨÓN;-D’ùóç§Òuà&&¦@Ú% Pl±ê_ãÊ%@@Žá°+÷|…Sô'B)8Á騱cÈž’@~b[~ùå—Dä5*BfD±‡W®)IÒîŠ1’”pšl›MKZ Õ#:Z¿)#¶ ~ŠDoÙ{£8¯þù矿CÊõaÚ "%ˆÒeT‚…35*-áZ´hÒõÎ;ï¤ÒU¥J•Ä„kÚ´i¨ yÙ§àÎŽ‚ wˆpb̉TÇúõëåɉ'Ü#|Ó·þÝ”Ýaƒ:uêøõâ%ª]F%H[)áš7oÒEFk]ä´ ÍN+*U½øâ‹! 2$²c’GgêÈ*$T~ÏÅì D‹i?µ-'œp‚JôÈv•àP»X„Ã,‚êš3gN*]$©ÐŠpº¶œ{œš°Œ.¦™J7øÕt®úõëËušæ·¾ €Oý±nݺԶ´k×ÎW¦ hÛÎK*átSÚìÙ³SéBTê‹äH]8`§e*V¬huBP àHŒnäÈ‘‘c¤Z‘÷=ä®”ü.TÇ AƒBþX»vmj[T®hŽ?íG2F "œzqÄÓEb5Öºè¦Äuiý€’ùRª„{àB„3ÝjJ‚.]º”b¹¡¤¤õë–Kiãp€z?µW¯^‘í2*A„½X„SçxO׬Y³Ré¢ODU¨P!²|¡lÚ,‰$xâ‰'B„S²\RÕtr*Xºð²ÊÙ¶ï•+W¦¶GM“ŠÛ •œwÞyE#œnÓ€T£¤º”4ŸÄ„CÊ5% 1•á0ÍQ»;wîœÊ—È2A v©Ô´âfº×ܹsSÛƒ[vžˆåCdý‰HRÌ8\Iâd"]ºˆ=2Š£èSr¬ ]Ÿ>}xÒÌaØòúë¯[ýލÝ5kÖTמ‰ GÂVRÄú–‹2Ò}ûö ÙL ù[¬mü‚‹Pžˆ+²?ŒJt‹s¤CÇu¬Õ«WéBJuR]4-ÇÓE2gåW¬Xá]y …Ú´iÃ?ùä“X“‡ 8ît`=‰»qe0ªè^‹TB#‰ ‡Ä/ÄzÑè dvÐKK^9¤OµmÛÌO8xƒ„ÍUB\uô„ôC6hÕ¾QÈKJ]”…ÍVº-Z¤Õ•dÁ‹ Á:±ÿ–r‹ŽANÈ…§‡¼8²ùaC‡µ&ˆnÝ„åH·cÇŽÝ8˜8q"3}÷ß¿ÖÈž8p ÌíÃ(,þÉžþyÿ<™;äæ–ÎRਠ9Ô`ÕªUÌšp8A®”溟ÿ'{AB£øêÅ6[&úiîœJ]Èž0aß¶m[,I~øáyCKs·RêjÖ¬™z4ë §\¹rZÒÑ L‚ä[²º¤GµjÕB\P¾6píµ×Ê Ž×ƒÖêÇ`º¢gj Ffô „V|©-‡Ìæ^xÁªmà'%5ö…ü\fÁ;Þ8„Œjذ¡Ì…Ò}y1›z@b¬ñ5«z°vÀ3îXÚèý‹˜²$âœ4eÊ^©R¥Ä¤«V­š ¶&!›×åÄêNáÈʤsذaQú|ð!ýo—â#nÙ²¥¶òüp—¤} 3®+–„e¢ ç%[bÅm{L¸­*œ„è±ø"ä%åÚŸîŠ *ª‘o\ô@pò裖Ãz«V­¸ÐÏ…äÍ%O½ØŒu¢æ|m8C…ãp.‹ø2à°O<Ñ· 19¬Ñ°¦°q¿¸Ìƒrq@æÅèÑ£uOV¨K:L×J»µõ¡.¼Íõ<€Ñ }g¸ŠÉá?„, W1å]‹Å‹Ë)XLµ14Ý3sæô™îÓ= „B!„B!„B!„B!„B!„B!„B!„B!† à=ÀàI`p;ð~`XÛ%D0_š9é]l—AE¾'éÄ:+”iusxÀ1o©³B)±¨›×ÔtL0RbÑ jÕ;)±¨›ÿ³®Î ¥Ä¢nž8æÉ:+”‹ºy<à)±Ò„XâEFJ,ê&DAC=)±¨›%–%CšAw'„¨›aÀ6Ч'v­uBò8ù ¼ Mvˆ€"—bÐWgeRb1)qíþ°”X EJ\ëðH‰ÅÀP4#'%;²Ä/bÞܼ©Û ©H‘%–Oüf_à*à@`v—ÛR¹/BFßF·~ïÔ½¦ÔB‘µ­Ý¨X~/àb`1ðãœc¦Ç{“ÿ÷w«ëƒYª×¶Òxà_Àƒ­ô06^7 àlùù~ÀË1ûÖíßÇ*Ös1pXê÷¨Šò:18;ŸÉÀ`9°»?U)RÔÚ-q,£/ÏaÊó«Ì߇ó°›7s³XŒ-¨g"p9°¹@Nx S´:9XéÔÕ—i϶ÖyŒöÅtäø–Ìtk0%Û »S1ƒ±?0؇¸^ô(à'ÀSä_Ë^àí‘ç’0­@þÁe× ØS›nØR?ø'ÅJ—N+0k—å­˜o*§ üعâùM~›‘û$ðY`f‰‡cJ5þ^àAàÐ’u} ØB¹sLÒ%ê™Ü”*» ë=‘¯¾Yò\Òì\Ðî=+È­Ì^ÀõN£šÀŸ[Çœ <ŸùÛV`SN¹$mNMÕõÚƒH¶ÐÙ"7{07 †©ÀÒŒ¼ë0‹˜Çhà÷©s 鎠ýA‰I¯¨ë4àYú­ìگϡÀ_3²û0ËKÞ=/êy”i˜ß”w17bOvx¸ë&§`V«ìÌ®-s)ö†ÞκÏݰî³YÊÀ´+\’ÞqŽ“0ß6-çüÀ²S°˜€Äj)ý×rÚ\6­^RPO¸2uü½GMÄ,tºŽk ŽïÄj§Í+È«Ìà—N£²éìe¡3)¶ª×=r†8å5¾1#ã;%Ëß*{}Áqçc_¶ÇJ§›°‡t¶[Îlà$¬·šÛú½G‡ö\š’÷<ðª€sH—iRm$á~ÚÏëá òj¡í£•wá//)o~Žœ˜Õ.Ó®»9'”ññLÙû°7ø2dà´€2GÒÞ>jtNFæ7ËÍsÚ;Rr‹#ëîHYµÒü›öÆ­Å܆2ìäÈibîDYŽwä\Xv,¶WBºì§#ÚøÅIº1 ÌHÚÛýPDÝiŽ£}´#Ô·ë´'Ä‚{\ãȺ)RV!e‡i6³ýHDÂíØ‹XÖcCIY–—”62¥Sw›ðAàe™<ïóhŸÀ¬jšƒÊz×l}‰º=¾Êö®Ôbàïä…¸‡æU&¦ÛZáä-‹¬íé‘9+1ë“~(CÞÜ>éäŠYŽçZ¿‡c×j 0BJÆnga0Y¦`/¡k êîÃ9Ý‹UQâ©™¶¬Ç^Ž«ònâ1¤•ØsžŽ¬““£Ä[0e™’Ê ±Ä{cŠ˜å,ªß|0k|s‡c6cGB%^ƒ ž<|„rÆ»·Þ= aH+±Wæ™Èú=wæùHY[3¿§¶ä-…™éäõßÔkf‰’{œ<ïß±ØÄ]íÎ*N%nïÆîQözt¢ùÄYêTâYåÜm%Ž”ðÈ>I÷ÿlA™7:y'ccªƒÁ0Ú»ëª>1”Sà±ØÍyønQìØîg‰7DÖïYâØÈº˜r“¼Õ‘õÇàE«=tu1‚< ‹“Splì½õÞD‰cn¼§Ä±«W=KkcÎe‚“W4 V7ã¼²n@Fc¾þ lBipð6l–q‘S¦ì¨S Y⺔¸ÎúÓ{ÁBÓ"ë!;´ö’Z7=X°Q/pæ‡_¼›A¼³œK²eÇÿ6Ð?º“0¤Ý‰X<«;˜JìùŸÓ°Ù¦ÁÀSâº-ñžX¨ìë[¿—aØs›<·¢Ê‰ÇèZ{šø—ÄB†¢%Lw Ðî¶%®S‰Ä¦z^ŠÅçùý^ݱ–¶·¼b…¡ûJÜmKü¨“7˜Jì¹3u)ñl¬GI"×z±!EïœGñì!øJ,KÜ:-q6ê¬Î'tòÆF¶¡,Þ¹Ö¡ÄW»¦~¯~PÎ-‘%ލ?ÖgCC”a~xà™ÄGo•Á®ºíétÚW—kŒ%öÖm…ʹ[•åd,˜¼l{vÞx¬vzñ+§Á_M¼ƒüçã–›#/äº ŠÇð4íÁÎgDÊzÔ‘óñ꩎œ&á½Æôo?M¿^ c¶tÿ,Þ ¤‡¿«úEíö¸Ú‘×Ä9MøPN;š˜[¶[©r°¤•²¬ÿ ”œYåOe`8ÿD/‹5#GÖ9²Þœ#kz ΑÑÄÜž°›}8¦°ûbVêSÀ™ã?_¢Þ?9õmÂÙ‹å})p:ùÖÙ9ç°X€¹ »´þ}/¶  üŽöÏE×#ÄwO/¸hPéÁÖ_å-ÃÞŠÝ8/67ÍpìãÔsÉßSb5¶Ú"dÿˆ ØÊæ¼½î <8L!³K{ʦ/•¨ü%AIZ üóϯÀB;“{ðÅyûÒy‹„lZˆÝ›]é¼gÈÌÕ ¡'U®kß騸ýËÑCÒÀ;YgSn3”­Ø8îé9 à+Øà}ˆœ>àVl QQ´VÂ)ØttYå]KÜF€ ò÷óÈKQ¼ É…rziwß&о^0IK£KžßBlȯkûþ]D÷±ë6?Å.ümØ“»–í—à{ËÝçgŽé¤ÿ†ui·´ä÷²ý6KÙÍPÆaóÿ‰Ux¢UæVàgÀ¯±›ð—TÛ¶a>oȺ7°ÉŽ«èü &¶wÙ¹TÛ¤¹*EÛK%u-¨k8vïò¶EX†¹myK†aÛË.ÀÜŒoc=F#SµÑé ³-ùI¡£± ˜;¬%¯‰)Ÿ7Ä–0¢%Ï‹gm`V54`{x«î²b“0Kufù’MQ–¶Ò}تÞl´V,±Ýxön¥)Ø[ýÌ5ZB¹ÐÈý±¶ˆ¹Ë1ƒqgMíB!„B ê\m,Dš=€oÀ^ÒïÁ¾&»ÑŽƒÊ\üð„gv±]Bq4g=çt­uBt`íu{éqvü/D‰(>u~L]•ê;v¢N¼ ú<^WW¥RbQ'ev4ÙýTˆgüˆþw !„B!„B!„B!„B!„B!„B!„B!„B!„B!„âÅÌÿ1NšÕ¾ÂþIEND®B`‚cl-containers-20170403-git/website/source/shared/style-200.css000066400000000000000000000131121306646076300236700ustar00rootroot00000000000000/* @group toc */ .table-of-contents { font-size: 90%; margin-bottom: 1em; padding-bottom: 1em; } .table-of-contents h2, h3, h4 { padding-top: 0; padding-bottom: 0; margin-top: 0; margin-bottom: 1px; } .table-of-contents h2 { font-size: inherit; font-style: inherit; position: relative; left: 2em; } .table-of-contents h3 { font-size: inherit; font-style: inherit; position: relative; left: 4em; } .table-of-contents h4 { font-size: inherit; font-style: inherit; position: relative; left: 6em; } .table-of-contents h5 { font-size: inherit; font-style: inherit; position: relative; left: 8px; } /* @end */ /* @group documentation */ .hidden { visibility: hidden; } .documentation .header { display: block; position: relative; border-top-style: solid; border-top-width: 1pt; padding-top: 4px; margin-top: 1.2em; } .documentation .name-and-args { width: 80%; float: left; } .documentation { margin-right: 1em; margin-left: 1em; clear: both; color: black; } .function { } .documentation .contents { top: 10px; position: relative; clear: both; margin-bottom: 1.8em; } .documentation-name { font-weight: bold; float: left; padding-right: 0.1em; } .documentation-kind { float: right; font-style: italic; color: gray; padding-left: 10px; } .documentation-arguments { float: left; font-style: italic; margin-left: 2em; clear: both; white-space: normal; } .documentation p { clear: both; margin-right: 1em; margin-left: 1em; } .documentation .marker { color: gray; font-size: 90%; } .docs-group .name-and-args span { float: left; margin-right: 1em; clear: right; } .docs-group .documentation-name { margin-right: 0em; margin-left: -1.9em; clear: right; } .functor .documentation-arguments { white-space: pre; } /* @end */ /* @group header/footer */ #header { position:relative; /* Position is declared "relative" to gain control of stacking order (z-index). */ width:auto; min-width:120px; font-size: medium; background-color: #ff9f07; color: white; border: solid #995f04 4px; padding: 1mm 1mm 1mm 1em; } .header { position:relative; /* Position is declared "relative" to gain control of stacking order (z-index). */ width:auto; min-width:120px; font-size: medium; background-color: #ff9f07; color: white; border: solid #995f04 4px; padding: 1mm 1mm 1mm 1em; } .footer { font-size: small; font-style: italic; background-color: #ff9f07; border-top: 2px solid; border-bottom: 2px solid; border-color:#002244; padding-top: 2mm; padding-bottom: 2mm; float: left; width: 100%; height: 04mm; } #footer { font-size: small; font-style: italic; background-color: #ff9f07; border-top: 2px solid; border-bottom: 2px solid; border-color: #417b39; padding-top: 2mm; padding-bottom: 2mm; float: left; width: 100%; height: 04mm; } .footer-text { color: black; float: right; padding-top: 3em; padding-bottom: 2em; padding-right: 1em; background: inherit; } .footer h3 { padding-top: 10px; padding-left: 0.5in; padding-right: 0.5in; margin-top: 0.2em; margin-bottom: 0.6em; } .footer a:link { font-weight:bold; text-decoration:underline; background: inherit; } .footer a:visited { font-weight:bold; text-decoration:underline; background: inherit; } .footer a:hover { font-weight:bold; color:#002244; text-decoration:underline; background: inherit; } #footer #timestamp { float: right; } #footer .copyright { display: block; padding-top: 0.1em; margin-top: 0.1em; } /* @end */ .system-links { list-style: url(http://common-lisp.net/project/cl-containers/images/lambda.png); width: 14%; text-align: left; padding-right: 1em; padding-top: 1.5em; float: left; font-size: 80%; } .system-links li { padding-top: 10px; font-family: Arial, Helvetica, sans-serif; } .system-description { width: 80%; padding-left: 0em; float: right; } .system-description p, li, .documentation { margin-right: 2em; padding-right: 2em; } .check { font-size: x-small; text-align:right; color: inherit; background: inherit; } .check a:link { font-weight:bold; color:#a0a0ff; text-decoration:underline; background: inherit; } .check a:visited { font-weight:bold; color:#a0a0ff; text-decoration:underline; background: inherit; } .check a:hover { font-weight:bold; color:#000000; text-decoration:underline; background: inherit; } .changelog { font-size: 75%; padding: 1em 2em 2em; vertical-align: top; color: #686868; background: inherit; } .changelog-author { text-align: right; color: #686868; background: inherit; } .changelog-description { padding-left: 2em; color: #000000; padding-bottom: 1em; font-size: 120%; padding-right: 2em; background: inherit; } .header h2 { padding-top: 0px; margin-top: 0.2em; margin-bottom: 0.6em; } .header h4 { padding-top: 0px; margin-top: 0.2em; margin-bottom: 0.6em; } .logo { float: right; text-align: right; right: 2em; } .nav { padding-left: 1em; } .code-block { font: 90% "Courier New", Courier, monospace; padding-right: 2em; padding-left: 2em; overflow: auto; color: #000000; background: #f6ead6; width: 90%; } pre { font: 90% "Courier New", Courier, monospace; color: #000000; background: #f6ead6; width: 90%; overflow: auto; border: 1px solid #995f04; padding: 0.25em 0.5em; margin-left: 2em; } .system-news { border-collapse: collapse; vertical-align: top; margin-bottom: 1em; } .system-news th { font-weight: normal; vertical-align: top; width: 100px; text-align: left; } .system-news td { vertical-align: top; padding-bottom: 0.4em; text-align: left; } .odd-row { background: #f4e9d7; } cl-containers-20170403-git/website/source/shared/style.css000066400000000000000000000057661306646076300234110ustar00rootroot00000000000000 .header { position:relative; /* Position is declared "relative" to gain control of stacking order (z-index). */ width:auto; min-width:120px; font-size: medium; background-color: #ff9f07; color: white; border: solid #995f04 4px; padding: 1mm 1mm 1mm 1em; } .footer { font-size: small; font-style: italic; background-color: #ff9f07; color: white; border-top: 2px solid; border-bottom: 2px solid; border-color:#002244; padding-top: 2mm; padding-bottom: 2mm; float: left; width: 100%; height: 04mm; } .footer-text { color: black; float: right; padding-top: 3em; padding-bottom: 2em; padding-right: 1em; background: inherit; } .footer a:link { font-weight:bold; color:#ffffff; text-decoration:underline; background: inherit; } .footer a:visited { font-weight:bold; color:#ffffff; text-decoration:underline; background: inherit; } .footer a:hover { font-weight:bold; color:#002244; text-decoration:underline; background: inherit; } .system-links { list-style: url(http://common-lisp.net/project/cl-containers/images/lambda.png); width: 14%; text-align: left; padding-right: 1em; padding-top: 1.5em; float: left; font-size: 80%; } .system-links li { padding-top: 10px; font-family: Arial, Helvetica, sans-serif; } .system-description { width: 80%; padding-left: 0em; float: right; } .check { font-size: x-small; text-align:right; color: inherit; background: inherit; } .check a:link { font-weight:bold; color:#a0a0ff; text-decoration:underline; background: inherit; } .check a:visited { font-weight:bold; color:#a0a0ff; text-decoration:underline; background: inherit; } .check a:hover { font-weight:bold; color:#000000; text-decoration:underline; background: inherit; } .changelog { font-size: 75%; padding: 1em 2em 2em; vertical-align: top; color: #686868; background: inherit; } .changelog-author { text-align: right; color: #686868; background: inherit; } .changelog-description { padding-left: 2em; color: #000000; padding-bottom: 1em; font-size: 120%; padding-right: 2em; background: inherit; } .header h2 { padding-top: 0px; margin-top: 0.2em; margin-bottom: 0.6em; } .header h4 { padding-top: 0px; margin-top: 0.2em; margin-bottom: 0.6em; } .logo { float: right; text-align: right; right: 2em; } .nav { padding-left: 1em; } .code-block { font: 90% "Courier New", Courier, monospace; padding-right: 2em; padding-left: 2em; overflow: auto; color: #000000; background: #f6ead6; width: 90%; } pre { font: 90% "Courier New", Courier, monospace; color: #000000; background: #f6ead6; width: 90%; overflow: auto; border: 1px solid #995f04; padding: 0.25em 0.5em; margin-left: 2em; } .system-news { border-collapse: collapse; vertical-align: top; margin-bottom: 1em; } .system-news th { font-weight: normal; vertical-align: top; width: 100px; text-align: left; } .system-news td { vertical-align: top; padding-bottom: 0.4em; text-align: left; } .odd-row { background: #f4e9d7; } cl-containers-20170403-git/website/source/user-guide-details/000077500000000000000000000000001306646076300237475ustar00rootroot00000000000000cl-containers-20170403-git/website/source/user-guide-details/motivation.mmd000066400000000000000000000031521306646076300266400ustar00rootroot00000000000000A significant portion of almost any non-trivial programming effort goes into the manipulation of structured data. Many data structures can be viewed as containers. These may be ordered or unordered, associative (indexed) or sequential and so forth. The power and beauty of some programming languages derives in no small part from their ability to handle container classes well (Smalltalk comes to mind) and other languages have gone to great lengths to incorporate flexible containers into their frameworks (C++'s STL for example). Although Common Lisp includes a number of *containers* (hash-tables, lists and arrays) there are many useful data structures that are not built-in (e.g., binary search trees) and the existing containers have a fragmented interface that shows Lisp's peripatetic evolution. The Common Lisp Container Library ({clcl}) extends Lisp in two ways: it adds new container functionality and, by standardizing container interfaces, it makes using them significantly easier. The standard interface also lends itself to more a flexible design and development process since data structure decisions are easier to change as the program evolves. {clcl}~ thereby expends the power of Lisp and makes it an even better tool for both rapid prototyping \emph{and} production code. The remainder of this document will cover the container types available in {clcl}, the methods applicable to these containers, information about the internal design of {clcl} and examples of containers in use. As will become evident, {clcl}'s design borrows from the Standard Template Library, Smalltalk and existing Lisp idioms wherever possible. cl-containers-20170403-git/website/source/user-guide.md000066400000000000000000000074051306646076300226540ustar00rootroot00000000000000{include resources/ug-header.md} {set-property title "CL-Containers User's Guide"} {set-property style-sheet user-guide} {set-property docs-package cl-containers} # CL-Containers User's Guide # Table of Contents {table-of-contents :start 2 :depth 3} ## Introduction Common Lisp ships with a set of powerful built in data structures including the venerable list, full featured arrays, and hash-tables. The Common Lisp Container Library {clcl} enhances and builds on these structures in two ways: 1. By adding containers that are not available in native Lisp (for example: binary search trees, red-black trees, sparse arrays and so on). 2. By standardizing the container interface so that they are simpler to use and so that changing design decisions becomes significantly easier. The containers in {clcl} can be divided into three storage types: Ordered, Unordered and Associative. * Ordered containers store things in (some) order. The order may be based on how items were inserted into the container or it may depend on an explicit sorting. * Unordered containers also store things and share much of Ordered containers interface. However, the items in an Unordered container do not maintain any particular arrangement. * Associative containers store items *associated* with some index or key. The key may be simple (for example, a one-dimensional array indexed by an integer) or complex (for example, a nested hash table indexed by color, size and object class). The way containers store their contents provides another view in {clcl}'s design: containers may store their contents directly (think of a list) or they may wrap each element within some data-structure -- a node -- that helps the container keep track of what is going on (think of a binary tree). We'll see many examples of both styles below. There are many other mixins that combine to produce generic container behavior. For example, a [bounded-container-mixin][] starts at some fixed size and cannot grow beyond it whereas a [keyed-container-mixin][] provide a `key` function that is used by other container functions (e.g., [sort-container][]) to modify their behavior. ## Terminology *Containers* store *elements*. Sometimes the elements are wrapped in *nodes*. We can *insert*, *delete*, *search-for*, *find*, *iterate*, and *collect* both elements and nodes from a container. We can also look at the *size* of a container, see it is *empty* (with [emptyp][]) and *empty* it (with [empty!][]). Ordered containers also let us find the *first*, *last* and *nth* element (or node) and they may let us *sort* or *reverse* the contents as a whole. Associative containers provide the ability to look at *keys* and elements (or, sometimes, *values*). We can collect and iterate either one of these or both simultaneously. Finally, certain specialized container classes provide synonyms for their usual operations. For example, you can still pop and push into a [stack-container][]. ## Using a container ### Creating and inspecting {include user-guide/creation-and-inspection.mmd} ### General use: adding, deleting, finding {include user-guide/editing.mmd} ### Some and Every {include user-guide/querying.mmd} ### Counting, Collecting, and Canvasing {include user-guide/iteration-and-collection.mmd} ### Finding and Searching {include user-guide/searching.mmd} ### Miscellaneous {docs reduce-elements} {docs reduce-nodes} {docs dimensions} ### Container taxonomy {include user-guide/taxonomy.mmd} ### Iterators {include user-guide/iteration.mmd} ## Indices ### Index of Functions {docs-index (function macro) function} ### Index of variables {docs-index variable} ### Full symbol index {docs-index :all}
#### Glossary {glossary} #### Footnotes {footnotes} {include resources/ug-footer.md} cl-containers-20170403-git/website/source/user-guide/000077500000000000000000000000001306646076300223245ustar00rootroot00000000000000cl-containers-20170403-git/website/source/user-guide/creation-and-inspection.mmd000066400000000000000000000011701306646076300275370ustar00rootroot00000000000000Containers can be created with {hs make-instance} or [make-container][]. The latter is exactly the same as the former unless [dynamic-classes][] is also loaded. In this case, `make-container` can take a list of superclasses and will find or create a container class to match. {docs make-container} Though specific container classes add to this list, every container shares a set of common operations: {docs size} {docs total-size} {docs empty!} {docs empty-p} Container nodes (i.e., instances of type [container-node-mixin][]) also share a set of operations: {docs element} {docs has-children-p} {docs make-node-for-container} cl-containers-20170403-git/website/source/user-guide/editing.mmd000066400000000000000000000006261306646076300244520ustar00rootroot00000000000000#### Adding #### Deleting {docs delete-item} {docs delete-element} {docs delete-node} #### Getting {docs nth-item} {docs nth-element} {docs item-at} {docs item-at-1} #### Specialized These operations are essentially synonyms for the generic container methods. They are included to make working with queues and stacks feel more natural. {docs enqueue} {docs dequeue} {docs push-item} {docs pop-item} cl-containers-20170403-git/website/source/user-guide/iteration-and-collection.mmd000066400000000000000000000011221306646076300277060ustar00rootroot00000000000000Once you have a container, it is very common to want to map some function over its contents or to want to collect its contents for some other purpose. The following functions support these desires. {docs iterate-nodes} {docs iterate-elements} {docs iterate-elements-stably} {docs iterate-keys} {docs iterate-key-value} {docs iterate-key-value-stably} {docs collect-items} {docs collect-nodes} {docs collect-elements} {docs collect-keys} {docs collect-key-value} {docs collect-elements-stably} {docs collect-key-value-stably} {docs count-elements} {docs count-items} {docs count-elements-if} cl-containers-20170403-git/website/source/user-guide/iteration.mmd000066400000000000000000000012771306646076300250300ustar00rootroot00000000000000CL-Containers includes a set of classes to implement forward iterators and simple generators (where the latter is a sort of infinite instance of the former). To iterate, you create an iterator on a container and then move forward until the iterator is exhausted. #### Creating an iterator {docs base-class-for-iteratee} {docs class-for-contents-as} {docs setup-initial-container} {docs open-file-for-iterator} {docs finish} #### Using an iterator {docs with-iterator} {docs move-p} {docs element-passes-p} {docs move} {docs advance} {docs current-element} {docs current-element-p} {docs iterate-forward} {docs move-forward} {docs move-forward-to-next-element} {docs next-element} {docs reset} cl-containers-20170403-git/website/source/user-guide/querying.mmd000066400000000000000000000002051306646076300246630ustar00rootroot00000000000000{docs some-item-p} {docs every-item-p} {docs some-element-p} {docs every-element-p} {docs every-key-value-p} {docs some-key-value-p} cl-containers-20170403-git/website/source/user-guide/searching.mmd000066400000000000000000000002361306646076300247670ustar00rootroot00000000000000{docs find-item} {docs find-node} {docs find-element} {docs search-for-element} {docs search-for-key} {docs search-for-matching-node} {docs search-for-node} cl-containers-20170403-git/website/source/user-guide/taxonomy.mmd000066400000000000000000000047221306646076300247060ustar00rootroot00000000000000package-container abstract-tree-container rooted-tree-container quad-tree binary-search-tree splay-tree red-black-tree vector-container-mixin many-ordered-child-node basic-vector-container vector-container heap-container k-best-heap-container flexible-vector-container bounded-vector-container uses-contents-mixin abstract-bag/set-container set-container bag-container stack-container alist-container array-container-abstract array-container contents-as-hashtable-mixin union-find-container bag/set-container keyed-bag/set-container associative-container keyed-associative-container simple-associative-container sparse-array-container contents-as-array-mixin contents-as-sequence-mixin contents-as-list-mixin many-unordered-child-node list-container sorted-list-container non-associative-container-mixin cl-graph:graph-container cl-graph:dot-graph ordered-container-mixin dlist-container sorted-dlist-container abstract-stack abstract-queue ring-buffer basic-queue priority-queue-on-container classified-container-mixin sorted-container-mixin unordered-container-mixin searchable-container-mixin iteratable-container-mixin forward-iterator delimited-iterator line-iterator word-iterator basic-stream-iterator file-form-iterator file-line-iterator file-iterator basic-generator arithmetic-sequence-generator finite-arithmetic-sequence-generator array-iterator list-iterator hash-table-iterator many-child-node stable-associative-container key-value-iteratable-container-mixin findable-container-mixin container-uses-nodes-mixin basic-initial-contents-mixin initial-contents-key-value-mixin associative-container-mixin biassociative-container-mixin initial-contents-mixin initial-element-mixin indexed-container-mixin bounded-container-mixin typed-container-mixin keyed-container-mixin) basic-iterator> # # # # # # # # # # # # # # #)cl-containers-20170403-git/website/source/user-guide/todo.mmd000066400000000000000000000005401306646076300237670ustar00rootroot00000000000000### What's missing ### What's included that shouldn't be ### Delete * drop collect-items * drop delete-item * drop find-item ### Add * add count-nodes and count-nodes-if * add collect-nodes-stably * maybe add emptyp to iterator protocol ### Rename * s/some-item/some-node/ * s/every-item/every-node/ * item-at * item-at-1 * push-item * pop-itemcl-containers-20170403-git/website/stuff/000077500000000000000000000000001306646076300201025ustar00rootroot00000000000000cl-containers-20170403-git/website/stuff/Temp.lisp000066400000000000000000000020131306646076300216740ustar00rootroot00000000000000(in-package #:few) #+Ignore ;; suck site up and output as LML (mapc (lambda (file) (let ((html (net.html.parser:parse-html file))) (setf html (remove-if (lambda (x) (and (consp x) (member (first x) '(:!doctype)))) html)) (with-new-file (s (make-pathname :type "lml" :defaults file) :print-right-margin 70) (format s "~S" html)))) (directory "Billy-Pilgrim:Users:gwking:darcs:metabang.tinaa:website:*.html")) (net.html.parser:parse-html #P"Billy-Pilgrim:Users:gwking:darcs:metabang.tinaa:website:index.html") (probe-file "Billy-Pilgrim:Users:gwking:darcs:cl-containers:website:index.shtml") (eval `(html ((:html :xmlns "http://www.w3.org/1999/xhtml") ,@(rest ccl:!)))) #+No (with-new-file (*html-stream* (spy (make-pathname :type "lml" :defaults file))) (dtd-prologue :xhtml11) (eval `(html ((:html :xmlns "http://www.w3.org/1999/xhtml") ,@html))))cl-containers-20170403-git/website/stuff/containers.dot000066400000000000000000000303151306646076300227610ustar00rootroot00000000000000graph G { graph [rankdir=LR]; SPLAY_TREE [label="splay-tree", color="blue", style="filled", fontcolor="white", fillcolor="blue"] SORTED_CONTAINER_MIXIN [label="sorted-container-mixin", ] KEYED_BAG_SET_CONTAINER [label="keyed-bag/set-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] MANY_CHILD_NODE [label="many-child-node", ] HEAP_CONTAINER [label="heap-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] ALIST_CONTAINER [label="alist-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] K_BEST_HEAP_CONTAINER [label="k-best-heap-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] FINDABLE_CONTAINER_MIXIN [label="findable-container-mixin", ] SPARSE_ARRAY_CONTAINER [label="sparse-array-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] FLEXIBLE_VECTOR_CONTAINER [label="flexible-vector-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] ABSTRACT_CONTAINER [label="abstract-container", ] KEYED_ASSOCIATIVE_CONTAINER [label="keyed-associative-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] KEY_VALUE_ITERATABLE_CONTAINER_MIXIN [label="key-value-iteratable-container-mixin", ] RING_BUFFER [label="ring-buffer", color="blue", style="filled", fontcolor="white", fillcolor="blue"] ABSTRACT_BAG_SET_CONTAINER [label="abstract-bag/set-container", ] LIST_CONTAINER [label="list-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] ABSTRACT_STACK [label="abstract-stack", ] BIASSOCIATIVE_CONTAINER_MIXIN [label="biassociative-container-mixin", ] BASIC_INITIAL_CONTENTS_MIXIN [label="basic-initial-contents-mixin", ] BAG_SET_CONTAINER [label="bag/set-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] INDEXED_CONTAINER_MIXIN [label="indexed-container-mixin", ] CONTENTS_AS_ARRAY_MIXIN [label="contents-as-array-mixin", ] SORTED_DLIST_CONTAINER [label="sorted-dlist-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] ARRAY_CONTAINER [label="array-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] DLIST_CONTAINER [label="dlist-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] PACKAGE_CONTAINER [label="package-container", ] USES_CONTENTS_MIXIN [label="uses-contents-mixin", ] MANY_UNORDERED_CHILD_NODE [label="many-unordered-child-node", ] UNION_FIND_CONTAINER [label="union-find-container", ] GRAPH_CONTAINER [label="graph-container", ] SORTED_LIST_CONTAINER [label="sorted-list-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] ARRAY_CONTAINER_ABSTRACT [label="array-container-abstract", ] STABLE_ASSOCIATIVE_CONTAINER [label="stable-associative-container", ] QUAD_TREE [label="quad-tree", color="blue", style="filled", fontcolor="white", fillcolor="blue"] INITIAL_ELEMENT_MIXIN [label="initial-element-mixin", ] SIMPLE_ASSOCIATIVE_CONTAINER [label="simple-associative-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] BAG_CONTAINER [label="bag-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] STACK_CONTAINER [label="stack-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] VECTOR_CONTAINER [label="vector-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] UNORDERED_CONTAINER_MIXIN [label="unordered-container-mixin", ] FORWARD_ITERATOR [label="forward-iterator", ] CONTAINER_USES_NODES_MIXIN [label="container-uses-nodes-mixin", ] PRIORITY_QUEUE_ON_CONTAINER [label="priority-queue-on-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] VECTOR_CONTAINER_MIXIN [label="vector-container-mixin", ] ITERATABLE_CONTAINER_MIXIN [label="iteratable-container-mixin", ] CLASSIFIED_CONTAINER_MIXIN [label="classified-container-mixin", ] SEARCHABLE_CONTAINER_MIXIN [label="searchable-container-mixin", ] CONTENTS_AS_HASHTABLE_MIXIN [label="contents-as-hashtable-mixin", ] INITIAL_CONTENTS_MIXIN [label="initial-contents-mixin", ] ABSTRACT_QUEUE [label="abstract-queue", ] BINARY_SEARCH_TREE [label="binary-search-tree", color="blue", style="filled", fontcolor="white", fillcolor="blue"] ABSTRACT_TREE_CONTAINER [label="abstract-tree-container", ] MANY_ORDERED_CHILD_NODE [label="many-ordered-child-node", ] NON_ASSOCIATIVE_CONTAINER_MIXIN [label="non-associative-container-mixin", ] INITIAL_CONTENTS_KEY_VALUE_MIXIN [label="initial-contents-key-value-mixin", ] ASSOCIATIVE_CONTAINER_MIXIN [label="associative-container-mixin", ] BASIC_VECTOR_CONTAINER [label="basic-vector-container", ] CONTENTS_AS_SEQUENCE_MIXIN [label="contents-as-sequence-mixin", ] TYPED_CONTAINER_MIXIN [label="typed-container-mixin", ] ROOTED_TREE_CONTAINER [label="rooted-tree-container", ] BASIC_QUEUE [label="basic-queue", color="blue", style="filled", fontcolor="white", fillcolor="blue"] CONTENTS_AS_LIST_MIXIN [label="contents-as-list-mixin", ] ASSOCIATIVE_CONTAINER [label="associative-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] SET_CONTAINER [label="set-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] RED_BLACK_TREE [label="red-black-tree", color="blue", style="filled", fontcolor="white", fillcolor="blue"] KEYED_CONTAINER_MIXIN [label="keyed-container-mixin", ] ORDERED_CONTAINER_MIXIN [label="ordered-container-mixin", ] BOUNDED_CONTAINER_MIXIN [label="bounded-container-mixin", ] BOUNDED_VECTOR_CONTAINER [label="bounded-vector-container", color="blue", style="filled", fontcolor="white", fillcolor="blue"] BINARY_SEARCH_TREE--SPLAY_TREE [] SORTED_CONTAINER_MIXIN--HEAP_CONTAINER [] SORTED_CONTAINER_MIXIN--SORTED_DLIST_CONTAINER [] SORTED_CONTAINER_MIXIN--SORTED_LIST_CONTAINER [] SORTED_CONTAINER_MIXIN--BINARY_SEARCH_TREE [] SORTED_CONTAINER_MIXIN--PRIORITY_QUEUE_ON_CONTAINER [] ORDERED_CONTAINER_MIXIN--SORTED_CONTAINER_MIXIN [] KEYED_CONTAINER_MIXIN--SORTED_CONTAINER_MIXIN [] BAG_SET_CONTAINER--KEYED_BAG_SET_CONTAINER [] MANY_CHILD_NODE--MANY_UNORDERED_CHILD_NODE [] MANY_CHILD_NODE--MANY_ORDERED_CHILD_NODE [] ITERATABLE_CONTAINER_MIXIN--MANY_CHILD_NODE [] HEAP_CONTAINER--K_BEST_HEAP_CONTAINER [] VECTOR_CONTAINER--HEAP_CONTAINER [] CONTAINER_USES_NODES_MIXIN--HEAP_CONTAINER [] USES_CONTENTS_MIXIN--ALIST_CONTAINER [] KEY_VALUE_ITERATABLE_CONTAINER_MIXIN--ALIST_CONTAINER [] BIASSOCIATIVE_CONTAINER_MIXIN--ALIST_CONTAINER [] INITIAL_ELEMENT_MIXIN--ALIST_CONTAINER [] BOUNDED_CONTAINER_MIXIN--K_BEST_HEAP_CONTAINER [] FINDABLE_CONTAINER_MIXIN--QUAD_TREE [] FINDABLE_CONTAINER_MIXIN--ABSTRACT_BAG_SET_CONTAINER [] FINDABLE_CONTAINER_MIXIN--BINARY_SEARCH_TREE [] FINDABLE_CONTAINER_MIXIN--PRIORITY_QUEUE_ON_CONTAINER [] FINDABLE_CONTAINER_MIXIN--CONTENTS_AS_HASHTABLE_MIXIN [] ABSTRACT_CONTAINER--FINDABLE_CONTAINER_MIXIN [] KEYED_CONTAINER_MIXIN--FINDABLE_CONTAINER_MIXIN [] CONTENTS_AS_HASHTABLE_MIXIN--SPARSE_ARRAY_CONTAINER [] ASSOCIATIVE_CONTAINER_MIXIN--SPARSE_ARRAY_CONTAINER [] INITIAL_ELEMENT_MIXIN--SPARSE_ARRAY_CONTAINER [] BOUNDED_CONTAINER_MIXIN--SPARSE_ARRAY_CONTAINER [] VECTOR_CONTAINER--FLEXIBLE_VECTOR_CONTAINER [] ABSTRACT_CONTAINER--PACKAGE_CONTAINER [] ABSTRACT_CONTAINER--VECTOR_CONTAINER_MIXIN [] ABSTRACT_CONTAINER--ABSTRACT_TREE_CONTAINER [] ABSTRACT_CONTAINER--USES_CONTENTS_MIXIN [] ABSTRACT_CONTAINER--NON_ASSOCIATIVE_CONTAINER_MIXIN [] ABSTRACT_CONTAINER--SEARCHABLE_CONTAINER_MIXIN [] ABSTRACT_CONTAINER--CONTAINER_USES_NODES_MIXIN [] ABSTRACT_CONTAINER--BASIC_INITIAL_CONTENTS_MIXIN [] ABSTRACT_CONTAINER--INITIAL_ELEMENT_MIXIN [] ABSTRACT_CONTAINER--INDEXED_CONTAINER_MIXIN [] ABSTRACT_CONTAINER--BOUNDED_CONTAINER_MIXIN [] ABSTRACT_CONTAINER--TYPED_CONTAINER_MIXIN [] ABSTRACT_CONTAINER--KEYED_CONTAINER_MIXIN [] ASSOCIATIVE_CONTAINER--KEYED_ASSOCIATIVE_CONTAINER [] KEYED_CONTAINER_MIXIN--KEYED_ASSOCIATIVE_CONTAINER [] KEY_VALUE_ITERATABLE_CONTAINER_MIXIN--STABLE_ASSOCIATIVE_CONTAINER [] KEY_VALUE_ITERATABLE_CONTAINER_MIXIN--CONTENTS_AS_HASHTABLE_MIXIN [] ITERATABLE_CONTAINER_MIXIN--KEY_VALUE_ITERATABLE_CONTAINER_MIXIN [] ABSTRACT_QUEUE--RING_BUFFER [] ITERATABLE_CONTAINER_MIXIN--RING_BUFFER [] BOUNDED_CONTAINER_MIXIN--RING_BUFFER [] ABSTRACT_BAG_SET_CONTAINER--SET_CONTAINER [] ABSTRACT_BAG_SET_CONTAINER--BAG_CONTAINER [] USES_CONTENTS_MIXIN--ABSTRACT_BAG_SET_CONTAINER [] UNORDERED_CONTAINER_MIXIN--ABSTRACT_BAG_SET_CONTAINER [] ITERATABLE_CONTAINER_MIXIN--ABSTRACT_BAG_SET_CONTAINER [] INITIAL_CONTENTS_MIXIN--ABSTRACT_BAG_SET_CONTAINER [] LIST_CONTAINER--SORTED_LIST_CONTAINER [] CONTENTS_AS_LIST_MIXIN--LIST_CONTAINER [] ABSTRACT_STACK--STACK_CONTAINER [] ORDERED_CONTAINER_MIXIN--ABSTRACT_STACK [] ITERATABLE_CONTAINER_MIXIN--ABSTRACT_STACK [] INITIAL_CONTENTS_MIXIN--ABSTRACT_STACK [] ASSOCIATIVE_CONTAINER_MIXIN--BIASSOCIATIVE_CONTAINER_MIXIN [] BASIC_INITIAL_CONTENTS_MIXIN--INITIAL_CONTENTS_KEY_VALUE_MIXIN [] BASIC_INITIAL_CONTENTS_MIXIN--INITIAL_CONTENTS_MIXIN [] CONTENTS_AS_HASHTABLE_MIXIN--BAG_SET_CONTAINER [] UNORDERED_CONTAINER_MIXIN--BAG_SET_CONTAINER [] INDEXED_CONTAINER_MIXIN--ASSOCIATIVE_CONTAINER_MIXIN [] CONTENTS_AS_ARRAY_MIXIN--VECTOR_CONTAINER_MIXIN [] USES_CONTENTS_MIXIN--CONTENTS_AS_ARRAY_MIXIN [] ITERATABLE_CONTAINER_MIXIN--CONTENTS_AS_ARRAY_MIXIN [] DLIST_CONTAINER--SORTED_DLIST_CONTAINER [] ARRAY_CONTAINER_ABSTRACT--ARRAY_CONTAINER [] ITERATABLE_CONTAINER_MIXIN--ARRAY_CONTAINER [] INITIAL_ELEMENT_MIXIN--ARRAY_CONTAINER [] TYPED_CONTAINER_MIXIN--ARRAY_CONTAINER [] ORDERED_CONTAINER_MIXIN--DLIST_CONTAINER [] ITERATABLE_CONTAINER_MIXIN--DLIST_CONTAINER [] CONTAINER_USES_NODES_MIXIN--DLIST_CONTAINER [] ITERATABLE_CONTAINER_MIXIN--PACKAGE_CONTAINER [] USES_CONTENTS_MIXIN--ARRAY_CONTAINER_ABSTRACT [] USES_CONTENTS_MIXIN--STACK_CONTAINER [] USES_CONTENTS_MIXIN--CONTENTS_AS_HASHTABLE_MIXIN [] USES_CONTENTS_MIXIN--CONTENTS_AS_SEQUENCE_MIXIN [] CONTENTS_AS_LIST_MIXIN--MANY_UNORDERED_CHILD_NODE [] CONTENTS_AS_HASHTABLE_MIXIN--UNION_FIND_CONTAINER [] NON_ASSOCIATIVE_CONTAINER_MIXIN--GRAPH_CONTAINER [] ITERATABLE_CONTAINER_MIXIN--GRAPH_CONTAINER [] CONTAINER_USES_NODES_MIXIN--GRAPH_CONTAINER [] INITIAL_CONTENTS_MIXIN--GRAPH_CONTAINER [] ASSOCIATIVE_CONTAINER_MIXIN--ARRAY_CONTAINER_ABSTRACT [] BOUNDED_CONTAINER_MIXIN--ARRAY_CONTAINER_ABSTRACT [] ITERATABLE_CONTAINER_MIXIN--STABLE_ASSOCIATIVE_CONTAINER [] ASSOCIATIVE_CONTAINER_MIXIN--STABLE_ASSOCIATIVE_CONTAINER [] ROOTED_TREE_CONTAINER--QUAD_TREE [] CLASSIFIED_CONTAINER_MIXIN--QUAD_TREE [] ITERATABLE_CONTAINER_MIXIN--QUAD_TREE [] CONTAINER_USES_NODES_MIXIN--QUAD_TREE [] INITIAL_CONTENTS_MIXIN--QUAD_TREE [] INITIAL_ELEMENT_MIXIN--ASSOCIATIVE_CONTAINER [] INITIAL_ELEMENT_MIXIN--SIMPLE_ASSOCIATIVE_CONTAINER [] CONTENTS_AS_HASHTABLE_MIXIN--SIMPLE_ASSOCIATIVE_CONTAINER [] ASSOCIATIVE_CONTAINER_MIXIN--SIMPLE_ASSOCIATIVE_CONTAINER [] BASIC_VECTOR_CONTAINER--VECTOR_CONTAINER [] NON_ASSOCIATIVE_CONTAINER_MIXIN--UNORDERED_CONTAINER_MIXIN [] ITERATABLE_CONTAINER_MIXIN--FORWARD_ITERATOR [] CONTAINER_USES_NODES_MIXIN--BINARY_SEARCH_TREE [] ABSTRACT_QUEUE--PRIORITY_QUEUE_ON_CONTAINER [] ITERATABLE_CONTAINER_MIXIN--PRIORITY_QUEUE_ON_CONTAINER [] VECTOR_CONTAINER_MIXIN--BASIC_VECTOR_CONTAINER [] VECTOR_CONTAINER_MIXIN--MANY_ORDERED_CHILD_NODE [] ORDERED_CONTAINER_MIXIN--VECTOR_CONTAINER_MIXIN [] INITIAL_CONTENTS_MIXIN--VECTOR_CONTAINER_MIXIN [] TYPED_CONTAINER_MIXIN--VECTOR_CONTAINER_MIXIN [] ITERATABLE_CONTAINER_MIXIN--BINARY_SEARCH_TREE [] ITERATABLE_CONTAINER_MIXIN--BASIC_QUEUE [] ITERATABLE_CONTAINER_MIXIN--CONTENTS_AS_SEQUENCE_MIXIN [] SEARCHABLE_CONTAINER_MIXIN--ITERATABLE_CONTAINER_MIXIN [] ORDERED_CONTAINER_MIXIN--CLASSIFIED_CONTAINER_MIXIN [] KEYED_CONTAINER_MIXIN--CLASSIFIED_CONTAINER_MIXIN [] CONTENTS_AS_HASHTABLE_MIXIN--ASSOCIATIVE_CONTAINER [] INITIAL_CONTENTS_MIXIN--BINARY_SEARCH_TREE [] INITIAL_CONTENTS_MIXIN--ABSTRACT_QUEUE [] INITIAL_CONTENTS_MIXIN--CONTENTS_AS_LIST_MIXIN [] ABSTRACT_QUEUE--BASIC_QUEUE [] ORDERED_CONTAINER_MIXIN--ABSTRACT_QUEUE [] BINARY_SEARCH_TREE--RED_BLACK_TREE [] ROOTED_TREE_CONTAINER--BINARY_SEARCH_TREE [] ABSTRACT_TREE_CONTAINER--ROOTED_TREE_CONTAINER [] NON_ASSOCIATIVE_CONTAINER_MIXIN--ORDERED_CONTAINER_MIXIN [] INITIAL_CONTENTS_KEY_VALUE_MIXIN--ASSOCIATIVE_CONTAINER_MIXIN [] ASSOCIATIVE_CONTAINER_MIXIN--ASSOCIATIVE_CONTAINER [] BASIC_VECTOR_CONTAINER--BOUNDED_VECTOR_CONTAINER [] CONTENTS_AS_SEQUENCE_MIXIN--CONTENTS_AS_LIST_MIXIN [] ORDERED_CONTAINER_MIXIN--CONTENTS_AS_LIST_MIXIN [] KEYED_CONTAINER_MIXIN--CONTENTS_AS_LIST_MIXIN [] }cl-containers-20170403-git/website/stuff/index.shtml000066400000000000000000000063161306646076300222700ustar00rootroot00000000000000 <!--#include virtual="project-name" -->

More fun than kissing monkeys!

When is it?

Last updated 6 October 2005.

What it is

Common Lisp ships with a set of powerful built in data structures including the venerable list, full featured arrays, and hash-tables. CL-containers enhances and builds on these structures in two ways:

  1. By adding containers that are not available in native Lisp (for example: binary search trees, red-black trees, sparse arrays and so on).
  2. By providing a standard interface so that they are simpler to use and so that changing design decisions becomes significantly easier.

Where it is

6 Oct 2005 I've decided to get cl-containers out without worrying about ASDF. This means I should be able to stick what's needed up on the web site by the end of this week (oh, oh, I've almost made a commitment). This includes:
  • cl-containers
  • metatilities (everyone needs their own set of matching utilities)
  • moptilities (everyone needs their own MOP layer too)
  • generic-load-utilities
Most of this will be released using the MIT license although some of the code comes from long ago and far away and has it's own (quite unrestrictive) license. Once I've released, lots of good stuff will remain to do (asdf, testing, making sure it's platform compliant, etc). As always, stay tuned.
5 Oct 2005 I've got most of cl-containers under darcs now and split away from various unneccesary dependencies of the rest of my code. The next steps are:
  • Switching completely to asdf
  • Adding license information (cl-containers will be released under the MIT license)
  • Getting basic documentation ready
  • Making the source available
If things go moderately then "real soon now" may actually occur "real soon". Thanks for your patience.
29 July 2005 I'm in the process of converting cl-containers from a home grown defsystem to ASDF, of cleaning up some unnecessary dependencies and of trying to create a bit of documentation. I hope to have cl-containers up in some form real soon now. You can drop me e-mail if you're interested, would like to help or want to be notified when the code actually appears up here!

Back to Common-lisp.net.

cl-containers-20170403-git/website/stuff/iterators.dot000066400000000000000000000035161306646076300226330ustar00rootroot00000000000000graph G { graph [rankdir=LR]; ARITHMETIC_SEQUENCE_GENERATOR [label="arithmetic-sequence-generator", ] BASIC_GENERATOR [label="basic-generator", ] HASH_TABLE_ITERATOR [label="hash-table-iterator", ] TRANSFORMING_ITERATOR_MIXIN [label="transforming-iterator-mixin", ] LIST_ITERATOR [label="list-iterator", ] FINITE_ARITHMETIC_SEQUENCE_GENERATOR [label="finite-arithmetic-sequence-generator", ] BASIC_STREAM_ITERATOR [label="basic-stream-iterator", ] BASIC_ITERATOR [label="basic-iterator", ] WORD_ITERATOR [label="word-iterator", ] CIRCULAR_ITERATOR_MIXIN [label="circular-iterator-mixin", ] FORWARD_ITERATOR [label="forward-iterator", ] FILE_ITERATOR [label="file-iterator", ] FILE_LINE_ITERATOR [label="file-line-iterator", ] FILTERED_ITERATOR_MIXIN [label="filtered-iterator-mixin", ] ABSTRACT_GENERATOR [label="abstract-generator", ] BASIC_FILTERED_ITERATOR_MIXIN [label="basic-filtered-iterator-mixin", ] ARRAY_ITERATOR [label="array-iterator", ] CIRCULAR_ITERATOR_MIXIN_AND_LIST_ITERATOR [label="circular-iterator-mixin-and-list-iterator", ] UNIQUE_VALUE_ITERATOR_MIXIN [label="unique-value-iterator-mixin", ] ARITHMETIC_SEQUENCE_GENERATOR--FINITE_ARITHMETIC_SEQUENCE_GENERATOR [] BASIC_GENERATOR--ARITHMETIC_SEQUENCE_GENERATOR [] FORWARD_ITERATOR--BASIC_GENERATOR [] LIST_ITERATOR--HASH_TABLE_ITERATOR [] LIST_ITERATOR--CIRCULAR_ITERATOR_MIXIN_AND_LIST_ITERATOR [] FORWARD_ITERATOR--LIST_ITERATOR [] BASIC_STREAM_ITERATOR--FILE_LINE_ITERATOR [] BASIC_STREAM_ITERATOR--FILE_ITERATOR [] FORWARD_ITERATOR--BASIC_STREAM_ITERATOR [] BASIC_ITERATOR--FORWARD_ITERATOR [] ABSTRACT_GENERATOR--BASIC_ITERATOR [] FORWARD_ITERATOR--WORD_ITERATOR [] CIRCULAR_ITERATOR_MIXIN--CIRCULAR_ITERATOR_MIXIN_AND_LIST_ITERATOR [] FORWARD_ITERATOR--ARRAY_ITERATOR [] BASIC_FILTERED_ITERATOR_MIXIN--FILTERED_ITERATOR_MIXIN [] BASIC_FILTERED_ITERATOR_MIXIN--UNIQUE_VALUE_ITERATOR_MIXIN [] }cl-containers-20170403-git/website/stuff/project-name000066400000000000000000000000161306646076300224060ustar00rootroot00000000000000cl-containers cl-containers-20170403-git/website/website.tmproj000066400000000000000000000107701306646076300216570ustar00rootroot00000000000000 currentDocument ../../shared/shared-links.md documents filename source/user-guide.md lastUsed 2008-10-12T17:02:00Z selected filename source/resources/user-guide.css lastUsed 2008-10-12T17:02:02Z filename ../dev/container-api.lisp lastUsed 2008-10-12T14:43:50Z filename ../../shared/shared-links.md lastUsed 2010-12-21T13:19:58Z filename source/index.md lastUsed 2010-12-21T13:19:58Z expanded name resources regexFolderFilter !.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$ sourceDirectory source/resources fileHierarchyDrawerWidth 224 metaData ../../shared/shared-links.md caret column 0 line 0 firstVisibleColumn 0 firstVisibleLine 32 ../dev/container-api.lisp caret column 0 line 160 firstVisibleColumn 0 firstVisibleLine 123 source/index.md caret column 62 line 99 columnSelection firstVisibleColumn 0 firstVisibleLine 0 selectFrom column 9 line 99 selectTo column 62 line 99 source/resources/footer.md caret column 25 line 8 firstVisibleColumn 0 firstVisibleLine 0 source/resources/header.md caret column 0 line 1 columnSelection firstVisibleColumn 0 firstVisibleLine 0 selectFrom column 0 line 0 selectTo column 0 line 1 source/resources/ug-footer.md caret column 37 line 10 firstVisibleColumn 0 firstVisibleLine 0 source/resources/ug-header.md caret column 0 line 14 firstVisibleColumn 0 firstVisibleLine 0 openDocuments source/index.md ../../shared/shared-links.md source/resources/header.md ../dev/container-api.lisp showFileHierarchyDrawer windowFrame {{239, 0}, {684, 778}}