; Copyright (c) 1993-1999 by Richard Kelsey. See file COPYING. ; Vectors of infinite length. These work as do regular vectors except that ; they have no fixed size. XVECTOR-LENGTH is one more than the highest index ; that has been passed to XVECTOR-SET!. ; ; (MAKE-XVECTOR ) ; (XVECTOR-LENGTH ) ; (XVECTOR-REF ) ; (XVECTOR-SET! ) ; (XVECTOR->VECTOR ) ; The actual record fields are: ; default - the fill value ; length - total length of internal vector(s) ; contents - either: ; a: vector of entries, or ; b: vector of vectors of entries, vector has #f's after the last needed ; sub-vector, each sub-vector has length XVEC-MAX-CONTENTS-SIZE ; max - maximum index used in a XVECTOR-SET! (define-record-type expanding-vector :expanding-vector (make-expanding-vector default length contents max) expanding-vector? (default expanding-vector-default) (length expanding-vector-length set-expanding-vector-length!) (contents expanding-vector-contents set-expanding-vector-contents!) (max expanding-vector-max set-expanding-vector-max!)) (define (make-xvector default) (make-expanding-vector default 0 '#() -1)) ; Maximum size of any internal vector (define xvec-max-contents-size 1024) ; XVECTOR-LENGTH returns 1 + the maximum index passed to XVECTOR-SET! (define (xvector-length xvec) (+ 1 (expanding-vector-max xvec))) ; If INDEX points outside current storage, the default is returned, otherwise ; the value is extracted from the one-or-two-level contents vector. (define (xvector-ref xvec index) (let ((length (expanding-vector-length xvec))) (cond ((>= index length) (expanding-vector-default xvec)) ((<= length xvec-max-contents-size) (vector-ref (expanding-vector-contents xvec) index)) (else (vector-ref (vector-ref (expanding-vector-contents xvec) (quotient index xvec-max-contents-size)) (remainder index xvec-max-contents-size)))))) ; Same as the above, setting instead of extracting. INDEX is checked agains ; the maximum index, and the contents may have to be expanded. (define (xvector-set! xvec index value) (let ((length (expanding-vector-length xvec))) (if (> index (expanding-vector-max xvec)) (set-expanding-vector-max! xvec index)) (cond ((>= index length) (expand-expanding-vector xvec) (xvector-set! xvec index value)) ((<= length xvec-max-contents-size) (vector-set! (expanding-vector-contents xvec) index value)) (else (vector-set! (vector-ref (expanding-vector-contents xvec) (quotient index xvec-max-contents-size)) (remainder index xvec-max-contents-size) value))))) ; Copy an expanding vector into a regular vector. (define (xvector->vector xvec) (let ((new (make-vector (xvector-length xvec)))) (do ((i 0 (+ i 1))) ((>= i (xvector-length xvec))) (vector-set! new i (xvector-ref xvec i))) new)) ; Expand an expanding vector. A new length and contents are produced and ; put in XVEC. If LENGTH is below the maximum for a contents vector it is ; doubled in size. If the two-level structure is being used, a new sub- ; vector is added to it. (define (expand-expanding-vector xvec) (let ((length (expanding-vector-length xvec)) (contents (expanding-vector-contents xvec)) (default (expanding-vector-default xvec)) (finish (lambda (length contents) (set-expanding-vector-length! xvec length) (set-expanding-vector-contents! xvec contents)))) (if (< length xvec-max-contents-size) (let ((new (expand-vector contents default))) (finish (vector-length new) new)) (let ((contents (cond ((= length xvec-max-contents-size) (let ((new (make-vector 4 #f))) (vector-set! new 0 contents) new)) ((vector-ref contents (- (vector-length contents) 1)) (expand-vector contents #f)) (else contents)))) (vector-set! contents (quotient length xvec-max-contents-size) (make-vector xvec-max-contents-size default)) (finish (+ length xvec-max-contents-size) contents))))) ; Make a new vector twice the length of OLD and copy the contents of OLD into ; it. DEFAULT is used to fill in the other slots. (define (expand-vector old default) (let* ((length (vector-length old)) (new (make-vector (if (= 0 length) 4 (* 2 length)) default))) (do ((i 0 (+ i 1))) ((>= i length)) (vector-set! new i (vector-ref old i))) new))