;;; Copyright (C) 2005-2014 by Chongkai Zhu.
;;; Distributed under the same terms as Racket, by permission.

(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 <vector-list> <default-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 <f> <length> <initial-seed> ...) -> vector
  ;;;     (F <index> <seed> ...) -> [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 <f> <length> <initial-seed> ...) -> vector
  ;;;     (F <seed> ...) -> [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> [<start> <end> <fill>]) -> 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> [<start> <end>]) -> 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> ...) -> vector
  ;;;   Append VECTOR ... into a newly allocated vector and return that
  ;;;   new vector.
  (define (vector-append . vectors)
    (vector-concatenate vectors))
  
  ;;; (VECTOR-CONCATENATE <vector-list>) -> 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? <vector>) -> 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= <elt=?> <vector> ...) -> boolean
  ;;;     (ELT=? <value> <value>) -> 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 with 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 <kons> <initial-knil> <vector> ...) -> knil
  ;;;     (KONS <knil> <elt> ...) -> 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 <predicate?> <vector> ...)
  ;;;       -> exact, nonnegative integer
  ;;;     (PREDICATE? <index> <value> ...) ; 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 <kons> <initial-knil> <vector> ...) -> knil
  ;;;     (KONS <knil> <elt> ...) -> 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 <f> <vector> ...) -> vector
  ;;;     (F <elt> ...) -> 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> <target> <length> <vector>)
  ;;;     (F <index> <elt>) -> 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! <f> <vector> ...) -> vector
  ;;;     (F <elt> ...) -> 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 <f> <vector> ...) -> void
  ;;;     (F <elt> ...) ; 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 <predicate?> <vector> ...)
  ;;;       -> exact, nonnegative integer or #F
  ;;;     (PREDICATE? <elt> ...) -> 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 <predicate?> <vector> ...)
  ;;;       -> exact, nonnegative integer or #F
  ;;;     (PREDICATE? <elt> ...) -> 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 <predicate?> <vector> ...)
  ;;;       -> exact, nonnegative integer or #F
  ;;;     (PREDICATE? <elt> ...) -> 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 <predicate?> <vector> ...)
  ;;;       -> exact, nonnegative integer or #F
  ;;;     (PREDICATE? <elt> ...) -> 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 <vector> <value> <cmp>)
  ;;;       -> exact, nonnegative integer or #F
  ;;;     (CMP <value1> <value2>) -> 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 <pred?> <vector> ...) -> 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 <pred?> <vector> ...) -> 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
                                     (</c (vector-length vec))))
                           (j (and/c index/c
                                     (</c (vector-length vec)))))
                          any))
                    (rename my-vector-fill! s:vector-fill!
                            (case->
                             (-> 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! <vector> <index1> <index2>) -> 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! <vector> <value> [<start> <end>]) -> <vector>
  ;;;   [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! <vector> [<start> <end>]) -> 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! <target> <tstart> <source> [<sstart> <send>])
  ;;;       -> 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! <target> <tstart> <source> [<sstart> <send>])
  (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 <vector> [<start> <end>]) -> 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 <vector> [<start> <end>]) -> 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 <list> -> 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)))
