;;; Copyright (C) 2005-2008 by Chongkai Zhu. (module vector-lib mzscheme (require srfi/8/receive mzlib/etc mzlib/contract) (define mutable-vector/c (and/c vector? (not/c immutable?))) (define index/c (and/c natural-number/c exact?)) (define (vec-start-end-contract vector?) (case-> (-> vector? any) (->r ((vec vector?) (start (and/c index/c (<=/c (vector-length vec))))) any) (->pp ((vec vector?) (start index/c) (end index/c)) (<= start end (vector-length vec)) any))) ;;; (%SMALLEST-LENGTH ) ;;; -> exact, nonnegative integer ;;; Compute the smallest length of VECTOR-LIST. DEFAULT-LENGTH is ;;; the length that is returned if VECTOR-LIST is empty. Common use ;;; of this is in n-ary vector routines: ;;; (define (f vec . vectors) (define (%smallest-length vector-list length) (if (null? vector-list) length (%smallest-length (cdr vector-list) (min length (vector-length (car vector-list)))))) (define (vectors-ref vectors i) (map (lambda (v) (vector-ref v i)) vectors)) ;;; from vector-unfold-right (define (unfold1! f vec i seed) (if (>= i 0) (receive (elt new-seed) (f i seed) (vector-set! vec i elt) (unfold1! f vec (sub1 i) new-seed)))) (define unfold-contract (->r ((f (lambda (f) (and (procedure? f) (procedure-arity-includes? f (add1 (length seeds)))))) (len index/c)) seeds list? any)) (define copy-contract (case-> (-> vector? any) (->r ((vec vector?) (start (and/c index/c (<=/c (vector-length vec))))) any) (->r ((vec vector?) (start (and/c index/c (<=/c (vector-length vec)))) (end (and/c index/c (>=/c start)))) any) (->r ((vec vector?) (start (and/c index/c (<=/c (vector-length vec)))) (end (and/c index/c (>=/c start))) (fill any/c)) any))) (provide/contract (vector-unfold unfold-contract) (vector-unfold-right unfold-contract) (vector-copy copy-contract) (vector-reverse-copy (vec-start-end-contract vector?)) (vector-append (->* () (listof vector?) any)) (vector-concatenate (-> (listof vector?) any))) ;;; (VECTOR-UNFOLD ...) -> vector ;;; (F ...) -> [elt seed' ...] ;;; The fundamental vector constructor. Creates a vector whose ;;; length is LENGTH and iterates across each index K between 0 and ;;; LENGTH, applying F at each iteration to the current index and the ;;; current seeds to receive N+1 values: first, the element to put in ;;; the Kth slot and then N new seeds for the next iteration. (define vector-unfold (letrec ((tabulate! ; Special zero-seed case. (lambda (f vec i len) (cond ((< i len) (vector-set! vec i (f i)) (tabulate! f vec (add1 i) len))))) (unfold1! ; Fast path for one seed. (lambda (f vec i len seed) (if (< i len) (receive (elt new-seed) (f i seed) (vector-set! vec i elt) (unfold1! f vec (add1 i) len new-seed))))) (unfold2+! ; Slower variant for N seeds. (lambda (f vec i len seeds) (if (< i len) (receive (elt . new-seeds) (apply f i seeds) (vector-set! vec i elt) (unfold2+! f vec (add1 i) len new-seeds)))))) (lambda (f len . initial-seeds) (let ((vec (make-vector len))) (cond ((null? initial-seeds) (tabulate! f vec 0 len)) ((null? (cdr initial-seeds)) (unfold1! f vec 0 len (car initial-seeds))) (else (unfold2+! f vec 0 len initial-seeds))) vec)))) ;;; (VECTOR-UNFOLD-RIGHT ...) -> vector ;;; (F ...) -> [seed' ...] ;;; Like VECTOR-UNFOLD, but it generates elements from LENGTH to 0 ;;; (still exclusive with LENGTH and inclusive with 0), not 0 to ;;; LENGTH as with VECTOR-UNFOLD. (define vector-unfold-right (letrec ((tabulate! (lambda (f vec i) (cond ((>= i 0) (vector-set! vec i (f i)) (tabulate! f vec (sub1 i)))))) (unfold2+! (lambda (f vec i seeds) (if (>= i 0) (receive (elt . new-seeds) (apply f i seeds) (vector-set! vec i elt) (unfold2+! f vec (sub1 i) new-seeds)))))) (lambda (f len . initial-seeds) (let ((vec (make-vector len)) (i (sub1 len))) (cond ((null? initial-seeds) (tabulate! f vec i)) ((null? (cdr initial-seeds)) (unfold1! f vec i (car initial-seeds))) (else (unfold2+! f vec i initial-seeds))) vec)))) ;;; (VECTOR-COPY [ ]) -> vector ;;; Create a newly allocated vector containing the elements from the ;;; range [START,END) in VECTOR. START defaults to 0; END defaults ;;; to the length of VECTOR. END may be greater than the length of ;;; VECTOR, in which case the vector is enlarged; if FILL is passed, ;;; the new locations from which there is no respective element in ;;; VECTOR are filled with FILL. (define vector-copy (opt-lambda (vec (start 0) (end (vector-length vec)) (fill 0)) (let ((new-vector (make-vector (- end start) fill))) (vector-copy! new-vector 0 vec start (min end (vector-length vec))) new-vector))) ;;; (VECTOR-REVERSE-COPY [ ]) -> vector ;;; Create a newly allocated vector whose elements are the reversed ;;; sequence of elements between START and END in VECTOR. START's ;;; default is 0; END's default is the length of VECTOR. (define vector-reverse-copy (opt-lambda (vec (start 0) (end (vector-length vec))) (let ((new (make-vector (- end start)))) (vector-reverse-copy! new 0 vec start end) new))) ;;; (VECTOR-APPEND ...) -> vector ;;; Append VECTOR ... into a newly allocated vector and return that ;;; new vector. (define (vector-append . vectors) (vector-concatenate vectors)) ;;; (VECTOR-CONCATENATE ) -> vector ;;; Concatenate the vectors in VECTOR-LIST. This is equivalent to ;;; (apply vector-append VECTOR-LIST) ;;; Actually, they're both implemented in terms of an internal routine. (define vector-concatenate (letrec ((compute-length (lambda (vectors len) (if (null? vectors) len (let ((vec (car vectors))) (compute-length (cdr vectors) (+ (vector-length vec) len)))))) (concatenate! (lambda (vectors target to) (if (null? vectors) target (let* ((vec1 (car vectors)) (len (vector-length vec1))) (vector-copy! target to vec1 0 len) (concatenate! (cdr vectors) target (+ to len))))))) (lambda (vectors) (let ((new-vector (make-vector (compute-length vectors 0)))) (concatenate! vectors new-vector 0) new-vector)))) (provide/contract (vector-empty? (-> vector? any)) (vector= (->* ((-> any/c any/c any)) (listof vector?) any))) ;;; (VECTOR-EMPTY? ) -> boolean ;;; Return #T if VECTOR has zero elements in it, i.e. VECTOR's length ;;; is 0, and #F if not. (define (vector-empty? vec) (zero? (vector-length vec))) ;;; (VECTOR= ...) -> boolean ;;; (ELT=? ) -> boolean ;;; Determine vector equality generalized across element comparators. ;;; Vectors A and B are equal iff their lengths are the same and for ;;; each respective elements E_a and E_b (element=? E_a E_b) returns ;;; a true value. ELT=? is always applied to two arguments. Element ;;; comparison must be consistent wtih EQ?; that is, if (eq? E_a E_b) ;;; results in a true value, then (ELEMENT=? E_a E_b) must result in a ;;; true value. This may be exploited to avoid multiple unnecessary ;;; element comparisons. (This implementation does, but does not deal ;;; with the situation that ELEMENT=? is EQ? to avoid more unnecessary ;;; comparisons, but I believe this optimization is probably fairly ;;; insignificant.) ;;; ;;; If the number of vector arguments is zero or one, then #T is ;;; automatically returned. If there are N vector arguments, ;;; VECTOR_1 VECTOR_2 ... VECTOR_N, then VECTOR_1 & VECTOR_2 are ;;; compared; if they are equal, the vectors VECTOR_2 ... VECTOR_N ;;; are compared. The precise order in which ELT=? is applied is not ;;; specified. (define (vector= elt=? . vectors) (or (null? vectors) (null? (cdr vectors)) (let loop ((vecs vectors)) (let ((vec1 (car vecs)) (vec2+ (cdr vecs))) (or (null? vec2+) (and (binary-vector= elt=? vec1 (car vec2+)) (loop vec2+))))))) (define (binary-vector= elt=? vector-a vector-b) (or (eq? vector-a vector-b) ;+++ (let ((length-a (vector-length vector-a))) (and (= length-a (vector-length vector-b)) (let loop ((i 0)) (or (= i length-a) (and (elt=? (vector-ref vector-a i) (vector-ref vector-b i)) (loop (add1 i))))))))) (define fold-contract (->r ((kons (lambda (f) (and (procedure? f) (procedure-arity-includes? f (+ 3 (length vec)))))) (knil any/c) (vec1 vector?)) vec (listof vector?) any)) (define (map-contract m) (->r ((f (lambda (f) (and (procedure? f) (procedure-arity-includes? f (+ 2 (length vec)))))) (vec1 m)) vec (listof vector?) any)) (provide/contract (vector-fold fold-contract) (vector-fold-right fold-contract) (vector-map (map-contract vector?)) (vector-map! (map-contract mutable-vector/c)) (vector-for-each (map-contract vector?)) (vector-count (map-contract vector?))) ;;; (VECTOR-FOLD ...) -> knil ;;; (KONS ...) -> knil' ; N vectors -> N+1 args ;;; The fundamental vector iterator. KONS is iterated over each ;;; index in all of the vectors in parallel, stopping at the end of ;;; the shortest; KONS is applied to an argument list of (list I ;;; STATE (vector-ref VEC I) ...), where STATE is the current state ;;; value -- the state value begins with KNIL and becomes whatever ;;; KONS returned at the respective iteration --, and I is the ;;; current index in the iteration. The iteration is strictly left- ;;; to-right. ;;; (vector-fold KONS KNIL (vector E_1 E_2 ... E_N)) ;;; <=> ;;; (KONS (... (KONS (KONS KNIL E_1) E_2) ... E_N-1) E_N) (define (vector-fold kons knil vec . vectors) (if (null? vectors) (%vector-fold1 kons knil (vector-length vec) vec) (%vector-fold2+ kons knil (%smallest-length vectors (vector-length vec)) (cons vec vectors)))) (define %vector-fold1 (letrec ((loop (lambda (kons knil len vec i) (if (= i len) knil (loop kons (kons i knil (vector-ref vec i)) len vec (add1 i)))))) (lambda (kons knil len vec) (loop kons knil len vec 0)))) (define %vector-fold2+ (letrec ((loop (lambda (kons knil len vectors i) (if (= i len) knil (loop kons (apply kons i knil (vectors-ref vectors i)) len vectors (add1 i)))))) (lambda (kons knil len vectors) (loop kons knil len vectors 0)))) ;;; (VECTOR-COUNT ...) ;;; -> exact, nonnegative integer ;;; (PREDICATE? ...) ; N vectors -> N+1 args ;;; PREDICATE? is applied element-wise to the elements of VECTOR ..., ;;; and a count is tallied of the number of elements for which a ;;; true value is produced by PREDICATE?. This count is returned. (define (vector-count pred? vec . vectors) (if (null? vectors) (%vector-fold1 (lambda (index count elt) (if (pred? index elt) (add1 count) count)) 0 (vector-length vec) vec) (%vector-fold2+ (lambda (index count . elts) (if (apply pred? index elts) (add1 count) count)) 0 (%smallest-length vectors (vector-length vec)) (cons vec vectors)))) ;;; (VECTOR-FOLD-RIGHT ...) -> knil ;;; (KONS ...) -> knil' ; N vectors => N+1 args ;;; The fundamental vector recursor. Iterates in parallel across ;;; VECTOR ... right to left, applying KONS to the elements and the ;;; current state value; the state value becomes what KONS returns ;;; at each next iteration. KNIL is the initial state value. ;;; (vector-fold-right KONS KNIL (vector E_1 E_2 ... E_N)) ;;; <=> ;;; (KONS (... (KONS (KONS KNIL E_N) E_N-1) ... E_2) E_1) ;;; ;;; Not implemented in terms of a more primitive operations that might ;;; called %VECTOR-FOLD-RIGHT due to the fact that it wouldn't be very ;;; useful elsewhere. (define vector-fold-right (letrec ((loop1 (lambda (kons knil vec i) (if (zero? i) knil (let ((j (sub1 i))) (loop1 kons (kons j knil (vector-ref vec j)) vec j))))) (loop2+ (lambda (kons knil vectors i) (if (zero? i) knil (let ((j (sub1 i))) (loop2+ kons (apply kons j knil (vectors-ref vectors j)) vectors j)))))) (lambda (kons knil vec . vectors) (if (null? vectors) (loop1 kons knil vec (vector-length vec)) (loop2+ kons knil (cons vec vectors) (%smallest-length vectors (vector-length vec))))))) ;;; (VECTOR-MAP ...) -> vector ;;; (F ...) -> value ; N vectors -> N args ;;; Constructs a new vector of the shortest length of the vector ;;; arguments. Each element at index I of the new vector is mapped ;;; from the old vectors by (F I (vector-ref VECTOR I) ...). The ;;; dynamic order of application of F is unspecified. (define (vector-map f vec . vectors) (if (null? vectors) (let ((len (vector-length vec))) (%vector-map1! f (make-vector len) vec len)) (let ((len (%smallest-length vectors (vector-length vec)))) (%vector-map2+! f (make-vector len) (cons vec vectors) len)))) ;;; (%VECTOR-MAP1! ) ;;; (F ) -> elt' (define (%vector-map1! f target vec i) (if (zero? i) target (let ((j (sub1 i))) (vector-set! target j (f j (vector-ref vec j))) (%vector-map1! f target vec j)))) (define (%vector-map2+! f target vectors i) (if (zero? i) target (let ((j (sub1 i))) (vector-set! target j (apply f j (vectors-ref vectors j))) (%vector-map2+! f target vectors j)))) ;;; (VECTOR-MAP! ...) -> vector ;;; (F ...) -> element' ; N vectors -> N args ;;; Similar to VECTOR-MAP, but rather than mapping the new elements ;;; into a new vector, the new mapped elements are destructively ;;; inserted into the first vector. Again, the dynamic order of ;;; application of F is unspecified, so it is dangerous for F to ;;; manipulate the first VECTOR. (define (vector-map! f vec . vectors) (if (null? vectors) (%vector-map1! f vec vec (vector-length vec)) (%vector-map2+! f vec (cons vec vectors) (%smallest-length vectors (vector-length vec))))) ;;; (VECTOR-FOR-EACH ...) -> void ;;; (F ...) ; N vectors -> N args ;;; Simple vector iterator: applies F to each index in the range [0, ;;; LENGTH), where LENGTH is the length of the smallest vector ;;; argument passed, and the respective element at that index. In ;;; contrast with VECTOR-MAP, F is reliably applied to each ;;; subsequent elements, starting at index 0 from left to right, in ;;; the vectors. (define vector-for-each (letrec ((for-each1 (lambda (f vec i len) (when (< i len) (f i (vector-ref vec i)) (for-each1 f vec (add1 i) len)))) (for-each2+ (lambda (f vecs i len) (when (< i len) (apply f i (vectors-ref vecs i)) (for-each2+ f vecs (add1 i) len))))) (lambda (f vec . vectors) (if (null? vectors) (for-each1 f vec 0 (vector-length vec)) (for-each2+ f (cons vec vectors) 0 (%smallest-length vectors (vector-length vec))))))) (define index-contract (->r ((f (lambda (f) (and (procedure? f) (procedure-arity-includes? f (add1 (length vec)))))) (vec1 vector?)) vec (listof vector?) any)) (provide/contract (vector-index index-contract) (vector-index-right index-contract) (vector-skip index-contract) (vector-skip-right index-contract) (vector-binary-search (-> vector? any/c (-> any/c any/c real?) any)) (vector-any index-contract) (vector-every index-contract)) ;; All the functions (except vector-binary-search) here can be ;; abstracted, but for performance I didn't do so. ;;; (VECTOR-INDEX ...) ;;; -> exact, nonnegative integer or #F ;;; (PREDICATE? ...) -> boolean ; N vectors -> N args ;;; Search left-to-right across VECTOR ... in parallel, returning the ;;; index of the first set of values VALUE ... such that (PREDICATE? ;;; VALUE ...) returns a true value; if no such set of elements is ;;; reached, return #F. (define vector-index (letrec ((loop1 (lambda (pred? vec len i) (cond ((= i len) #f) ((pred? (vector-ref vec i)) i) (else (loop1 pred? vec len (add1 i)))))) (loop2+ (lambda (pred? vectors len i) (cond ((= i len) #f) ((apply pred? (vectors-ref vectors i)) i) (else (loop2+ pred? vectors len (add1 i))))))) (lambda (pred? vec . vectors) (if (null? vectors) (loop1 pred? vec (vector-length vec) 0) (loop2+ pred? (cons vec vectors) (%smallest-length vectors (vector-length vec)) 0))))) ;;; (VECTOR-SKIP ...) ;;; -> exact, nonnegative integer or #F ;;; (PREDICATE? ...) -> boolean ; N vectors -> N args ;;; (vector-index (lambda elts (not (apply PREDICATE? elts))) ;;; VECTOR ...) ;;; Like VECTOR-INDEX, but find the index of the first set of values ;;; that do _not_ satisfy PREDICATE?. (define vector-skip (letrec ((loop1 (lambda (pred? vec len i) (cond ((= i len) #f) ((pred? (vector-ref vec i)) (loop1 pred? vec len (add1 i))) (else i)))) (loop2+ (lambda (pred? vectors len i) (cond ((= i len) #f) ((apply pred? (vectors-ref vectors i)) (loop2+ pred? vectors len (add1 i))) (else i))))) (lambda (pred? vec . vectors) (if (null? vectors) (loop1 pred? vec (vector-length vec) 0) (loop2+ pred? (cons vec vectors) (%smallest-length vectors (vector-length vec)) 0))))) ;;; (VECTOR-INDEX-RIGHT ...) ;;; -> exact, nonnegative integer or #F ;;; (PREDICATE? ...) -> boolean ; N vectors -> N args ;;; Right-to-left variant of VECTOR-INDEX. (define vector-index-right (letrec ((loop1 (lambda (pred? vec i) (if (zero? i) #f (let ((i (sub1 i))) (if (pred? (vector-ref vec i)) i (loop1 pred? vec i)))))) (loop2+ (lambda (pred? vectors i) (if (zero? i) #f (let ((i (sub1 i))) (if (apply pred? (vectors-ref vectors i)) i (loop2+ pred? vectors i))))))) (lambda (pred? vec . vectors) (if (null? vectors) (loop1 pred? vec (vector-length vec)) (loop2+ pred? (cons vec vectors) (%smallest-length vectors (vector-length vec))))))) ;;; (VECTOR-SKIP-RIGHT ...) ;;; -> exact, nonnegative integer or #F ;;; (PREDICATE? ...) -> boolean ; N vectors -> N args ;;; Right-to-left variant of VECTOR-SKIP. (define vector-skip-right (letrec ((loop1 (lambda (pred? vec i) (if (zero? i) #f (let ((i (sub1 i))) (if (pred? (vector-ref vec i)) (loop1 pred? vec i) i))))) (loop2+ (lambda (pred? vectors i) (if (zero? i) #f (let ((i (sub1 i))) (if (apply pred? (vectors-ref vectors i)) (loop2+ pred? vectors i) i)))))) (lambda (pred? vec . vectors) (if (null? vectors) (loop1 pred? vec (vector-length vec)) (loop2+ pred? (cons vec vectors) (%smallest-length vectors (vector-length vec))))))) ;;; (VECTOR-BINARY-SEARCH ) ;;; -> exact, nonnegative integer or #F ;;; (CMP ) -> integer ;;; positive -> VALUE1 > VALUE2 ;;; zero -> VALUE1 = VALUE2 ;;; negative -> VALUE1 < VALUE2 ;;; Perform a binary search through VECTOR for VALUE, comparing each ;;; element to VALUE with CMP. (define (vector-binary-search vec value cmp) (let loop ((start 0) (end (vector-length vec))) (if (= start end) #f (let* ((i (quotient (+ start end) 2)) (comparison (cmp (vector-ref vec i) value))) (cond ((zero? comparison) i) ((positive? comparison) (loop start i)) (else (loop (add1 i) end))))))) ;;; (VECTOR-ANY ...) -> value ;;; Apply PRED? to each parallel element in each VECTOR ...; if PRED? ;;; should ever return a true value, immediately stop and return that ;;; value; otherwise, when the shortest vector runs out, return #F. ;;; The iteration and order of application of PRED? across elements ;;; is of the vectors is strictly left-to-right. (define vector-any (letrec ((loop1 (lambda (pred? vec i len) (and (not (= i len)) (or (pred? (vector-ref vec i)) (loop1 pred? vec (add1 i) len))))) (loop2+ (lambda (pred? vectors i len) (and (not (= i len)) (or (apply pred? (vectors-ref vectors i)) (loop2+ pred? vectors (add1 i) len)))))) (lambda (pred? vec . vectors) (if (null? vectors) (loop1 pred? vec 0 (vector-length vec)) (loop2+ pred? (cons vec vectors) 0 (%smallest-length vectors (vector-length vec))))))) ;;; (VECTOR-EVERY ...) -> value ;;; Apply PRED? to each parallel value in each VECTOR ...; if PRED? ;;; should ever return #F, immediately stop and return #F; otherwise, ;;; if PRED? should return a true value for each element, stopping at ;;; the end of the shortest vector, return the last value that PRED? ;;; returned. In the case that there is an empty vector, return #T. ;;; The iteration and order of application of PRED? across elements ;;; is of the vectors is strictly left-to-right. (define vector-every (letrec ((loop1 (lambda (pred? vec i len) (or (> i len) (if (= i len) (pred? (vector-ref vec i)) (and (pred? (vector-ref vec i)) (loop1 pred? vec (add1 i) len)))))) (loop2+ (lambda (pred? vectors i len) (or (> i len) (if (= i len) (apply pred? (vectors-ref vectors i)) (and (apply pred? (vectors-ref vectors i)) (loop2+ pred? vectors (add1 i) len))))))) (lambda (pred? vec . vectors) (if (null? vectors) (loop1 pred? vec 0 (sub1 (vector-length vec))) (loop2+ pred? (cons vec vectors) 0 (sub1 (%smallest-length vectors (vector-length vec)))))))) (define copy!-contract (case-> (->r ((target mutable-vector/c) (tstart (and/c index/c (<=/c (- (vector-length target) (vector-length source))))) (source vector?)) any) (->r ((target mutable-vector/c) (tstart (and/c index/c (<=/c (- (vector-length target) (- (vector-length source) sstart))))) (source vector?) (sstart (and/c index/c (<=/c (vector-length source))))) any) (->pp ((target mutable-vector/c) (tstart (and/c index/c (<=/c (- (vector-length target) (- send sstart))))) (source vector?) (sstart index/c) (send index/c)) (<= sstart send (vector-length source)) any))) (provide/contract (vector-swap! (->r ((vec mutable-vector/c) (i (and/c index/c ( (-> vector? any/c any) (->r ((vec vector?) (fill any/c) (start (and/c index/c (<=/c (vector-length vec))))) any) (->pp ((vec vector?) (fill any/c) (start index/c) (end index/c)) (<= start end (vector-length vec)) any))) (vector-reverse! (vec-start-end-contract mutable-vector/c)) (vector-copy! copy!-contract) (vector-reverse-copy! copy!-contract)) ;;; (VECTOR-SWAP! ) -> void ;;; Swap the values in the locations at INDEX1 and INDEX2. (define (vector-swap! vec i j) (let ((x (vector-ref vec i))) (vector-set! vec i (vector-ref vec j)) (vector-set! vec j x))) ;;; (VECTOR-FILL! [ ]) -> ;;; [R5RS+] Fill the locations in VECTOR between START, whose default ;;; is 0, and END, whose default is the length of VECTOR, with VALUE. ;;; ;;; This one can probably be made really fast natively. (define my-vector-fill! (case-lambda ((vec value) (vector-fill! vec value)) ((vec value start) (my-vector-fill! vec value start (vector-length vec))) ((vec value start end) (do ((i start (add1 i))) ((= i end)) (vector-set! vec i value)) vec))) ;;; (VECTOR-REVERSE! [ ]) -> void ;;; Destructively reverse the contents of the sequence of locations ;;; in VECTOR between START, whose default is 0, and END, whose ;;; default is the length of VECTOR. (define vector-reverse! (letrec ((loop (lambda (vec i j) (when (< i j) (vector-swap! vec i j) (loop vec (add1 i) (sub1 j)))))) (opt-lambda (vec (start 0) (end (vector-length vec))) (loop vec start (sub1 end))))) ;;; (VECTOR-COPY! [ ]) ;;; -> unspecified ;;; Copy the values in the locations in [SSTART,SEND) from SOURCE to ;;; to TARGET, starting at TSTART in TARGET. (define vector-copy! (letrec ((loop/l->r (lambda (target source send i j) (cond ((< i send) (vector-set! target j (vector-ref source i)) (loop/l->r target source send (add1 i) (add1 j)))))) (loop/r->l (lambda (target source sstart i j) (cond ((>= i sstart) (vector-set! target j (vector-ref source i)) (loop/r->l target source sstart (sub1 i) (sub1 j))))))) (opt-lambda (target tstart source (sstart 0) (send (vector-length source))) (if (> sstart tstart) ; Make sure we don't copy over ; ourselves. (loop/l->r target source send sstart tstart) (loop/r->l target source sstart (sub1 send) (+ -1 tstart send (- sstart))))))) ;;; (VECTOR-REVERSE-COPY! [ ]) (define vector-reverse-copy! (letrec ((loop (lambda (target source sstart i j) (cond ((>= i sstart) (vector-set! target j (vector-ref source i)) (loop target source sstart (sub1 i) (add1 j))))))) (opt-lambda (target tstart source (sstart 0) (send (vector-length source))) (cond ((and (eq? target source) (= sstart tstart)) (vector-reverse! target tstart send)) ((and (eq? target source) (or (between? sstart tstart send) (between? tstart sstart (+ tstart (- send sstart))))) ;an error in the reference implement here (error 'vector-reverse-copy! "Vector range for self-copying overlaps")) (else (loop target source sstart (sub1 send) tstart)))))) (define (between? x y z) (and (< x y) (<= y z))) (provide/contract (rename my-vector->list s:vector->list (vec-start-end-contract vector?)) (reverse-vector->list vec-start-end-contract) (reverse-list->vector (-> list? any))) ;;; (VECTOR->LIST [ ]) -> list ;;; [R5RS+] Produce a list containing the elements in the locations ;;; between START, whose default is 0, and END, whose default is the ;;; length of VECTOR, from VECTOR. (define my-vector->list (case-lambda ((vec) (vector->list vec)) ;+++ ((vec start) (my-vector->list vec start (vector-length vec))) ((vec start end) (do ((i (sub1 end) (sub1 i)) (result '() (cons (vector-ref vec i) result))) ((< i start) result))))) ;;; (REVERSE-VECTOR->LIST [ ]) -> list ;;; Produce a list containing the elements in the locations between ;;; START, whose default is 0, and END, whose default is the length ;;; of VECTOR, from VECTOR, in reverse order. (define reverse-vector->list (opt-lambda (vec (start 0) (end (vector-length vec))) ;(unfold (lambda (i) (= i end)) ; No SRFI 1. ; (lambda (i) (vector-ref vec i)) ; (lambda (i) (add1 i)) ; start) (do ((i start (add1 i)) (result '() (cons (vector-ref vec i) result))) ((= i end) result)))) ;;; (REVERSE-LIST->VECTOR -> vector ;;; Produce a vector containing the elements in LIST in reverse order. (define (reverse-list->vector lst) (let* ((len (length lst)) (vec (make-vector len))) (unfold1! (lambda (index l) (values (car l) (cdr l))) vec (sub1 len) lst) vec)))