
;;--------------------------------------------------------------------
;; s8vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc s8vector? (obj) ::<boolean> SCM_S8VECTORP)

(define-cproc s8vector-empty? (v::<s8vector>) ::<boolean>
  (return (== (SCM_S8VECTOR_SIZE v) 0)))

(define-cproc make-s8vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (int8_t)])
    (C: "filler = (int8_t)Scm_GetInteger8Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeS8Vector length filler))))

(define-cproc s8vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToS8Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_S8VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc s8vector-length (v::<s8vector>) ::<ulong> SCM_S8VECTOR_SIZE)

(define-cproc s8vector-copy
  (v::<s8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S8VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc s8vector-copy!
  (dst::<s8vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_S8VECTORP src)
      (Scm_Error "s8vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_S8VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_S8VECTOR src) sstart send))]
   [(SCM_S8VECTORP dstart) ; old API
    (return (Scm_S8VectorCopyX dst 0 (SCM_S8VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc s8vector-reverse-copy 
  (v::<s8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeS8Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_S8VECTOR_ELEMENT r j) (SCM_S8VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc s8vector-reverse-copy!
  (dst::<s8vector> dstart::<fixnum> src::<s8vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_S8VECTOR_ELEMENT dst dend) 
            (SCM_S8VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc s8vector-multi-copy!
  (dst::<s8vector> dstart::<fixnum> dstride::<fixnum>
   src::<s8vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_S8VECTOR_ELEMENT dst di)
                 (SCM_S8VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_S8VECTOR_ELEMENTS dst) di)
                      (+ (SCM_S8VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type int8_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc s8vector->list
  (v::<s8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S8VectorToList)

(define-cproc reverse-s8vector->list
  (v::<s8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(int8_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_S8VECTOR_ELEMENT v end))
      (C: "z = SCM_MAKE_INT(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->s8vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_S8VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->s8vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-s8vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (s8vector-set! v i (car l) clamp))))

(define-cproc s8vector-fill!
  (v::<s8vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (int8_t)])
    (C: "filler = (int8_t)Scm_GetInteger8Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_S8VectorFill v filler start end)))

(define-cproc s8vector->vector
  (v::<s8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S8VectorToVector)

(define-cproc vector->s8vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToS8Vector v start end (Scm_ClampMode clamp))))

(define-cproc s8vector=?              ; srfi-66
  (a::<s8vector> b::<s8vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc s8vector-compare        ; srfi-66
  (a::<s8vector> b::<s8vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (s8vector-unfold f len seed)
  (let1 rvec (make-s8vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (s8vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (s8vector-unfold-right f len seed)
  (let1 rvec (make-s8vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (s8vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (s8vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (s8vector-length v) l)) 0 vs)]
         [dst  (make-s8vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (s8vector-length (car vs)))])
        [(null? vs) dst]
      (s8vector-copy! dst k (car vs)))))
(define (s8vector-append . vs) (s8vector-concatenate vs))

(define-cproc s8vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_S8VECTORP v)
          (Scm_Error "<s8vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_S8VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeS8Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_S8VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_S8VECTOR_ELEMENT r i)
                    (SCM_S8VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (s8vector-take v n) (s8vector-copy v 0 n))
(define (s8vector-take-right v n)
  (s8vector-copy v (- (s8vector-length v) n)))
(define (s8vector-drop v n) (s8vector-copy v n))
(define (s8vector-drop-right v n)
  (s8vector-copy v 0 (- (s8vector-length v) n)))
(define (s8vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (s8vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (s8vector-copy v i (+ i n)) vs))))
  (rec 0 (s8vector-length v) '()))
(define (s8vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (s8vector=? a b)
       (or (null? rest)
           (apply s8vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (s8vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (s8vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (s8vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (s8vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (s8vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (s8vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (s8vector-ref vec i)) rs)])
          [(= i len) (list->s8vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->s8vector (reverse rs))]))))
(define (s8vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s8vector-set! vec i (proc (s8vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s8vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (s8vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (s8vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (s8vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (s8vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (s8vector-cumulate proc knil vec)
  (let* ([len (s8vector-length vec)]
         [rvec (make-s8vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (s8vector-ref vec i))
                 (s8vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (s8vector-take-while pred vec)
  (let1 len (s8vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->s8vector (reverse r))
        (let1 e (s8vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->s8vector (reverse r))))))))
(define (s8vector-take-while-right pred vec)
  (let1 len (s8vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->s8vector r)
        (let1 e (s8vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->s8vector r)))))))
(define (s8vector-drop-while pred vec)
  (let1 len (s8vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-s8vector 0)
        (let1 e (s8vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (s8vector-copy vec i)))))))
(define (s8vector-drop-while-right pred vec)
  (let1 len (s8vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-s8vector 0)
        (let1 e (s8vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (s8vector-copy vec 0 (+ i 1))))))))

(define (s8vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s8vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (s8vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s8vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (s8vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s8vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (s8vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s8vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (s8vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s8vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (s8vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (s8vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (s8vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (s8vector-partition pred vec)
  (let1 len (s8vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-s8vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (s8vector-set! rvec i (car rs)))
        (let1 e (s8vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (s8vector-filter pred vec)
  (let1 len (s8vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s8vector (reverse rs))
        (let1 e (s8vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (s8vector-remove pred vec)
  (let1 len (s8vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s8vector (reverse rs))
        (let1 e (s8vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc s8vector-swap! (v::<s8vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_S8VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_S8VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(int8_t) (SCM_S8VECTOR_ELEMENT v i)])
    (set! (SCM_S8VECTOR_ELEMENT v i) (SCM_S8VECTOR_ELEMENT v j))
    (set! (SCM_S8VECTOR_ELEMENT v j) e)))

(define-cproc s8vector-reverse!
 (v::<s8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_S8VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(int8_t)])
      (while (< i j)
        (set! e (SCM_S8VECTOR_ELEMENT v i))
        (set! (SCM_S8VECTOR_ELEMENT v i) (SCM_S8VECTOR_ELEMENT v j))
        (set! (SCM_S8VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (s8vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (s8vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (s8vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (s8vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-s8vector-generator vec)
  (assume-type vec <s8vector>)
  (uvector->generator vec))

;; Comparator

(define s8vector-comparator
  (make-comparator s8vector? s8vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-s8vector vec :optional (port (current-output-port)))
  (assume-type vec <s8vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <s8vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-s8vector size)] [i 0])
      (proc (^[item] (s8vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->s8vector q))))
    ))

(define-method referencer ((v <s8vector>)) s8vector-ref)
(define-method modifier   ((v <s8vector>)) s8vector-set!)
(define-method size-of    ((v <s8vector>)) (s8vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <s8vector>))
  (s8vector->list v))
(define-method coerce-to  ((c <s8vector-meta>) (v <list>))
  (list->s8vector v))
(define-method coerce-to  ((c <vector-meta>) (v <s8vector>))
  (s8vector->vector v))
(define-method coerce-to  ((c <s8vector-meta>) (v <vector>))
  (vector->s8vector v))
(define-method coerce-to  ((c <s8vector-meta>) (v <s8vector>))
  (s8vector-copy v))
(define-method subseq ((v <s8vector>) . args)
  (apply s8vector-copy v args))



;;--------------------------------------------------------------------
;; u8vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc u8vector? (obj) ::<boolean> SCM_U8VECTORP)

(define-cproc u8vector-empty? (v::<u8vector>) ::<boolean>
  (return (== (SCM_U8VECTOR_SIZE v) 0)))

(define-cproc make-u8vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (uint8_t)])
    (C: "filler = (uint8_t)Scm_GetIntegerU8Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeU8Vector length filler))))

(define-cproc u8vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToU8Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_U8VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc u8vector-length (v::<u8vector>) ::<ulong> SCM_U8VECTOR_SIZE)

(define-cproc u8vector-copy
  (v::<u8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U8VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc u8vector-copy!
  (dst::<u8vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_U8VECTORP src)
      (Scm_Error "u8vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_U8VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_U8VECTOR src) sstart send))]
   [(SCM_U8VECTORP dstart) ; old API
    (return (Scm_U8VectorCopyX dst 0 (SCM_U8VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc u8vector-reverse-copy 
  (v::<u8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeU8Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_U8VECTOR_ELEMENT r j) (SCM_U8VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc u8vector-reverse-copy!
  (dst::<u8vector> dstart::<fixnum> src::<u8vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_U8VECTOR_ELEMENT dst dend) 
            (SCM_U8VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc u8vector-multi-copy!
  (dst::<u8vector> dstart::<fixnum> dstride::<fixnum>
   src::<u8vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_U8VECTOR_ELEMENT dst di)
                 (SCM_U8VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_U8VECTOR_ELEMENTS dst) di)
                      (+ (SCM_U8VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type uint8_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc u8vector->list
  (v::<u8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U8VectorToList)

(define-cproc reverse-u8vector->list
  (v::<u8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(uint8_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_U8VECTOR_ELEMENT v end))
      (C: "z = SCM_MAKE_INT(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->u8vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_U8VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->u8vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-u8vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (u8vector-set! v i (car l) clamp))))

(define-cproc u8vector-fill!
  (v::<u8vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (uint8_t)])
    (C: "filler = (uint8_t)Scm_GetIntegerU8Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_U8VectorFill v filler start end)))

(define-cproc u8vector->vector
  (v::<u8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U8VectorToVector)

(define-cproc vector->u8vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToU8Vector v start end (Scm_ClampMode clamp))))

(define-cproc u8vector=?              ; srfi-66
  (a::<u8vector> b::<u8vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc u8vector-compare        ; srfi-66
  (a::<u8vector> b::<u8vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (u8vector-unfold f len seed)
  (let1 rvec (make-u8vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (u8vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (u8vector-unfold-right f len seed)
  (let1 rvec (make-u8vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (u8vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (u8vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (u8vector-length v) l)) 0 vs)]
         [dst  (make-u8vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (u8vector-length (car vs)))])
        [(null? vs) dst]
      (u8vector-copy! dst k (car vs)))))
(define (u8vector-append . vs) (u8vector-concatenate vs))

(define-cproc u8vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_U8VECTORP v)
          (Scm_Error "<u8vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_U8VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeU8Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_U8VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_U8VECTOR_ELEMENT r i)
                    (SCM_U8VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (u8vector-take v n) (u8vector-copy v 0 n))
(define (u8vector-take-right v n)
  (u8vector-copy v (- (u8vector-length v) n)))
(define (u8vector-drop v n) (u8vector-copy v n))
(define (u8vector-drop-right v n)
  (u8vector-copy v 0 (- (u8vector-length v) n)))
(define (u8vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (u8vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (u8vector-copy v i (+ i n)) vs))))
  (rec 0 (u8vector-length v) '()))
(define (u8vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (u8vector=? a b)
       (or (null? rest)
           (apply u8vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (u8vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (u8vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (u8vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (u8vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (u8vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (u8vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (u8vector-ref vec i)) rs)])
          [(= i len) (list->u8vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->u8vector (reverse rs))]))))
(define (u8vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u8vector-set! vec i (proc (u8vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u8vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (u8vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (u8vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (u8vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (u8vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (u8vector-cumulate proc knil vec)
  (let* ([len (u8vector-length vec)]
         [rvec (make-u8vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (u8vector-ref vec i))
                 (u8vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (u8vector-take-while pred vec)
  (let1 len (u8vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->u8vector (reverse r))
        (let1 e (u8vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->u8vector (reverse r))))))))
(define (u8vector-take-while-right pred vec)
  (let1 len (u8vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->u8vector r)
        (let1 e (u8vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->u8vector r)))))))
(define (u8vector-drop-while pred vec)
  (let1 len (u8vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-u8vector 0)
        (let1 e (u8vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (u8vector-copy vec i)))))))
(define (u8vector-drop-while-right pred vec)
  (let1 len (u8vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-u8vector 0)
        (let1 e (u8vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (u8vector-copy vec 0 (+ i 1))))))))

(define (u8vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u8vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (u8vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u8vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (u8vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u8vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (u8vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u8vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (u8vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u8vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (u8vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (u8vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (u8vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (u8vector-partition pred vec)
  (let1 len (u8vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-u8vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (u8vector-set! rvec i (car rs)))
        (let1 e (u8vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (u8vector-filter pred vec)
  (let1 len (u8vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u8vector (reverse rs))
        (let1 e (u8vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (u8vector-remove pred vec)
  (let1 len (u8vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u8vector (reverse rs))
        (let1 e (u8vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc u8vector-swap! (v::<u8vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_U8VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_U8VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(uint8_t) (SCM_U8VECTOR_ELEMENT v i)])
    (set! (SCM_U8VECTOR_ELEMENT v i) (SCM_U8VECTOR_ELEMENT v j))
    (set! (SCM_U8VECTOR_ELEMENT v j) e)))

(define-cproc u8vector-reverse!
 (v::<u8vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_U8VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(uint8_t)])
      (while (< i j)
        (set! e (SCM_U8VECTOR_ELEMENT v i))
        (set! (SCM_U8VECTOR_ELEMENT v i) (SCM_U8VECTOR_ELEMENT v j))
        (set! (SCM_U8VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (u8vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (u8vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (u8vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (u8vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-u8vector-generator vec)
  (assume-type vec <u8vector>)
  (uvector->generator vec))

;; Comparator

(define u8vector-comparator
  (make-comparator u8vector? u8vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-u8vector vec :optional (port (current-output-port)))
  (assume-type vec <u8vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <u8vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-u8vector size)] [i 0])
      (proc (^[item] (u8vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->u8vector q))))
    ))

(define-method referencer ((v <u8vector>)) u8vector-ref)
(define-method modifier   ((v <u8vector>)) u8vector-set!)
(define-method size-of    ((v <u8vector>)) (u8vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <u8vector>))
  (u8vector->list v))
(define-method coerce-to  ((c <u8vector-meta>) (v <list>))
  (list->u8vector v))
(define-method coerce-to  ((c <vector-meta>) (v <u8vector>))
  (u8vector->vector v))
(define-method coerce-to  ((c <u8vector-meta>) (v <vector>))
  (vector->u8vector v))
(define-method coerce-to  ((c <u8vector-meta>) (v <u8vector>))
  (u8vector-copy v))
(define-method subseq ((v <u8vector>) . args)
  (apply u8vector-copy v args))



;;--------------------------------------------------------------------
;; s16vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc s16vector? (obj) ::<boolean> SCM_S16VECTORP)

(define-cproc s16vector-empty? (v::<s16vector>) ::<boolean>
  (return (== (SCM_S16VECTOR_SIZE v) 0)))

(define-cproc make-s16vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (int16_t)])
    (C: "filler = (int16_t)Scm_GetInteger16Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeS16Vector length filler))))

(define-cproc s16vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToS16Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_S16VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc s16vector-length (v::<s16vector>) ::<ulong> SCM_S16VECTOR_SIZE)

(define-cproc s16vector-copy
  (v::<s16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S16VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc s16vector-copy!
  (dst::<s16vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_S16VECTORP src)
      (Scm_Error "s16vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_S16VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_S16VECTOR src) sstart send))]
   [(SCM_S16VECTORP dstart) ; old API
    (return (Scm_S16VectorCopyX dst 0 (SCM_S16VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc s16vector-reverse-copy 
  (v::<s16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeS16Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_S16VECTOR_ELEMENT r j) (SCM_S16VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc s16vector-reverse-copy!
  (dst::<s16vector> dstart::<fixnum> src::<s16vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_S16VECTOR_ELEMENT dst dend) 
            (SCM_S16VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc s16vector-multi-copy!
  (dst::<s16vector> dstart::<fixnum> dstride::<fixnum>
   src::<s16vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_S16VECTOR_ELEMENT dst di)
                 (SCM_S16VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_S16VECTOR_ELEMENTS dst) di)
                      (+ (SCM_S16VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type int16_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc s16vector->list
  (v::<s16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S16VectorToList)

(define-cproc reverse-s16vector->list
  (v::<s16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(int16_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_S16VECTOR_ELEMENT v end))
      (C: "z = SCM_MAKE_INT(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->s16vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_S16VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->s16vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-s16vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (s16vector-set! v i (car l) clamp))))

(define-cproc s16vector-fill!
  (v::<s16vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (int16_t)])
    (C: "filler = (int16_t)Scm_GetInteger16Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_S16VectorFill v filler start end)))

(define-cproc s16vector->vector
  (v::<s16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S16VectorToVector)

(define-cproc vector->s16vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToS16Vector v start end (Scm_ClampMode clamp))))

(define-cproc s16vector=?              ; srfi-66
  (a::<s16vector> b::<s16vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc s16vector-compare        ; srfi-66
  (a::<s16vector> b::<s16vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (s16vector-unfold f len seed)
  (let1 rvec (make-s16vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (s16vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (s16vector-unfold-right f len seed)
  (let1 rvec (make-s16vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (s16vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (s16vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (s16vector-length v) l)) 0 vs)]
         [dst  (make-s16vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (s16vector-length (car vs)))])
        [(null? vs) dst]
      (s16vector-copy! dst k (car vs)))))
(define (s16vector-append . vs) (s16vector-concatenate vs))

(define-cproc s16vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_S16VECTORP v)
          (Scm_Error "<s16vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_S16VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeS16Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_S16VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_S16VECTOR_ELEMENT r i)
                    (SCM_S16VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (s16vector-take v n) (s16vector-copy v 0 n))
(define (s16vector-take-right v n)
  (s16vector-copy v (- (s16vector-length v) n)))
(define (s16vector-drop v n) (s16vector-copy v n))
(define (s16vector-drop-right v n)
  (s16vector-copy v 0 (- (s16vector-length v) n)))
(define (s16vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (s16vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (s16vector-copy v i (+ i n)) vs))))
  (rec 0 (s16vector-length v) '()))
(define (s16vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (s16vector=? a b)
       (or (null? rest)
           (apply s16vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (s16vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (s16vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (s16vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (s16vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (s16vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (s16vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (s16vector-ref vec i)) rs)])
          [(= i len) (list->s16vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->s16vector (reverse rs))]))))
(define (s16vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s16vector-set! vec i (proc (s16vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s16vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (s16vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (s16vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (s16vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (s16vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (s16vector-cumulate proc knil vec)
  (let* ([len (s16vector-length vec)]
         [rvec (make-s16vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (s16vector-ref vec i))
                 (s16vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (s16vector-take-while pred vec)
  (let1 len (s16vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->s16vector (reverse r))
        (let1 e (s16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->s16vector (reverse r))))))))
(define (s16vector-take-while-right pred vec)
  (let1 len (s16vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->s16vector r)
        (let1 e (s16vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->s16vector r)))))))
(define (s16vector-drop-while pred vec)
  (let1 len (s16vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-s16vector 0)
        (let1 e (s16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (s16vector-copy vec i)))))))
(define (s16vector-drop-while-right pred vec)
  (let1 len (s16vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-s16vector 0)
        (let1 e (s16vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (s16vector-copy vec 0 (+ i 1))))))))

(define (s16vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s16vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (s16vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s16vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (s16vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s16vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (s16vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s16vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (s16vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s16vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (s16vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (s16vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (s16vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (s16vector-partition pred vec)
  (let1 len (s16vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-s16vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (s16vector-set! rvec i (car rs)))
        (let1 e (s16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (s16vector-filter pred vec)
  (let1 len (s16vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s16vector (reverse rs))
        (let1 e (s16vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (s16vector-remove pred vec)
  (let1 len (s16vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s16vector (reverse rs))
        (let1 e (s16vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc s16vector-swap! (v::<s16vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_S16VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_S16VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(int16_t) (SCM_S16VECTOR_ELEMENT v i)])
    (set! (SCM_S16VECTOR_ELEMENT v i) (SCM_S16VECTOR_ELEMENT v j))
    (set! (SCM_S16VECTOR_ELEMENT v j) e)))

(define-cproc s16vector-reverse!
 (v::<s16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_S16VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(int16_t)])
      (while (< i j)
        (set! e (SCM_S16VECTOR_ELEMENT v i))
        (set! (SCM_S16VECTOR_ELEMENT v i) (SCM_S16VECTOR_ELEMENT v j))
        (set! (SCM_S16VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (s16vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (s16vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (s16vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (s16vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-s16vector-generator vec)
  (assume-type vec <s16vector>)
  (uvector->generator vec))

;; Comparator

(define s16vector-comparator
  (make-comparator s16vector? s16vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-s16vector vec :optional (port (current-output-port)))
  (assume-type vec <s16vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <s16vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-s16vector size)] [i 0])
      (proc (^[item] (s16vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->s16vector q))))
    ))

(define-method referencer ((v <s16vector>)) s16vector-ref)
(define-method modifier   ((v <s16vector>)) s16vector-set!)
(define-method size-of    ((v <s16vector>)) (s16vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <s16vector>))
  (s16vector->list v))
(define-method coerce-to  ((c <s16vector-meta>) (v <list>))
  (list->s16vector v))
(define-method coerce-to  ((c <vector-meta>) (v <s16vector>))
  (s16vector->vector v))
(define-method coerce-to  ((c <s16vector-meta>) (v <vector>))
  (vector->s16vector v))
(define-method coerce-to  ((c <s16vector-meta>) (v <s16vector>))
  (s16vector-copy v))
(define-method subseq ((v <s16vector>) . args)
  (apply s16vector-copy v args))



;;--------------------------------------------------------------------
;; u16vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc u16vector? (obj) ::<boolean> SCM_U16VECTORP)

(define-cproc u16vector-empty? (v::<u16vector>) ::<boolean>
  (return (== (SCM_U16VECTOR_SIZE v) 0)))

(define-cproc make-u16vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (uint16_t)])
    (C: "filler = (uint16_t)Scm_GetIntegerU16Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeU16Vector length filler))))

(define-cproc u16vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToU16Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_U16VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc u16vector-length (v::<u16vector>) ::<ulong> SCM_U16VECTOR_SIZE)

(define-cproc u16vector-copy
  (v::<u16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U16VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc u16vector-copy!
  (dst::<u16vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_U16VECTORP src)
      (Scm_Error "u16vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_U16VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_U16VECTOR src) sstart send))]
   [(SCM_U16VECTORP dstart) ; old API
    (return (Scm_U16VectorCopyX dst 0 (SCM_U16VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc u16vector-reverse-copy 
  (v::<u16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeU16Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_U16VECTOR_ELEMENT r j) (SCM_U16VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc u16vector-reverse-copy!
  (dst::<u16vector> dstart::<fixnum> src::<u16vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_U16VECTOR_ELEMENT dst dend) 
            (SCM_U16VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc u16vector-multi-copy!
  (dst::<u16vector> dstart::<fixnum> dstride::<fixnum>
   src::<u16vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_U16VECTOR_ELEMENT dst di)
                 (SCM_U16VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_U16VECTOR_ELEMENTS dst) di)
                      (+ (SCM_U16VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type uint16_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc u16vector->list
  (v::<u16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U16VectorToList)

(define-cproc reverse-u16vector->list
  (v::<u16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(uint16_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_U16VECTOR_ELEMENT v end))
      (C: "z = SCM_MAKE_INT(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->u16vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_U16VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->u16vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-u16vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (u16vector-set! v i (car l) clamp))))

(define-cproc u16vector-fill!
  (v::<u16vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (uint16_t)])
    (C: "filler = (uint16_t)Scm_GetIntegerU16Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_U16VectorFill v filler start end)))

(define-cproc u16vector->vector
  (v::<u16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U16VectorToVector)

(define-cproc vector->u16vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToU16Vector v start end (Scm_ClampMode clamp))))

(define-cproc u16vector=?              ; srfi-66
  (a::<u16vector> b::<u16vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc u16vector-compare        ; srfi-66
  (a::<u16vector> b::<u16vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (u16vector-unfold f len seed)
  (let1 rvec (make-u16vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (u16vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (u16vector-unfold-right f len seed)
  (let1 rvec (make-u16vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (u16vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (u16vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (u16vector-length v) l)) 0 vs)]
         [dst  (make-u16vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (u16vector-length (car vs)))])
        [(null? vs) dst]
      (u16vector-copy! dst k (car vs)))))
(define (u16vector-append . vs) (u16vector-concatenate vs))

(define-cproc u16vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_U16VECTORP v)
          (Scm_Error "<u16vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_U16VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeU16Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_U16VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_U16VECTOR_ELEMENT r i)
                    (SCM_U16VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (u16vector-take v n) (u16vector-copy v 0 n))
(define (u16vector-take-right v n)
  (u16vector-copy v (- (u16vector-length v) n)))
(define (u16vector-drop v n) (u16vector-copy v n))
(define (u16vector-drop-right v n)
  (u16vector-copy v 0 (- (u16vector-length v) n)))
(define (u16vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (u16vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (u16vector-copy v i (+ i n)) vs))))
  (rec 0 (u16vector-length v) '()))
(define (u16vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (u16vector=? a b)
       (or (null? rest)
           (apply u16vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (u16vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (u16vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (u16vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (u16vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (u16vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (u16vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (u16vector-ref vec i)) rs)])
          [(= i len) (list->u16vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->u16vector (reverse rs))]))))
(define (u16vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u16vector-set! vec i (proc (u16vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u16vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (u16vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (u16vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (u16vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (u16vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (u16vector-cumulate proc knil vec)
  (let* ([len (u16vector-length vec)]
         [rvec (make-u16vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (u16vector-ref vec i))
                 (u16vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (u16vector-take-while pred vec)
  (let1 len (u16vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->u16vector (reverse r))
        (let1 e (u16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->u16vector (reverse r))))))))
(define (u16vector-take-while-right pred vec)
  (let1 len (u16vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->u16vector r)
        (let1 e (u16vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->u16vector r)))))))
(define (u16vector-drop-while pred vec)
  (let1 len (u16vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-u16vector 0)
        (let1 e (u16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (u16vector-copy vec i)))))))
(define (u16vector-drop-while-right pred vec)
  (let1 len (u16vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-u16vector 0)
        (let1 e (u16vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (u16vector-copy vec 0 (+ i 1))))))))

(define (u16vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u16vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (u16vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u16vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (u16vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u16vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (u16vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u16vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (u16vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u16vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (u16vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (u16vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (u16vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (u16vector-partition pred vec)
  (let1 len (u16vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-u16vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (u16vector-set! rvec i (car rs)))
        (let1 e (u16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (u16vector-filter pred vec)
  (let1 len (u16vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u16vector (reverse rs))
        (let1 e (u16vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (u16vector-remove pred vec)
  (let1 len (u16vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u16vector (reverse rs))
        (let1 e (u16vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc u16vector-swap! (v::<u16vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_U16VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_U16VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(uint16_t) (SCM_U16VECTOR_ELEMENT v i)])
    (set! (SCM_U16VECTOR_ELEMENT v i) (SCM_U16VECTOR_ELEMENT v j))
    (set! (SCM_U16VECTOR_ELEMENT v j) e)))

(define-cproc u16vector-reverse!
 (v::<u16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_U16VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(uint16_t)])
      (while (< i j)
        (set! e (SCM_U16VECTOR_ELEMENT v i))
        (set! (SCM_U16VECTOR_ELEMENT v i) (SCM_U16VECTOR_ELEMENT v j))
        (set! (SCM_U16VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (u16vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (u16vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (u16vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (u16vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-u16vector-generator vec)
  (assume-type vec <u16vector>)
  (uvector->generator vec))

;; Comparator

(define u16vector-comparator
  (make-comparator u16vector? u16vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-u16vector vec :optional (port (current-output-port)))
  (assume-type vec <u16vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <u16vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-u16vector size)] [i 0])
      (proc (^[item] (u16vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->u16vector q))))
    ))

(define-method referencer ((v <u16vector>)) u16vector-ref)
(define-method modifier   ((v <u16vector>)) u16vector-set!)
(define-method size-of    ((v <u16vector>)) (u16vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <u16vector>))
  (u16vector->list v))
(define-method coerce-to  ((c <u16vector-meta>) (v <list>))
  (list->u16vector v))
(define-method coerce-to  ((c <vector-meta>) (v <u16vector>))
  (u16vector->vector v))
(define-method coerce-to  ((c <u16vector-meta>) (v <vector>))
  (vector->u16vector v))
(define-method coerce-to  ((c <u16vector-meta>) (v <u16vector>))
  (u16vector-copy v))
(define-method subseq ((v <u16vector>) . args)
  (apply u16vector-copy v args))



;;--------------------------------------------------------------------
;; s32vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc s32vector? (obj) ::<boolean> SCM_S32VECTORP)

(define-cproc s32vector-empty? (v::<s32vector>) ::<boolean>
  (return (== (SCM_S32VECTOR_SIZE v) 0)))

(define-cproc make-s32vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (int32_t)])
    (C: "filler = (int32_t)Scm_GetInteger32Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeS32Vector length filler))))

(define-cproc s32vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToS32Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_S32VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc s32vector-length (v::<s32vector>) ::<ulong> SCM_S32VECTOR_SIZE)

(define-cproc s32vector-copy
  (v::<s32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S32VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc s32vector-copy!
  (dst::<s32vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_S32VECTORP src)
      (Scm_Error "s32vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_S32VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_S32VECTOR src) sstart send))]
   [(SCM_S32VECTORP dstart) ; old API
    (return (Scm_S32VectorCopyX dst 0 (SCM_S32VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc s32vector-reverse-copy 
  (v::<s32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeS32Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_S32VECTOR_ELEMENT r j) (SCM_S32VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc s32vector-reverse-copy!
  (dst::<s32vector> dstart::<fixnum> src::<s32vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_S32VECTOR_ELEMENT dst dend) 
            (SCM_S32VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc s32vector-multi-copy!
  (dst::<s32vector> dstart::<fixnum> dstride::<fixnum>
   src::<s32vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_S32VECTOR_ELEMENT dst di)
                 (SCM_S32VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_S32VECTOR_ELEMENTS dst) di)
                      (+ (SCM_S32VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type int32_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc s32vector->list
  (v::<s32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S32VectorToList)

(define-cproc reverse-s32vector->list
  (v::<s32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(int32_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_S32VECTOR_ELEMENT v end))
      (C: "z = Scm_MakeInteger(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->s32vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_S32VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->s32vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-s32vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (s32vector-set! v i (car l) clamp))))

(define-cproc s32vector-fill!
  (v::<s32vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (int32_t)])
    (C: "filler = (int32_t)Scm_GetInteger32Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_S32VectorFill v filler start end)))

(define-cproc s32vector->vector
  (v::<s32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S32VectorToVector)

(define-cproc vector->s32vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToS32Vector v start end (Scm_ClampMode clamp))))

(define-cproc s32vector=?              ; srfi-66
  (a::<s32vector> b::<s32vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc s32vector-compare        ; srfi-66
  (a::<s32vector> b::<s32vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (s32vector-unfold f len seed)
  (let1 rvec (make-s32vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (s32vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (s32vector-unfold-right f len seed)
  (let1 rvec (make-s32vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (s32vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (s32vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (s32vector-length v) l)) 0 vs)]
         [dst  (make-s32vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (s32vector-length (car vs)))])
        [(null? vs) dst]
      (s32vector-copy! dst k (car vs)))))
(define (s32vector-append . vs) (s32vector-concatenate vs))

(define-cproc s32vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_S32VECTORP v)
          (Scm_Error "<s32vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_S32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeS32Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_S32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_S32VECTOR_ELEMENT r i)
                    (SCM_S32VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (s32vector-take v n) (s32vector-copy v 0 n))
(define (s32vector-take-right v n)
  (s32vector-copy v (- (s32vector-length v) n)))
(define (s32vector-drop v n) (s32vector-copy v n))
(define (s32vector-drop-right v n)
  (s32vector-copy v 0 (- (s32vector-length v) n)))
(define (s32vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (s32vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (s32vector-copy v i (+ i n)) vs))))
  (rec 0 (s32vector-length v) '()))
(define (s32vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (s32vector=? a b)
       (or (null? rest)
           (apply s32vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (s32vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (s32vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (s32vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (s32vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (s32vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (s32vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (s32vector-ref vec i)) rs)])
          [(= i len) (list->s32vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->s32vector (reverse rs))]))))
(define (s32vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s32vector-set! vec i (proc (s32vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s32vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (s32vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (s32vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (s32vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (s32vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (s32vector-cumulate proc knil vec)
  (let* ([len (s32vector-length vec)]
         [rvec (make-s32vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (s32vector-ref vec i))
                 (s32vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (s32vector-take-while pred vec)
  (let1 len (s32vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->s32vector (reverse r))
        (let1 e (s32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->s32vector (reverse r))))))))
(define (s32vector-take-while-right pred vec)
  (let1 len (s32vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->s32vector r)
        (let1 e (s32vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->s32vector r)))))))
(define (s32vector-drop-while pred vec)
  (let1 len (s32vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-s32vector 0)
        (let1 e (s32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (s32vector-copy vec i)))))))
(define (s32vector-drop-while-right pred vec)
  (let1 len (s32vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-s32vector 0)
        (let1 e (s32vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (s32vector-copy vec 0 (+ i 1))))))))

(define (s32vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s32vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (s32vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s32vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (s32vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s32vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (s32vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s32vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (s32vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s32vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (s32vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (s32vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (s32vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (s32vector-partition pred vec)
  (let1 len (s32vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-s32vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (s32vector-set! rvec i (car rs)))
        (let1 e (s32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (s32vector-filter pred vec)
  (let1 len (s32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s32vector (reverse rs))
        (let1 e (s32vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (s32vector-remove pred vec)
  (let1 len (s32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s32vector (reverse rs))
        (let1 e (s32vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc s32vector-swap! (v::<s32vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_S32VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_S32VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(int32_t) (SCM_S32VECTOR_ELEMENT v i)])
    (set! (SCM_S32VECTOR_ELEMENT v i) (SCM_S32VECTOR_ELEMENT v j))
    (set! (SCM_S32VECTOR_ELEMENT v j) e)))

(define-cproc s32vector-reverse!
 (v::<s32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_S32VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(int32_t)])
      (while (< i j)
        (set! e (SCM_S32VECTOR_ELEMENT v i))
        (set! (SCM_S32VECTOR_ELEMENT v i) (SCM_S32VECTOR_ELEMENT v j))
        (set! (SCM_S32VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (s32vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (s32vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (s32vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (s32vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-s32vector-generator vec)
  (assume-type vec <s32vector>)
  (uvector->generator vec))

;; Comparator

(define s32vector-comparator
  (make-comparator s32vector? s32vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-s32vector vec :optional (port (current-output-port)))
  (assume-type vec <s32vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <s32vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-s32vector size)] [i 0])
      (proc (^[item] (s32vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->s32vector q))))
    ))

(define-method referencer ((v <s32vector>)) s32vector-ref)
(define-method modifier   ((v <s32vector>)) s32vector-set!)
(define-method size-of    ((v <s32vector>)) (s32vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <s32vector>))
  (s32vector->list v))
(define-method coerce-to  ((c <s32vector-meta>) (v <list>))
  (list->s32vector v))
(define-method coerce-to  ((c <vector-meta>) (v <s32vector>))
  (s32vector->vector v))
(define-method coerce-to  ((c <s32vector-meta>) (v <vector>))
  (vector->s32vector v))
(define-method coerce-to  ((c <s32vector-meta>) (v <s32vector>))
  (s32vector-copy v))
(define-method subseq ((v <s32vector>) . args)
  (apply s32vector-copy v args))



;;--------------------------------------------------------------------
;; u32vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc u32vector? (obj) ::<boolean> SCM_U32VECTORP)

(define-cproc u32vector-empty? (v::<u32vector>) ::<boolean>
  (return (== (SCM_U32VECTOR_SIZE v) 0)))

(define-cproc make-u32vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (uint32_t)])
    (C: "filler = (uint32_t)Scm_GetIntegerU32Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeU32Vector length filler))))

(define-cproc u32vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToU32Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_U32VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc u32vector-length (v::<u32vector>) ::<ulong> SCM_U32VECTOR_SIZE)

(define-cproc u32vector-copy
  (v::<u32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U32VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc u32vector-copy!
  (dst::<u32vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_U32VECTORP src)
      (Scm_Error "u32vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_U32VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_U32VECTOR src) sstart send))]
   [(SCM_U32VECTORP dstart) ; old API
    (return (Scm_U32VectorCopyX dst 0 (SCM_U32VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc u32vector-reverse-copy 
  (v::<u32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeU32Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_U32VECTOR_ELEMENT r j) (SCM_U32VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc u32vector-reverse-copy!
  (dst::<u32vector> dstart::<fixnum> src::<u32vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_U32VECTOR_ELEMENT dst dend) 
            (SCM_U32VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc u32vector-multi-copy!
  (dst::<u32vector> dstart::<fixnum> dstride::<fixnum>
   src::<u32vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_U32VECTOR_ELEMENT dst di)
                 (SCM_U32VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_U32VECTOR_ELEMENTS dst) di)
                      (+ (SCM_U32VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type uint32_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc u32vector->list
  (v::<u32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U32VectorToList)

(define-cproc reverse-u32vector->list
  (v::<u32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(uint32_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_U32VECTOR_ELEMENT v end))
      (C: "z = Scm_MakeIntegerU(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->u32vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_U32VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->u32vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-u32vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (u32vector-set! v i (car l) clamp))))

(define-cproc u32vector-fill!
  (v::<u32vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (uint32_t)])
    (C: "filler = (uint32_t)Scm_GetIntegerU32Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_U32VectorFill v filler start end)))

(define-cproc u32vector->vector
  (v::<u32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U32VectorToVector)

(define-cproc vector->u32vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToU32Vector v start end (Scm_ClampMode clamp))))

(define-cproc u32vector=?              ; srfi-66
  (a::<u32vector> b::<u32vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc u32vector-compare        ; srfi-66
  (a::<u32vector> b::<u32vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (u32vector-unfold f len seed)
  (let1 rvec (make-u32vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (u32vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (u32vector-unfold-right f len seed)
  (let1 rvec (make-u32vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (u32vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (u32vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (u32vector-length v) l)) 0 vs)]
         [dst  (make-u32vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (u32vector-length (car vs)))])
        [(null? vs) dst]
      (u32vector-copy! dst k (car vs)))))
(define (u32vector-append . vs) (u32vector-concatenate vs))

(define-cproc u32vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_U32VECTORP v)
          (Scm_Error "<u32vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_U32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeU32Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_U32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_U32VECTOR_ELEMENT r i)
                    (SCM_U32VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (u32vector-take v n) (u32vector-copy v 0 n))
(define (u32vector-take-right v n)
  (u32vector-copy v (- (u32vector-length v) n)))
(define (u32vector-drop v n) (u32vector-copy v n))
(define (u32vector-drop-right v n)
  (u32vector-copy v 0 (- (u32vector-length v) n)))
(define (u32vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (u32vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (u32vector-copy v i (+ i n)) vs))))
  (rec 0 (u32vector-length v) '()))
(define (u32vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (u32vector=? a b)
       (or (null? rest)
           (apply u32vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (u32vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (u32vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (u32vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (u32vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (u32vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (u32vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (u32vector-ref vec i)) rs)])
          [(= i len) (list->u32vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->u32vector (reverse rs))]))))
(define (u32vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u32vector-set! vec i (proc (u32vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u32vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (u32vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (u32vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (u32vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (u32vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (u32vector-cumulate proc knil vec)
  (let* ([len (u32vector-length vec)]
         [rvec (make-u32vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (u32vector-ref vec i))
                 (u32vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (u32vector-take-while pred vec)
  (let1 len (u32vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->u32vector (reverse r))
        (let1 e (u32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->u32vector (reverse r))))))))
(define (u32vector-take-while-right pred vec)
  (let1 len (u32vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->u32vector r)
        (let1 e (u32vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->u32vector r)))))))
(define (u32vector-drop-while pred vec)
  (let1 len (u32vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-u32vector 0)
        (let1 e (u32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (u32vector-copy vec i)))))))
(define (u32vector-drop-while-right pred vec)
  (let1 len (u32vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-u32vector 0)
        (let1 e (u32vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (u32vector-copy vec 0 (+ i 1))))))))

(define (u32vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u32vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (u32vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u32vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (u32vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u32vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (u32vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u32vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (u32vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u32vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (u32vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (u32vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (u32vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (u32vector-partition pred vec)
  (let1 len (u32vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-u32vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (u32vector-set! rvec i (car rs)))
        (let1 e (u32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (u32vector-filter pred vec)
  (let1 len (u32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u32vector (reverse rs))
        (let1 e (u32vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (u32vector-remove pred vec)
  (let1 len (u32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u32vector (reverse rs))
        (let1 e (u32vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc u32vector-swap! (v::<u32vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_U32VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_U32VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(uint32_t) (SCM_U32VECTOR_ELEMENT v i)])
    (set! (SCM_U32VECTOR_ELEMENT v i) (SCM_U32VECTOR_ELEMENT v j))
    (set! (SCM_U32VECTOR_ELEMENT v j) e)))

(define-cproc u32vector-reverse!
 (v::<u32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_U32VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(uint32_t)])
      (while (< i j)
        (set! e (SCM_U32VECTOR_ELEMENT v i))
        (set! (SCM_U32VECTOR_ELEMENT v i) (SCM_U32VECTOR_ELEMENT v j))
        (set! (SCM_U32VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (u32vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (u32vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (u32vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (u32vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-u32vector-generator vec)
  (assume-type vec <u32vector>)
  (uvector->generator vec))

;; Comparator

(define u32vector-comparator
  (make-comparator u32vector? u32vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-u32vector vec :optional (port (current-output-port)))
  (assume-type vec <u32vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <u32vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-u32vector size)] [i 0])
      (proc (^[item] (u32vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->u32vector q))))
    ))

(define-method referencer ((v <u32vector>)) u32vector-ref)
(define-method modifier   ((v <u32vector>)) u32vector-set!)
(define-method size-of    ((v <u32vector>)) (u32vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <u32vector>))
  (u32vector->list v))
(define-method coerce-to  ((c <u32vector-meta>) (v <list>))
  (list->u32vector v))
(define-method coerce-to  ((c <vector-meta>) (v <u32vector>))
  (u32vector->vector v))
(define-method coerce-to  ((c <u32vector-meta>) (v <vector>))
  (vector->u32vector v))
(define-method coerce-to  ((c <u32vector-meta>) (v <u32vector>))
  (u32vector-copy v))
(define-method subseq ((v <u32vector>) . args)
  (apply u32vector-copy v args))



;;--------------------------------------------------------------------
;; s64vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc s64vector? (obj) ::<boolean> SCM_S64VECTORP)

(define-cproc s64vector-empty? (v::<s64vector>) ::<boolean>
  (return (== (SCM_S64VECTOR_SIZE v) 0)))

(define-cproc make-s64vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (int64_t)])
    (C: "filler = Scm_GetInteger64Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeS64Vector length filler))))

(define-cproc s64vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToS64Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_S64VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc s64vector-length (v::<s64vector>) ::<ulong> SCM_S64VECTOR_SIZE)

(define-cproc s64vector-copy
  (v::<s64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S64VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc s64vector-copy!
  (dst::<s64vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_S64VECTORP src)
      (Scm_Error "s64vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_S64VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_S64VECTOR src) sstart send))]
   [(SCM_S64VECTORP dstart) ; old API
    (return (Scm_S64VectorCopyX dst 0 (SCM_S64VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc s64vector-reverse-copy 
  (v::<s64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeS64Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_S64VECTOR_ELEMENT r j) (SCM_S64VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc s64vector-reverse-copy!
  (dst::<s64vector> dstart::<fixnum> src::<s64vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_S64VECTOR_ELEMENT dst dend) 
            (SCM_S64VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc s64vector-multi-copy!
  (dst::<s64vector> dstart::<fixnum> dstride::<fixnum>
   src::<s64vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_S64VECTOR_ELEMENT dst di)
                 (SCM_S64VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_S64VECTOR_ELEMENTS dst) di)
                      (+ (SCM_S64VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type int64_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc s64vector->list
  (v::<s64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S64VectorToList)

(define-cproc reverse-s64vector->list
  (v::<s64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(int64_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_S64VECTOR_ELEMENT v end))
      (C: "z = Scm_MakeInteger64(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->s64vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_S64VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->s64vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-s64vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (s64vector-set! v i (car l) clamp))))

(define-cproc s64vector-fill!
  (v::<s64vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (int64_t)])
    (C: "filler = Scm_GetInteger64Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_S64VectorFill v filler start end)))

(define-cproc s64vector->vector
  (v::<s64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_S64VectorToVector)

(define-cproc vector->s64vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToS64Vector v start end (Scm_ClampMode clamp))))

(define-cproc s64vector=?              ; srfi-66
  (a::<s64vector> b::<s64vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc s64vector-compare        ; srfi-66
  (a::<s64vector> b::<s64vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (s64vector-unfold f len seed)
  (let1 rvec (make-s64vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (s64vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (s64vector-unfold-right f len seed)
  (let1 rvec (make-s64vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (s64vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (s64vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (s64vector-length v) l)) 0 vs)]
         [dst  (make-s64vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (s64vector-length (car vs)))])
        [(null? vs) dst]
      (s64vector-copy! dst k (car vs)))))
(define (s64vector-append . vs) (s64vector-concatenate vs))

(define-cproc s64vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_S64VECTORP v)
          (Scm_Error "<s64vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_S64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeS64Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_S64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_S64VECTOR_ELEMENT r i)
                    (SCM_S64VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (s64vector-take v n) (s64vector-copy v 0 n))
(define (s64vector-take-right v n)
  (s64vector-copy v (- (s64vector-length v) n)))
(define (s64vector-drop v n) (s64vector-copy v n))
(define (s64vector-drop-right v n)
  (s64vector-copy v 0 (- (s64vector-length v) n)))
(define (s64vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (s64vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (s64vector-copy v i (+ i n)) vs))))
  (rec 0 (s64vector-length v) '()))
(define (s64vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (s64vector=? a b)
       (or (null? rest)
           (apply s64vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (s64vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (s64vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (s64vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (s64vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (s64vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (s64vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (s64vector-ref vec i)) rs)])
          [(= i len) (list->s64vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->s64vector (reverse rs))]))))
(define (s64vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s64vector-set! vec i (proc (s64vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (s64vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (s64vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (s64vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (s64vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (s64vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (s64vector-cumulate proc knil vec)
  (let* ([len (s64vector-length vec)]
         [rvec (make-s64vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (s64vector-ref vec i))
                 (s64vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (s64vector-take-while pred vec)
  (let1 len (s64vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->s64vector (reverse r))
        (let1 e (s64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->s64vector (reverse r))))))))
(define (s64vector-take-while-right pred vec)
  (let1 len (s64vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->s64vector r)
        (let1 e (s64vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->s64vector r)))))))
(define (s64vector-drop-while pred vec)
  (let1 len (s64vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-s64vector 0)
        (let1 e (s64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (s64vector-copy vec i)))))))
(define (s64vector-drop-while-right pred vec)
  (let1 len (s64vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-s64vector 0)
        (let1 e (s64vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (s64vector-copy vec 0 (+ i 1))))))))

(define (s64vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s64vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (s64vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s64vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (s64vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s64vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (s64vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (s64vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (s64vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (s64vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (s64vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (s64vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (s64vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (s64vector-partition pred vec)
  (let1 len (s64vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-s64vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (s64vector-set! rvec i (car rs)))
        (let1 e (s64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (s64vector-filter pred vec)
  (let1 len (s64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s64vector (reverse rs))
        (let1 e (s64vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (s64vector-remove pred vec)
  (let1 len (s64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->s64vector (reverse rs))
        (let1 e (s64vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc s64vector-swap! (v::<s64vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_S64VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_S64VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(int64_t) (SCM_S64VECTOR_ELEMENT v i)])
    (set! (SCM_S64VECTOR_ELEMENT v i) (SCM_S64VECTOR_ELEMENT v j))
    (set! (SCM_S64VECTOR_ELEMENT v j) e)))

(define-cproc s64vector-reverse!
 (v::<s64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_S64VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(int64_t)])
      (while (< i j)
        (set! e (SCM_S64VECTOR_ELEMENT v i))
        (set! (SCM_S64VECTOR_ELEMENT v i) (SCM_S64VECTOR_ELEMENT v j))
        (set! (SCM_S64VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (s64vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (s64vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (s64vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (s64vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-s64vector-generator vec)
  (assume-type vec <s64vector>)
  (uvector->generator vec))

;; Comparator

(define s64vector-comparator
  (make-comparator s64vector? s64vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-s64vector vec :optional (port (current-output-port)))
  (assume-type vec <s64vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <s64vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-s64vector size)] [i 0])
      (proc (^[item] (s64vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->s64vector q))))
    ))

(define-method referencer ((v <s64vector>)) s64vector-ref)
(define-method modifier   ((v <s64vector>)) s64vector-set!)
(define-method size-of    ((v <s64vector>)) (s64vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <s64vector>))
  (s64vector->list v))
(define-method coerce-to  ((c <s64vector-meta>) (v <list>))
  (list->s64vector v))
(define-method coerce-to  ((c <vector-meta>) (v <s64vector>))
  (s64vector->vector v))
(define-method coerce-to  ((c <s64vector-meta>) (v <vector>))
  (vector->s64vector v))
(define-method coerce-to  ((c <s64vector-meta>) (v <s64vector>))
  (s64vector-copy v))
(define-method subseq ((v <s64vector>) . args)
  (apply s64vector-copy v args))



;;--------------------------------------------------------------------
;; u64vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc u64vector? (obj) ::<boolean> SCM_U64VECTORP)

(define-cproc u64vector-empty? (v::<u64vector>) ::<boolean>
  (return (== (SCM_U64VECTOR_SIZE v) 0)))

(define-cproc make-u64vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (uint64_t)])
    (C: "filler = Scm_GetIntegerU64Clamp(fill, SCM_CLAMP_ERROR, NULL)")
    (return (Scm_MakeU64Vector length filler))))

(define-cproc u64vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToU64Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_U64VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc u64vector-length (v::<u64vector>) ::<ulong> SCM_U64VECTOR_SIZE)

(define-cproc u64vector-copy
  (v::<u64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U64VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc u64vector-copy!
  (dst::<u64vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_U64VECTORP src)
      (Scm_Error "u64vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_U64VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_U64VECTOR src) sstart send))]
   [(SCM_U64VECTORP dstart) ; old API
    (return (Scm_U64VectorCopyX dst 0 (SCM_U64VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc u64vector-reverse-copy 
  (v::<u64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeU64Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_U64VECTOR_ELEMENT r j) (SCM_U64VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc u64vector-reverse-copy!
  (dst::<u64vector> dstart::<fixnum> src::<u64vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_U64VECTOR_ELEMENT dst dend) 
            (SCM_U64VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc u64vector-multi-copy!
  (dst::<u64vector> dstart::<fixnum> dstride::<fixnum>
   src::<u64vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_U64VECTOR_ELEMENT dst di)
                 (SCM_U64VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_U64VECTOR_ELEMENTS dst) di)
                      (+ (SCM_U64VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type uint64_t)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc u64vector->list
  (v::<u64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U64VectorToList)

(define-cproc reverse-u64vector->list
  (v::<u64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(uint64_t)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_U64VECTOR_ELEMENT v end))
      (C: "z = Scm_MakeIntegerU64(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->u64vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_U64VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->u64vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-u64vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (u64vector-set! v i (car l) clamp))))

(define-cproc u64vector-fill!
  (v::<u64vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (uint64_t)])
    (C: "filler = Scm_GetIntegerU64Clamp(val, SCM_CLAMP_ERROR, NULL)")
    (Scm_U64VectorFill v filler start end)))

(define-cproc u64vector->vector
  (v::<u64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_U64VectorToVector)

(define-cproc vector->u64vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToU64Vector v start end (Scm_ClampMode clamp))))

(define-cproc u64vector=?              ; srfi-66
  (a::<u64vector> b::<u64vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc u64vector-compare        ; srfi-66
  (a::<u64vector> b::<u64vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (u64vector-unfold f len seed)
  (let1 rvec (make-u64vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (u64vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (u64vector-unfold-right f len seed)
  (let1 rvec (make-u64vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (u64vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (u64vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (u64vector-length v) l)) 0 vs)]
         [dst  (make-u64vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (u64vector-length (car vs)))])
        [(null? vs) dst]
      (u64vector-copy! dst k (car vs)))))
(define (u64vector-append . vs) (u64vector-concatenate vs))

(define-cproc u64vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_U64VECTORP v)
          (Scm_Error "<u64vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_U64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeU64Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_U64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_U64VECTOR_ELEMENT r i)
                    (SCM_U64VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (u64vector-take v n) (u64vector-copy v 0 n))
(define (u64vector-take-right v n)
  (u64vector-copy v (- (u64vector-length v) n)))
(define (u64vector-drop v n) (u64vector-copy v n))
(define (u64vector-drop-right v n)
  (u64vector-copy v 0 (- (u64vector-length v) n)))
(define (u64vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (u64vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (u64vector-copy v i (+ i n)) vs))))
  (rec 0 (u64vector-length v) '()))
(define (u64vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (u64vector=? a b)
       (or (null? rest)
           (apply u64vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (u64vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (u64vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (u64vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (u64vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (u64vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (u64vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (u64vector-ref vec i)) rs)])
          [(= i len) (list->u64vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->u64vector (reverse rs))]))))
(define (u64vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u64vector-set! vec i (proc (u64vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (u64vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (u64vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (u64vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (u64vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (u64vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (u64vector-cumulate proc knil vec)
  (let* ([len (u64vector-length vec)]
         [rvec (make-u64vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (u64vector-ref vec i))
                 (u64vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (u64vector-take-while pred vec)
  (let1 len (u64vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->u64vector (reverse r))
        (let1 e (u64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->u64vector (reverse r))))))))
(define (u64vector-take-while-right pred vec)
  (let1 len (u64vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->u64vector r)
        (let1 e (u64vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->u64vector r)))))))
(define (u64vector-drop-while pred vec)
  (let1 len (u64vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-u64vector 0)
        (let1 e (u64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (u64vector-copy vec i)))))))
(define (u64vector-drop-while-right pred vec)
  (let1 len (u64vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-u64vector 0)
        (let1 e (u64vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (u64vector-copy vec 0 (+ i 1))))))))

(define (u64vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u64vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (u64vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u64vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (u64vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u64vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (u64vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (u64vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (u64vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (u64vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (u64vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (u64vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (u64vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (u64vector-partition pred vec)
  (let1 len (u64vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-u64vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (u64vector-set! rvec i (car rs)))
        (let1 e (u64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (u64vector-filter pred vec)
  (let1 len (u64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u64vector (reverse rs))
        (let1 e (u64vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (u64vector-remove pred vec)
  (let1 len (u64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->u64vector (reverse rs))
        (let1 e (u64vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc u64vector-swap! (v::<u64vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_U64VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_U64VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(uint64_t) (SCM_U64VECTOR_ELEMENT v i)])
    (set! (SCM_U64VECTOR_ELEMENT v i) (SCM_U64VECTOR_ELEMENT v j))
    (set! (SCM_U64VECTOR_ELEMENT v j) e)))

(define-cproc u64vector-reverse!
 (v::<u64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_U64VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(uint64_t)])
      (while (< i j)
        (set! e (SCM_U64VECTOR_ELEMENT v i))
        (set! (SCM_U64VECTOR_ELEMENT v i) (SCM_U64VECTOR_ELEMENT v j))
        (set! (SCM_U64VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (u64vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (u64vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (u64vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (u64vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-u64vector-generator vec)
  (assume-type vec <u64vector>)
  (uvector->generator vec))

;; Comparator

(define u64vector-comparator
  (make-comparator u64vector? u64vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-u64vector vec :optional (port (current-output-port)))
  (assume-type vec <u64vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <u64vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-u64vector size)] [i 0])
      (proc (^[item] (u64vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->u64vector q))))
    ))

(define-method referencer ((v <u64vector>)) u64vector-ref)
(define-method modifier   ((v <u64vector>)) u64vector-set!)
(define-method size-of    ((v <u64vector>)) (u64vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <u64vector>))
  (u64vector->list v))
(define-method coerce-to  ((c <u64vector-meta>) (v <list>))
  (list->u64vector v))
(define-method coerce-to  ((c <vector-meta>) (v <u64vector>))
  (u64vector->vector v))
(define-method coerce-to  ((c <u64vector-meta>) (v <vector>))
  (vector->u64vector v))
(define-method coerce-to  ((c <u64vector-meta>) (v <u64vector>))
  (u64vector-copy v))
(define-method subseq ((v <u64vector>) . args)
  (apply u64vector-copy v args))



;;--------------------------------------------------------------------
;; f16vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc f16vector? (obj) ::<boolean> SCM_F16VECTORP)

(define-cproc f16vector-empty? (v::<f16vector>) ::<boolean>
  (return (== (SCM_F16VECTOR_SIZE v) 0)))

(define-cproc make-f16vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (ScmHalfFloat)])
    (C: "filler = Scm_DoubleToHalf(Scm_GetDouble(fill))")
    (return (Scm_MakeF16Vector length filler))))

(define-cproc f16vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToF16Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_F16VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc f16vector-length (v::<f16vector>) ::<ulong> SCM_F16VECTOR_SIZE)

(define-cproc f16vector-copy
  (v::<f16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F16VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc f16vector-copy!
  (dst::<f16vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_F16VECTORP src)
      (Scm_Error "f16vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_F16VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_F16VECTOR src) sstart send))]
   [(SCM_F16VECTORP dstart) ; old API
    (return (Scm_F16VectorCopyX dst 0 (SCM_F16VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc f16vector-reverse-copy 
  (v::<f16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeF16Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_F16VECTOR_ELEMENT r j) (SCM_F16VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc f16vector-reverse-copy!
  (dst::<f16vector> dstart::<fixnum> src::<f16vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_F16VECTOR_ELEMENT dst dend) 
            (SCM_F16VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc f16vector-multi-copy!
  (dst::<f16vector> dstart::<fixnum> dstride::<fixnum>
   src::<f16vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_F16VECTOR_ELEMENT dst di)
                 (SCM_F16VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_F16VECTOR_ELEMENTS dst) di)
                      (+ (SCM_F16VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type ScmHalfFloat)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc f16vector->list
  (v::<f16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F16VectorToList)

(define-cproc reverse-f16vector->list
  (v::<f16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(ScmHalfFloat)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_F16VECTOR_ELEMENT v end))
      (C: "z = Scm_MakeFlonum(Scm_HalfToDouble(e))")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->f16vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_F16VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->f16vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-f16vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (f16vector-set! v i (car l) clamp))))

(define-cproc f16vector-fill!
  (v::<f16vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (ScmHalfFloat)])
    (C: "filler = Scm_DoubleToHalf(Scm_GetDouble(val))")
    (Scm_F16VectorFill v filler start end)))

(define-cproc f16vector->vector
  (v::<f16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F16VectorToVector)

(define-cproc vector->f16vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToF16Vector v start end (Scm_ClampMode clamp))))

(define-cproc f16vector=?              ; srfi-66
  (a::<f16vector> b::<f16vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc f16vector-compare        ; srfi-66
  (a::<f16vector> b::<f16vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (f16vector-unfold f len seed)
  (let1 rvec (make-f16vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (f16vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (f16vector-unfold-right f len seed)
  (let1 rvec (make-f16vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (f16vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (f16vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (f16vector-length v) l)) 0 vs)]
         [dst  (make-f16vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (f16vector-length (car vs)))])
        [(null? vs) dst]
      (f16vector-copy! dst k (car vs)))))
(define (f16vector-append . vs) (f16vector-concatenate vs))

(define-cproc f16vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_F16VECTORP v)
          (Scm_Error "<f16vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_F16VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeF16Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_F16VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_F16VECTOR_ELEMENT r i)
                    (SCM_F16VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (f16vector-take v n) (f16vector-copy v 0 n))
(define (f16vector-take-right v n)
  (f16vector-copy v (- (f16vector-length v) n)))
(define (f16vector-drop v n) (f16vector-copy v n))
(define (f16vector-drop-right v n)
  (f16vector-copy v 0 (- (f16vector-length v) n)))
(define (f16vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (f16vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (f16vector-copy v i (+ i n)) vs))))
  (rec 0 (f16vector-length v) '()))
(define (f16vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (f16vector=? a b)
       (or (null? rest)
           (apply f16vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (f16vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (f16vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (f16vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (f16vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (f16vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (f16vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (f16vector-ref vec i)) rs)])
          [(= i len) (list->f16vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->f16vector (reverse rs))]))))
(define (f16vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (f16vector-set! vec i (proc (f16vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (f16vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (f16vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (f16vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (f16vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (f16vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (f16vector-cumulate proc knil vec)
  (let* ([len (f16vector-length vec)]
         [rvec (make-f16vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (f16vector-ref vec i))
                 (f16vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (f16vector-take-while pred vec)
  (let1 len (f16vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->f16vector (reverse r))
        (let1 e (f16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->f16vector (reverse r))))))))
(define (f16vector-take-while-right pred vec)
  (let1 len (f16vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->f16vector r)
        (let1 e (f16vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->f16vector r)))))))
(define (f16vector-drop-while pred vec)
  (let1 len (f16vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-f16vector 0)
        (let1 e (f16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (f16vector-copy vec i)))))))
(define (f16vector-drop-while-right pred vec)
  (let1 len (f16vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-f16vector 0)
        (let1 e (f16vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (f16vector-copy vec 0 (+ i 1))))))))

(define (f16vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f16vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (f16vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (f16vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (f16vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f16vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (f16vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (f16vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (f16vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f16vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (f16vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (f16vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (f16vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (f16vector-partition pred vec)
  (let1 len (f16vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-f16vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (f16vector-set! rvec i (car rs)))
        (let1 e (f16vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (f16vector-filter pred vec)
  (let1 len (f16vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->f16vector (reverse rs))
        (let1 e (f16vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (f16vector-remove pred vec)
  (let1 len (f16vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->f16vector (reverse rs))
        (let1 e (f16vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc f16vector-swap! (v::<f16vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_F16VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_F16VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(ScmHalfFloat) (SCM_F16VECTOR_ELEMENT v i)])
    (set! (SCM_F16VECTOR_ELEMENT v i) (SCM_F16VECTOR_ELEMENT v j))
    (set! (SCM_F16VECTOR_ELEMENT v j) e)))

(define-cproc f16vector-reverse!
 (v::<f16vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_F16VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(ScmHalfFloat)])
      (while (< i j)
        (set! e (SCM_F16VECTOR_ELEMENT v i))
        (set! (SCM_F16VECTOR_ELEMENT v i) (SCM_F16VECTOR_ELEMENT v j))
        (set! (SCM_F16VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (f16vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (f16vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (f16vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (f16vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-f16vector-generator vec)
  (assume-type vec <f16vector>)
  (uvector->generator vec))

;; Comparator

(define f16vector-comparator
  (make-comparator f16vector? f16vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-f16vector vec :optional (port (current-output-port)))
  (assume-type vec <f16vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <f16vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-f16vector size)] [i 0])
      (proc (^[item] (f16vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->f16vector q))))
    ))

(define-method referencer ((v <f16vector>)) f16vector-ref)
(define-method modifier   ((v <f16vector>)) f16vector-set!)
(define-method size-of    ((v <f16vector>)) (f16vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <f16vector>))
  (f16vector->list v))
(define-method coerce-to  ((c <f16vector-meta>) (v <list>))
  (list->f16vector v))
(define-method coerce-to  ((c <vector-meta>) (v <f16vector>))
  (f16vector->vector v))
(define-method coerce-to  ((c <f16vector-meta>) (v <vector>))
  (vector->f16vector v))
(define-method coerce-to  ((c <f16vector-meta>) (v <f16vector>))
  (f16vector-copy v))
(define-method subseq ((v <f16vector>) . args)
  (apply f16vector-copy v args))



;;--------------------------------------------------------------------
;; f32vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc f32vector? (obj) ::<boolean> SCM_F32VECTORP)

(define-cproc f32vector-empty? (v::<f32vector>) ::<boolean>
  (return (== (SCM_F32VECTOR_SIZE v) 0)))

(define-cproc make-f32vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (float)])
    (C: "filler = (float)Scm_GetDouble(fill)")
    (return (Scm_MakeF32Vector length filler))))

(define-cproc f32vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToF32Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_F32VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc f32vector-length (v::<f32vector>) ::<ulong> SCM_F32VECTOR_SIZE)

(define-cproc f32vector-copy
  (v::<f32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F32VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc f32vector-copy!
  (dst::<f32vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_F32VECTORP src)
      (Scm_Error "f32vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_F32VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_F32VECTOR src) sstart send))]
   [(SCM_F32VECTORP dstart) ; old API
    (return (Scm_F32VectorCopyX dst 0 (SCM_F32VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc f32vector-reverse-copy 
  (v::<f32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeF32Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_F32VECTOR_ELEMENT r j) (SCM_F32VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc f32vector-reverse-copy!
  (dst::<f32vector> dstart::<fixnum> src::<f32vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_F32VECTOR_ELEMENT dst dend) 
            (SCM_F32VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc f32vector-multi-copy!
  (dst::<f32vector> dstart::<fixnum> dstride::<fixnum>
   src::<f32vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_F32VECTOR_ELEMENT dst di)
                 (SCM_F32VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_F32VECTOR_ELEMENTS dst) di)
                      (+ (SCM_F32VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type float)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc f32vector->list
  (v::<f32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F32VectorToList)

(define-cproc reverse-f32vector->list
  (v::<f32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(float)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_F32VECTOR_ELEMENT v end))
      (C: "z = Scm_MakeFlonum((double)e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->f32vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_F32VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->f32vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-f32vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (f32vector-set! v i (car l) clamp))))

(define-cproc f32vector-fill!
  (v::<f32vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (float)])
    (C: "filler = (float)Scm_GetDouble(val)")
    (Scm_F32VectorFill v filler start end)))

(define-cproc f32vector->vector
  (v::<f32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F32VectorToVector)

(define-cproc vector->f32vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToF32Vector v start end (Scm_ClampMode clamp))))

(define-cproc f32vector=?              ; srfi-66
  (a::<f32vector> b::<f32vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc f32vector-compare        ; srfi-66
  (a::<f32vector> b::<f32vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (f32vector-unfold f len seed)
  (let1 rvec (make-f32vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (f32vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (f32vector-unfold-right f len seed)
  (let1 rvec (make-f32vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (f32vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (f32vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (f32vector-length v) l)) 0 vs)]
         [dst  (make-f32vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (f32vector-length (car vs)))])
        [(null? vs) dst]
      (f32vector-copy! dst k (car vs)))))
(define (f32vector-append . vs) (f32vector-concatenate vs))

(define-cproc f32vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_F32VECTORP v)
          (Scm_Error "<f32vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_F32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeF32Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_F32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_F32VECTOR_ELEMENT r i)
                    (SCM_F32VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (f32vector-take v n) (f32vector-copy v 0 n))
(define (f32vector-take-right v n)
  (f32vector-copy v (- (f32vector-length v) n)))
(define (f32vector-drop v n) (f32vector-copy v n))
(define (f32vector-drop-right v n)
  (f32vector-copy v 0 (- (f32vector-length v) n)))
(define (f32vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (f32vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (f32vector-copy v i (+ i n)) vs))))
  (rec 0 (f32vector-length v) '()))
(define (f32vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (f32vector=? a b)
       (or (null? rest)
           (apply f32vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (f32vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (f32vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (f32vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (f32vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (f32vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (f32vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (f32vector-ref vec i)) rs)])
          [(= i len) (list->f32vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->f32vector (reverse rs))]))))
(define (f32vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (f32vector-set! vec i (proc (f32vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (f32vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (f32vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (f32vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (f32vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (f32vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (f32vector-cumulate proc knil vec)
  (let* ([len (f32vector-length vec)]
         [rvec (make-f32vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (f32vector-ref vec i))
                 (f32vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (f32vector-take-while pred vec)
  (let1 len (f32vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->f32vector (reverse r))
        (let1 e (f32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->f32vector (reverse r))))))))
(define (f32vector-take-while-right pred vec)
  (let1 len (f32vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->f32vector r)
        (let1 e (f32vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->f32vector r)))))))
(define (f32vector-drop-while pred vec)
  (let1 len (f32vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-f32vector 0)
        (let1 e (f32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (f32vector-copy vec i)))))))
(define (f32vector-drop-while-right pred vec)
  (let1 len (f32vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-f32vector 0)
        (let1 e (f32vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (f32vector-copy vec 0 (+ i 1))))))))

(define (f32vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f32vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (f32vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (f32vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (f32vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f32vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (f32vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (f32vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (f32vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f32vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (f32vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (f32vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (f32vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (f32vector-partition pred vec)
  (let1 len (f32vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-f32vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (f32vector-set! rvec i (car rs)))
        (let1 e (f32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (f32vector-filter pred vec)
  (let1 len (f32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->f32vector (reverse rs))
        (let1 e (f32vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (f32vector-remove pred vec)
  (let1 len (f32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->f32vector (reverse rs))
        (let1 e (f32vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc f32vector-swap! (v::<f32vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_F32VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_F32VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(float) (SCM_F32VECTOR_ELEMENT v i)])
    (set! (SCM_F32VECTOR_ELEMENT v i) (SCM_F32VECTOR_ELEMENT v j))
    (set! (SCM_F32VECTOR_ELEMENT v j) e)))

(define-cproc f32vector-reverse!
 (v::<f32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_F32VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(float)])
      (while (< i j)
        (set! e (SCM_F32VECTOR_ELEMENT v i))
        (set! (SCM_F32VECTOR_ELEMENT v i) (SCM_F32VECTOR_ELEMENT v j))
        (set! (SCM_F32VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (f32vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (f32vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (f32vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (f32vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-f32vector-generator vec)
  (assume-type vec <f32vector>)
  (uvector->generator vec))

;; Comparator

(define f32vector-comparator
  (make-comparator f32vector? f32vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-f32vector vec :optional (port (current-output-port)))
  (assume-type vec <f32vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <f32vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-f32vector size)] [i 0])
      (proc (^[item] (f32vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->f32vector q))))
    ))

(define-method referencer ((v <f32vector>)) f32vector-ref)
(define-method modifier   ((v <f32vector>)) f32vector-set!)
(define-method size-of    ((v <f32vector>)) (f32vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <f32vector>))
  (f32vector->list v))
(define-method coerce-to  ((c <f32vector-meta>) (v <list>))
  (list->f32vector v))
(define-method coerce-to  ((c <vector-meta>) (v <f32vector>))
  (f32vector->vector v))
(define-method coerce-to  ((c <f32vector-meta>) (v <vector>))
  (vector->f32vector v))
(define-method coerce-to  ((c <f32vector-meta>) (v <f32vector>))
  (f32vector-copy v))
(define-method subseq ((v <f32vector>) . args)
  (apply f32vector-copy v args))



;;--------------------------------------------------------------------
;; f64vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc f64vector? (obj) ::<boolean> SCM_F64VECTORP)

(define-cproc f64vector-empty? (v::<f64vector>) ::<boolean>
  (return (== (SCM_F64VECTOR_SIZE v) 0)))

(define-cproc make-f64vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (double)])
    (C: "filler = Scm_GetDouble(fill)")
    (return (Scm_MakeF64Vector length filler))))

(define-cproc f64vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToF64Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_F64VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc f64vector-length (v::<f64vector>) ::<ulong> SCM_F64VECTOR_SIZE)

(define-cproc f64vector-copy
  (v::<f64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F64VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc f64vector-copy!
  (dst::<f64vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_F64VECTORP src)
      (Scm_Error "f64vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_F64VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_F64VECTOR src) sstart send))]
   [(SCM_F64VECTORP dstart) ; old API
    (return (Scm_F64VectorCopyX dst 0 (SCM_F64VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc f64vector-reverse-copy 
  (v::<f64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeF64Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_F64VECTOR_ELEMENT r j) (SCM_F64VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc f64vector-reverse-copy!
  (dst::<f64vector> dstart::<fixnum> src::<f64vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_F64VECTOR_ELEMENT dst dend) 
            (SCM_F64VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc f64vector-multi-copy!
  (dst::<f64vector> dstart::<fixnum> dstride::<fixnum>
   src::<f64vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_F64VECTOR_ELEMENT dst di)
                 (SCM_F64VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_F64VECTOR_ELEMENTS dst) di)
                      (+ (SCM_F64VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type double)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc f64vector->list
  (v::<f64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F64VectorToList)

(define-cproc reverse-f64vector->list
  (v::<f64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(double)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_F64VECTOR_ELEMENT v end))
      (C: "z = Scm_MakeFlonum(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->f64vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_F64VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->f64vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-f64vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (f64vector-set! v i (car l) clamp))))

(define-cproc f64vector-fill!
  (v::<f64vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (double)])
    (C: "filler = Scm_GetDouble(val)")
    (Scm_F64VectorFill v filler start end)))

(define-cproc f64vector->vector
  (v::<f64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_F64VectorToVector)

(define-cproc vector->f64vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToF64Vector v start end (Scm_ClampMode clamp))))

(define-cproc f64vector=?              ; srfi-66
  (a::<f64vector> b::<f64vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc f64vector-compare        ; srfi-66
  (a::<f64vector> b::<f64vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (f64vector-unfold f len seed)
  (let1 rvec (make-f64vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (f64vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (f64vector-unfold-right f len seed)
  (let1 rvec (make-f64vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (f64vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (f64vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (f64vector-length v) l)) 0 vs)]
         [dst  (make-f64vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (f64vector-length (car vs)))])
        [(null? vs) dst]
      (f64vector-copy! dst k (car vs)))))
(define (f64vector-append . vs) (f64vector-concatenate vs))

(define-cproc f64vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_F64VECTORP v)
          (Scm_Error "<f64vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_F64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeF64Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_F64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_F64VECTOR_ELEMENT r i)
                    (SCM_F64VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (f64vector-take v n) (f64vector-copy v 0 n))
(define (f64vector-take-right v n)
  (f64vector-copy v (- (f64vector-length v) n)))
(define (f64vector-drop v n) (f64vector-copy v n))
(define (f64vector-drop-right v n)
  (f64vector-copy v 0 (- (f64vector-length v) n)))
(define (f64vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (f64vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (f64vector-copy v i (+ i n)) vs))))
  (rec 0 (f64vector-length v) '()))
(define (f64vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (f64vector=? a b)
       (or (null? rest)
           (apply f64vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (f64vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (f64vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (f64vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (f64vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (f64vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (f64vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (f64vector-ref vec i)) rs)])
          [(= i len) (list->f64vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->f64vector (reverse rs))]))))
(define (f64vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (f64vector-set! vec i (proc (f64vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (f64vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (f64vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (f64vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (f64vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (f64vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (f64vector-cumulate proc knil vec)
  (let* ([len (f64vector-length vec)]
         [rvec (make-f64vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (f64vector-ref vec i))
                 (f64vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (f64vector-take-while pred vec)
  (let1 len (f64vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->f64vector (reverse r))
        (let1 e (f64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->f64vector (reverse r))))))))
(define (f64vector-take-while-right pred vec)
  (let1 len (f64vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->f64vector r)
        (let1 e (f64vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->f64vector r)))))))
(define (f64vector-drop-while pred vec)
  (let1 len (f64vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-f64vector 0)
        (let1 e (f64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (f64vector-copy vec i)))))))
(define (f64vector-drop-while-right pred vec)
  (let1 len (f64vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-f64vector 0)
        (let1 e (f64vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (f64vector-copy vec 0 (+ i 1))))))))

(define (f64vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f64vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (f64vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (f64vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (f64vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f64vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (f64vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (f64vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (f64vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (f64vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (f64vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (f64vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (f64vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (f64vector-partition pred vec)
  (let1 len (f64vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-f64vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (f64vector-set! rvec i (car rs)))
        (let1 e (f64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (f64vector-filter pred vec)
  (let1 len (f64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->f64vector (reverse rs))
        (let1 e (f64vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (f64vector-remove pred vec)
  (let1 len (f64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->f64vector (reverse rs))
        (let1 e (f64vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc f64vector-swap! (v::<f64vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_F64VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_F64VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(double) (SCM_F64VECTOR_ELEMENT v i)])
    (set! (SCM_F64VECTOR_ELEMENT v i) (SCM_F64VECTOR_ELEMENT v j))
    (set! (SCM_F64VECTOR_ELEMENT v j) e)))

(define-cproc f64vector-reverse!
 (v::<f64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_F64VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(double)])
      (while (< i j)
        (set! e (SCM_F64VECTOR_ELEMENT v i))
        (set! (SCM_F64VECTOR_ELEMENT v i) (SCM_F64VECTOR_ELEMENT v j))
        (set! (SCM_F64VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (f64vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (f64vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (f64vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (f64vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-f64vector-generator vec)
  (assume-type vec <f64vector>)
  (uvector->generator vec))

;; Comparator

(define f64vector-comparator
  (make-comparator f64vector? f64vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-f64vector vec :optional (port (current-output-port)))
  (assume-type vec <f64vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <f64vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-f64vector size)] [i 0])
      (proc (^[item] (f64vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->f64vector q))))
    ))

(define-method referencer ((v <f64vector>)) f64vector-ref)
(define-method modifier   ((v <f64vector>)) f64vector-set!)
(define-method size-of    ((v <f64vector>)) (f64vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <f64vector>))
  (f64vector->list v))
(define-method coerce-to  ((c <f64vector-meta>) (v <list>))
  (list->f64vector v))
(define-method coerce-to  ((c <vector-meta>) (v <f64vector>))
  (f64vector->vector v))
(define-method coerce-to  ((c <f64vector-meta>) (v <vector>))
  (vector->f64vector v))
(define-method coerce-to  ((c <f64vector-meta>) (v <f64vector>))
  (f64vector-copy v))
(define-method subseq ((v <f64vector>) . args)
  (apply f64vector-copy v args))



;;--------------------------------------------------------------------
;; c32vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc c32vector? (obj) ::<boolean> SCM_C32VECTORP)

(define-cproc c32vector-empty? (v::<c32vector>) ::<boolean>
  (return (== (SCM_C32VECTOR_SIZE v) 0)))

(define-cproc make-c32vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (ScmHalfComplex)])
    (C: "filler = Scm_GetHalfComplex(fill)")
    (return (Scm_MakeC32Vector length filler))))

(define-cproc c32vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToC32Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_C32VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc c32vector-length (v::<c32vector>) ::<ulong> SCM_C32VECTOR_SIZE)

(define-cproc c32vector-copy
  (v::<c32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C32VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc c32vector-copy!
  (dst::<c32vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_C32VECTORP src)
      (Scm_Error "c32vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_C32VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_C32VECTOR src) sstart send))]
   [(SCM_C32VECTORP dstart) ; old API
    (return (Scm_C32VectorCopyX dst 0 (SCM_C32VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc c32vector-reverse-copy 
  (v::<c32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeC32Vector (- end start) 
                                                  (C: "(ScmHalfComplex){0, 0}")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_C32VECTOR_ELEMENT r j) (SCM_C32VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc c32vector-reverse-copy!
  (dst::<c32vector> dstart::<fixnum> src::<c32vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_C32VECTOR_ELEMENT dst dend) 
            (SCM_C32VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc c32vector-multi-copy!
  (dst::<c32vector> dstart::<fixnum> dstride::<fixnum>
   src::<c32vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_C32VECTOR_ELEMENT dst di)
                 (SCM_C32VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_C32VECTOR_ELEMENTS dst) di)
                      (+ (SCM_C32VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type ScmHalfComplex)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc c32vector->list
  (v::<c32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C32VectorToList)

(define-cproc reverse-c32vector->list
  (v::<c32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(ScmHalfComplex)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_C32VECTOR_ELEMENT v end))
      (C: "z = Scm_HalfComplexToComplex(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->c32vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_C32VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->c32vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-c32vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (c32vector-set! v i (car l) clamp))))

(define-cproc c32vector-fill!
  (v::<c32vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (ScmHalfComplex)])
    (C: "filler = Scm_GetHalfComplex(val)")
    (Scm_C32VectorFill v filler start end)))

(define-cproc c32vector->vector
  (v::<c32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C32VectorToVector)

(define-cproc vector->c32vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToC32Vector v start end (Scm_ClampMode clamp))))

(define-cproc c32vector=?              ; srfi-66
  (a::<c32vector> b::<c32vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc c32vector-compare        ; srfi-66
  (a::<c32vector> b::<c32vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (c32vector-unfold f len seed)
  (let1 rvec (make-c32vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (c32vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (c32vector-unfold-right f len seed)
  (let1 rvec (make-c32vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (c32vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (c32vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (c32vector-length v) l)) 0 vs)]
         [dst  (make-c32vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (c32vector-length (car vs)))])
        [(null? vs) dst]
      (c32vector-copy! dst k (car vs)))))
(define (c32vector-append . vs) (c32vector-concatenate vs))

(define-cproc c32vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_C32VECTORP v)
          (Scm_Error "<c32vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_C32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeC32Vector total (C: "(ScmHalfComplex){0, 0}"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_C32VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_C32VECTOR_ELEMENT r i)
                    (SCM_C32VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (c32vector-take v n) (c32vector-copy v 0 n))
(define (c32vector-take-right v n)
  (c32vector-copy v (- (c32vector-length v) n)))
(define (c32vector-drop v n) (c32vector-copy v n))
(define (c32vector-drop-right v n)
  (c32vector-copy v 0 (- (c32vector-length v) n)))
(define (c32vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (c32vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (c32vector-copy v i (+ i n)) vs))))
  (rec 0 (c32vector-length v) '()))
(define (c32vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (c32vector=? a b)
       (or (null? rest)
           (apply c32vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (c32vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (c32vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (c32vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (c32vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (c32vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (c32vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (c32vector-ref vec i)) rs)])
          [(= i len) (list->c32vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->c32vector (reverse rs))]))))
(define (c32vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (c32vector-set! vec i (proc (c32vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (c32vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (c32vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (c32vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (c32vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (c32vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (c32vector-cumulate proc knil vec)
  (let* ([len (c32vector-length vec)]
         [rvec (make-c32vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (c32vector-ref vec i))
                 (c32vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (c32vector-take-while pred vec)
  (let1 len (c32vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->c32vector (reverse r))
        (let1 e (c32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->c32vector (reverse r))))))))
(define (c32vector-take-while-right pred vec)
  (let1 len (c32vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->c32vector r)
        (let1 e (c32vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->c32vector r)))))))
(define (c32vector-drop-while pred vec)
  (let1 len (c32vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-c32vector 0)
        (let1 e (c32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (c32vector-copy vec i)))))))
(define (c32vector-drop-while-right pred vec)
  (let1 len (c32vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-c32vector 0)
        (let1 e (c32vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (c32vector-copy vec 0 (+ i 1))))))))

(define (c32vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c32vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (c32vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (c32vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (c32vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c32vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (c32vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (c32vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (c32vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c32vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (c32vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (c32vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (c32vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (c32vector-partition pred vec)
  (let1 len (c32vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-c32vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (c32vector-set! rvec i (car rs)))
        (let1 e (c32vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (c32vector-filter pred vec)
  (let1 len (c32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->c32vector (reverse rs))
        (let1 e (c32vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (c32vector-remove pred vec)
  (let1 len (c32vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->c32vector (reverse rs))
        (let1 e (c32vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc c32vector-swap! (v::<c32vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_C32VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_C32VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(ScmHalfComplex) (SCM_C32VECTOR_ELEMENT v i)])
    (set! (SCM_C32VECTOR_ELEMENT v i) (SCM_C32VECTOR_ELEMENT v j))
    (set! (SCM_C32VECTOR_ELEMENT v j) e)))

(define-cproc c32vector-reverse!
 (v::<c32vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_C32VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(ScmHalfComplex)])
      (while (< i j)
        (set! e (SCM_C32VECTOR_ELEMENT v i))
        (set! (SCM_C32VECTOR_ELEMENT v i) (SCM_C32VECTOR_ELEMENT v j))
        (set! (SCM_C32VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (c32vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (c32vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (c32vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (c32vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-c32vector-generator vec)
  (assume-type vec <c32vector>)
  (uvector->generator vec))

;; Comparator

(define c32vector-comparator
  (make-comparator c32vector? c32vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-c32vector vec :optional (port (current-output-port)))
  (assume-type vec <c32vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <c32vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-c32vector size)] [i 0])
      (proc (^[item] (c32vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->c32vector q))))
    ))

(define-method referencer ((v <c32vector>)) c32vector-ref)
(define-method modifier   ((v <c32vector>)) c32vector-set!)
(define-method size-of    ((v <c32vector>)) (c32vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <c32vector>))
  (c32vector->list v))
(define-method coerce-to  ((c <c32vector-meta>) (v <list>))
  (list->c32vector v))
(define-method coerce-to  ((c <vector-meta>) (v <c32vector>))
  (c32vector->vector v))
(define-method coerce-to  ((c <c32vector-meta>) (v <vector>))
  (vector->c32vector v))
(define-method coerce-to  ((c <c32vector-meta>) (v <c32vector>))
  (c32vector-copy v))
(define-method subseq ((v <c32vector>) . args)
  (apply c32vector-copy v args))



;;--------------------------------------------------------------------
;; c64vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc c64vector? (obj) ::<boolean> SCM_C64VECTORP)

(define-cproc c64vector-empty? (v::<c64vector>) ::<boolean>
  (return (== (SCM_C64VECTOR_SIZE v) 0)))

(define-cproc make-c64vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (ScmFloatComplex)])
    (C: "filler = Scm_GetFloatComplex(fill)")
    (return (Scm_MakeC64Vector length filler))))

(define-cproc c64vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToC64Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_C64VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc c64vector-length (v::<c64vector>) ::<ulong> SCM_C64VECTOR_SIZE)

(define-cproc c64vector-copy
  (v::<c64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C64VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc c64vector-copy!
  (dst::<c64vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_C64VECTORP src)
      (Scm_Error "c64vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_C64VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_C64VECTOR src) sstart send))]
   [(SCM_C64VECTORP dstart) ; old API
    (return (Scm_C64VectorCopyX dst 0 (SCM_C64VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc c64vector-reverse-copy 
  (v::<c64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeC64Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_C64VECTOR_ELEMENT r j) (SCM_C64VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc c64vector-reverse-copy!
  (dst::<c64vector> dstart::<fixnum> src::<c64vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_C64VECTOR_ELEMENT dst dend) 
            (SCM_C64VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc c64vector-multi-copy!
  (dst::<c64vector> dstart::<fixnum> dstride::<fixnum>
   src::<c64vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_C64VECTOR_ELEMENT dst di)
                 (SCM_C64VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_C64VECTOR_ELEMENTS dst) di)
                      (+ (SCM_C64VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type ScmFloatComplex)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc c64vector->list
  (v::<c64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C64VectorToList)

(define-cproc reverse-c64vector->list
  (v::<c64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(ScmFloatComplex)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_C64VECTOR_ELEMENT v end))
      (C: "z = Scm_FloatComplexToComplex(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->c64vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_C64VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->c64vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-c64vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (c64vector-set! v i (car l) clamp))))

(define-cproc c64vector-fill!
  (v::<c64vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (ScmFloatComplex)])
    (C: "filler = Scm_GetFloatComplex(val)")
    (Scm_C64VectorFill v filler start end)))

(define-cproc c64vector->vector
  (v::<c64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C64VectorToVector)

(define-cproc vector->c64vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToC64Vector v start end (Scm_ClampMode clamp))))

(define-cproc c64vector=?              ; srfi-66
  (a::<c64vector> b::<c64vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc c64vector-compare        ; srfi-66
  (a::<c64vector> b::<c64vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (c64vector-unfold f len seed)
  (let1 rvec (make-c64vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (c64vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (c64vector-unfold-right f len seed)
  (let1 rvec (make-c64vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (c64vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (c64vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (c64vector-length v) l)) 0 vs)]
         [dst  (make-c64vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (c64vector-length (car vs)))])
        [(null? vs) dst]
      (c64vector-copy! dst k (car vs)))))
(define (c64vector-append . vs) (c64vector-concatenate vs))

(define-cproc c64vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_C64VECTORP v)
          (Scm_Error "<c64vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_C64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeC64Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_C64VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_C64VECTOR_ELEMENT r i)
                    (SCM_C64VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (c64vector-take v n) (c64vector-copy v 0 n))
(define (c64vector-take-right v n)
  (c64vector-copy v (- (c64vector-length v) n)))
(define (c64vector-drop v n) (c64vector-copy v n))
(define (c64vector-drop-right v n)
  (c64vector-copy v 0 (- (c64vector-length v) n)))
(define (c64vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (c64vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (c64vector-copy v i (+ i n)) vs))))
  (rec 0 (c64vector-length v) '()))
(define (c64vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (c64vector=? a b)
       (or (null? rest)
           (apply c64vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (c64vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (c64vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (c64vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (c64vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (c64vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (c64vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (c64vector-ref vec i)) rs)])
          [(= i len) (list->c64vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->c64vector (reverse rs))]))))
(define (c64vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (c64vector-set! vec i (proc (c64vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (c64vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (c64vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (c64vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (c64vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (c64vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (c64vector-cumulate proc knil vec)
  (let* ([len (c64vector-length vec)]
         [rvec (make-c64vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (c64vector-ref vec i))
                 (c64vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (c64vector-take-while pred vec)
  (let1 len (c64vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->c64vector (reverse r))
        (let1 e (c64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->c64vector (reverse r))))))))
(define (c64vector-take-while-right pred vec)
  (let1 len (c64vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->c64vector r)
        (let1 e (c64vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->c64vector r)))))))
(define (c64vector-drop-while pred vec)
  (let1 len (c64vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-c64vector 0)
        (let1 e (c64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (c64vector-copy vec i)))))))
(define (c64vector-drop-while-right pred vec)
  (let1 len (c64vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-c64vector 0)
        (let1 e (c64vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (c64vector-copy vec 0 (+ i 1))))))))

(define (c64vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c64vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (c64vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (c64vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (c64vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c64vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (c64vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (c64vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (c64vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c64vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (c64vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (c64vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (c64vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (c64vector-partition pred vec)
  (let1 len (c64vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-c64vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (c64vector-set! rvec i (car rs)))
        (let1 e (c64vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (c64vector-filter pred vec)
  (let1 len (c64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->c64vector (reverse rs))
        (let1 e (c64vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (c64vector-remove pred vec)
  (let1 len (c64vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->c64vector (reverse rs))
        (let1 e (c64vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc c64vector-swap! (v::<c64vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_C64VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_C64VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(ScmFloatComplex) (SCM_C64VECTOR_ELEMENT v i)])
    (set! (SCM_C64VECTOR_ELEMENT v i) (SCM_C64VECTOR_ELEMENT v j))
    (set! (SCM_C64VECTOR_ELEMENT v j) e)))

(define-cproc c64vector-reverse!
 (v::<c64vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_C64VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(ScmFloatComplex)])
      (while (< i j)
        (set! e (SCM_C64VECTOR_ELEMENT v i))
        (set! (SCM_C64VECTOR_ELEMENT v i) (SCM_C64VECTOR_ELEMENT v j))
        (set! (SCM_C64VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (c64vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (c64vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (c64vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (c64vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-c64vector-generator vec)
  (assume-type vec <c64vector>)
  (uvector->generator vec))

;; Comparator

(define c64vector-comparator
  (make-comparator c64vector? c64vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-c64vector vec :optional (port (current-output-port)))
  (assume-type vec <c64vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <c64vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-c64vector size)] [i 0])
      (proc (^[item] (c64vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->c64vector q))))
    ))

(define-method referencer ((v <c64vector>)) c64vector-ref)
(define-method modifier   ((v <c64vector>)) c64vector-set!)
(define-method size-of    ((v <c64vector>)) (c64vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <c64vector>))
  (c64vector->list v))
(define-method coerce-to  ((c <c64vector-meta>) (v <list>))
  (list->c64vector v))
(define-method coerce-to  ((c <vector-meta>) (v <c64vector>))
  (c64vector->vector v))
(define-method coerce-to  ((c <c64vector-meta>) (v <vector>))
  (vector->c64vector v))
(define-method coerce-to  ((c <c64vector-meta>) (v <c64vector>))
  (c64vector-copy v))
(define-method subseq ((v <c64vector>) . args)
  (apply c64vector-copy v args))



;;--------------------------------------------------------------------
;; c128vector basic API
;;

;; NB: Predicates referencers and modifiers are in the core.

(define-cproc c128vector? (obj) ::<boolean> SCM_C128VECTORP)

(define-cproc c128vector-empty? (v::<c128vector>) ::<boolean>
  (return (== (SCM_C128VECTOR_SIZE v) 0)))

(define-cproc make-c128vector (length::<fixnum> :optional (fill 0))
  (let* ([filler :: (ScmDoubleComplex)])
    (C: "filler = Scm_GetDoubleComplex(fill)")
    (return (Scm_MakeC128Vector length filler))))

(define-cproc c128vector (:optarray (elts nelts 10) :rest args)
  :fast-flonum
  (cond [(SCM_NULLP args)
         (return (Scm_ObjArrayToC128Vector elts nelts SCM_CLAMP_ERROR))]
        [else
         (let* ([i::int (- nelts 1)] [p args])
           (for [() (>= i 0) (post-- i)]
                (SCM_FLONUM_ENSURE_MEM (aref elts i))
                (set! p (Scm_Cons (aref elts i) p)))
           (return (Scm_ListToUVector SCM_CLASS_C128VECTOR p SCM_CLAMP_ERROR)))]))

(define-cproc c128vector-length (v::<c128vector>) ::<ulong> SCM_C128VECTOR_SIZE)

(define-cproc c128vector-copy
  (v::<c128vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C128VectorCopy)

;; NB: this function accommodates to two APIs.
;; The 'modern' API, compatible to srfi-13 and srfi-43, takes arguments:
;;    (dst dstart src :optional sstart send)
;; The old API only takes:
;;    (dst src)
;; We dispatch by the second argument.  The old API is deprecated, but
;; kept for the existing code.
(define-cproc c128vector-copy!
  (dst::<c128vector> dstart :optional src (sstart::<int> 0) (send::<int> -1))
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (cond
   [(SCM_INTEGERP dstart) ; new API
    (unless (SCM_C128VECTORP src)
      (Scm_Error "c128vector-copy!: argument is not a matching uvector: %S"src))
    (return (Scm_C128VectorCopyX dst (Scm_GetInteger dstart)
                  (SCM_C128VECTOR src) sstart send))]
   [(SCM_C128VECTORP dstart) ; old API
    (return (Scm_C128VectorCopyX dst 0 (SCM_C128VECTOR dstart) 0 -1))]
   [else (SCM_TYPE_ERROR dstart "integer") (return SCM_UNDEFINED)]))

(define-cproc c128vector-reverse-copy 
  (v::<c128vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([r::ScmUVector* (SCM_UVECTOR (Scm_MakeC128Vector (- end start) 
                                                  (C: "0")))]
           [i::ScmSmallInt (- end 1)]
           [j::ScmSmallInt 0])
      (while (>= i start)
        (set! (SCM_C128VECTOR_ELEMENT r j) (SCM_C128VECTOR_ELEMENT v i))
        (post-- i)
        (post++ j))
      (return (SCM_OBJ r)))))

(define-cproc c128vector-reverse-copy!
  (dst::<c128vector> dstart::<fixnum> src::<c128vector>
          :optional (sstart::<fixnum> 0) (send::<fixnum> -1))
  ::<void>
  (let* ([dlen::ScmSmallInt (SCM_UVECTOR_SIZE dst)]
         [slen::ScmSmallInt (SCM_UVECTOR_SIZE src)]
         [dend::ScmSmallInt -1])
    (SCM_UVECTOR_CHECK_MUTABLE dst)
    (SCM_CHECK_START_END sstart send slen)
    (SCM_CHECK_START_END dstart dend dlen)
    (set! dend (+ dstart (- send sstart)))
    (when (> dend dlen)
      (Scm_Error "Copy region is out of bound, from [%d,%d]%S to [%d,%d]%S"
                 sstart send (SCM_OBJ src)
                 dstart dend (SCM_OBJ dst)))
    (while (>= (pre-- dend) dstart)
      (set! (SCM_C128VECTOR_ELEMENT dst dend) 
            (SCM_C128VECTOR_ELEMENT src sstart))
      (post++ sstart))))

;; multi-copy! - copy src repeatedly to different parts of dst.
(define-cproc c128vector-multi-copy!
  (dst::<c128vector> dstart::<fixnum> dstride::<fixnum>
   src::<c128vector> :optional (sstart::<fixnum> 0) (ssize::<fixnum> 0)
                               (sstride::<fixnum> -1) (count::<fixnum> -1))
  ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE dst)
  (when (< sstride 0)
    (if (<= ssize 0) (set! sstride 0) (set! sstride ssize)))
  (when (<= ssize 0)
    (set! ssize (- (SCM_UVECTOR_SIZE src) sstart)))
  (let* ([di::long dstart] [si::long sstart]
         [dlen::long (SCM_UVECTOR_SIZE dst)]
         [slen::long (SCM_UVECTOR_SIZE src)]
         [c::long 0]
         [cnt::long (?: (< count 0) LONG_MAX count)])
    (if (== ssize 1)
      ;; shortcut for optimization
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (set! (SCM_C128VECTOR_ELEMENT dst di)
                 (SCM_C128VECTOR_ELEMENT src si))
           (+= di dstride)
           (+= si sstride))
      ;; general case
      (for [() (and (< c cnt) (< di dlen) (< si slen)) (inc! c)]
           (let* ([nitems::long ssize])
             (when (< dlen (+ di nitems)) (set! nitems (- dlen di)))
             (when (< slen (+ si nitems)) (set! nitems (- slen si)))
             (memmove (+ (SCM_C128VECTOR_ELEMENTS dst) di)
                      (+ (SCM_C128VECTOR_ELEMENTS src) si)
                      (* nitems (sizeof (.type ScmDoubleComplex)))))
           (+= di dstride)
           (+= si sstride)))))

(define-cproc c128vector->list
  (v::<c128vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C128VectorToList)

(define-cproc reverse-c128vector->list
  (v::<c128vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  (let* ([len::ScmSmallInt (SCM_UVECTOR_SIZE v)]
         [h SCM_NIL] [t SCM_NIL] [e::(ScmDoubleComplex)] [z])
    (SCM_CHECK_START_END start end len)
    (pre-- end)
    (while (<= start end)
      (set! e (SCM_C128VECTOR_ELEMENT v end))
      (C: "z = Scm_DoubleComplexToComplex(e)")
      (SCM_APPEND1 h t z)
      (pre-- end))
    (return h)))

(define-cproc list->c128vector (l::<list> :optional clamp)
  (return (Scm_ListToUVector SCM_CLASS_C128VECTOR l (Scm_ClampMode clamp))))

(define (reverse-list->c128vector l :optional (clamp #f))
  (let* ([len (length l)]
         [v (make-c128vector len)])
    (do [(l l (cdr l))
         (i (- len 1) (- i 1))]
        [(< i 0) v]
      (c128vector-set! v i (car l) clamp))))

(define-cproc c128vector-fill!
  (v::<c128vector> val :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
  (let* ([filler :: (ScmDoubleComplex)])
    (C: "filler = Scm_GetDoubleComplex(val)")
    (Scm_C128VectorFill v filler start end)))

(define-cproc c128vector->vector
  (v::<c128vector> :optional (start::<fixnum> 0) (end::<fixnum> -1))
  Scm_C128VectorToVector)

(define-cproc vector->c128vector
  (v::<vector> :optional (start::<fixnum> 0) (end::<fixnum> -1) clamp)
  (return (Scm_VectorToC128Vector v start end (Scm_ClampMode clamp))))

(define-cproc c128vector=?              ; srfi-66
  (a::<c128vector> b::<c128vector>)     ;  we just typecheck args and call equal?
  ::<boolean>
  (return (Scm_EqualP (SCM_OBJ a) (SCM_OBJ b))))

(define-cproc c128vector-compare        ; srfi-66
  (a::<c128vector> b::<c128vector>)     ;  we just typecheck args and call compare
  ::<int>
  (return (Scm_Compare (SCM_OBJ a) (SCM_OBJ b))))

;;;
;;; Some srfi-160 procedures
;;;

;; Constructors
(define (c128vector-unfold f len seed)
  (let1 rvec (make-c128vector len)
    (let loop ([i 0] [seed seed])
      (if (= i len)
        rvec
        (receive (e seed) (f i seed)
          (c128vector-set! rvec i e)
          (loop (+ i 1) seed))))))
(define (c128vector-unfold-right f len seed)
  (let1 rvec (make-c128vector len)
    (let loop ([i (- len 1)] [seed seed])
      (if (< i 0)
        rvec
        (receive (e seed) (f i seed)
          (c128vector-set! rvec i e)
          (loop (- i 1) seed))))))

(define (c128vector-concatenate vs)
  (let* ([size (fold (^[v l] (+ (c128vector-length v) l)) 0 vs)]
         [dst  (make-c128vector size)])
    (do ([vs vs (cdr vs)]
         [k  0  (+ k (c128vector-length (car vs)))])
        [(null? vs) dst]
      (c128vector-copy! dst k (car vs)))))
(define (c128vector-append . vs) (c128vector-concatenate vs))

(define-cproc c128vector-append-subvectors (:rest args)
  ;; first path - check args and lengths
  (unless (== (% (Scm_Length args) 3) 0)
    (Scm_Error "Argument count isn't a multiple of 3: %S" args))
  (let* ([total::ScmSmallInt 0]
         [lis args])
    (while (SCM_PAIRP lis)
      (let* ([v (SCM_CAR lis)]
             [s (SCM_CADR lis)]
             [e (SCM_CAR (SCM_CDDR lis))])
        (unless (SCM_C128VECTORP v)
          (Scm_Error "<c128vector> expected, but got: %S" v))
        (unless (SCM_INTP s)
          (Scm_Error "fixnum expected for start, but got: %S" s))
        (unless (SCM_INTP e)
          (Scm_Error "fixnum expected for end, but got: %S" e))
        (let* ([start::ScmSmallInt (SCM_INT_VALUE s)]
               [end::ScmSmallInt (SCM_INT_VALUE e)]
               [len::ScmSmallInt (SCM_C128VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (+= total (- end start)))
        (set! lis (SCM_CDR (SCM_CDDR lis)))))
    ;; Second path - fill it
    (let* ([r (Scm_MakeC128Vector total (C: "0"))]
           [i::ScmSmallInt 0]
           [lis args])
      (while (SCM_PAIRP lis)
        (let* ([v (SCM_CAR lis)]
               [start::ScmSmallInt (SCM_INT_VALUE (SCM_CADR lis))]
               [end::ScmSmallInt   (SCM_INT_VALUE (SCM_CAR (SCM_CDDR lis)))]
               [len::ScmSmallInt   (SCM_C128VECTOR_SIZE v)])
          (SCM_CHECK_START_END start end len)
          (let* ([j::ScmSmallInt start])
            (while (< j end)
              (set! (SCM_C128VECTOR_ELEMENT r i)
                    (SCM_C128VECTOR_ELEMENT v j))
              (pre++ i)
              (pre++ j))))
        (set! lis (SCM_CDR (SCM_CDDR lis))))
      (return r))))

;; Iteration

(define (c128vector-take v n) (c128vector-copy v 0 n))
(define (c128vector-take-right v n)
  (c128vector-copy v (- (c128vector-length v) n)))
(define (c128vector-drop v n) (c128vector-copy v n))
(define (c128vector-drop-right v n)
  (c128vector-copy v 0 (- (c128vector-length v) n)))
(define (c128vector-segment v n)
  (define (rec i len vs)
    (if (<= (- len i) n)
      (reverse (cons (c128vector-copy v i) vs))
      (rec (+ i n) len 
           (cons (c128vector-copy v i (+ i n)) vs))))
  (rec 0 (c128vector-length v) '()))
(define (c128vector= a b . rest) ; can have shortcut of 3 arg case as well
  (and (c128vector=? a b)
       (or (null? rest)
           (apply c128vector= b rest))))

(define (%minlen vec vecs)
  (apply min (uvector-length vec) (map uvector-length vecs)))
(define (%vecrefs i vec vecs)
  (cons (uvector-ref vec i) (map (cut uvector-ref <> i) vecs)))

(define (c128vector-fold kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (do ([i 0 (+ i 1)]
           [seed knil (kons seed (c128vector-ref vec i))])
          [(= i len) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(= i len) seed]))))
(define (c128vector-fold-right kons knil vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (do ([i (- len 1) (- i 1)]
           [seed knil (kons (c128vector-ref vec i) seed)])
          [(< i 0) seed]))
    (let1 len (%minlen vec vecs)
      (do ([i (- len 1) (- i 1)]
           [seed knil (apply kons seed (%vecrefs i vec vecs))])
          [(< i 0) seed]))))
(define (c128vector-map proc vec . vecs)
  (if (null? vecs)
    ;; we need intermediate list to be restart-safe
    (let1 len (c128vector-length vec)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (proc (c128vector-ref vec i)) rs)])
          [(= i len) (list->c128vector (reverse rs))]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [rs '() (cons (apply proc (%vecrefs i vec vecs)) rs)])
          [(= i len) (list->c128vector (reverse rs))]))))
(define (c128vector-map! proc vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (c128vector-set! vec i (proc (c128vector-ref vec i)))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) vec]
        (c128vector-set! vec i (apply proc (%vecrefs i vec vecs)))))))
(define (c128vector-for-each proc vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (proc (c128vector-ref vec i))))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)])
          [(= i len) (undefined)]
        (apply proc (%vecrefs i vec vecs))))))
(define (c128vector-count pred vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (do ([i 0 (+ i 1)]
           [c 0 (if (pred (c128vector-ref vec i)) (+ c 1) c)])
          [(= i len) c]))
    (let1 len (%minlen vec vecs)
      (do ([i 0 (+ i 1)]
           [c 0 (if (apply pred (%vecrefs i vec vecs)) (+ c 1) c)])
          [(= i len) c]))))
(define (c128vector-cumulate proc knil vec)
  (let* ([len (c128vector-length vec)]
         [rvec (make-c128vector len)])
    (do ([i 0 (+ i 1)]
         [seed knil
               (rlet1 seed (proc seed (c128vector-ref vec i))
                 (c128vector-set! rvec i seed))])
        [(= i len) rvec])))
  
;; Searching

(define (c128vector-take-while pred vec)
  (let1 len (c128vector-length vec)
    (let loop ([i 0] [r '()])
      (if (= i len)
        (list->c128vector (reverse r))
        (let1 e (c128vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e r))
            (list->c128vector (reverse r))))))))
(define (c128vector-take-while-right pred vec)
  (let1 len (c128vector-length vec)
    (let loop ([i (- len 1)] [r '()])
      (if (< i 0)
        (list->c128vector r)
        (let1 e (c128vector-ref vec i)
          (if (pred e)
            (loop (- i 1) (cons e r))
            (list->c128vector r)))))))
(define (c128vector-drop-while pred vec)
  (let1 len (c128vector-length vec)
    (let loop ([i 0])
      (if (= i len)
        (make-c128vector 0)
        (let1 e (c128vector-ref vec i)
          (if (pred e)
            (loop (+ i 1))
            (c128vector-copy vec i)))))))
(define (c128vector-drop-while-right pred vec)
  (let1 len (c128vector-length vec)
    (let loop ([i (- len 1)])
      (if (< i 0)
        (make-c128vector 0)
        (let1 e (c128vector-ref vec i)
          (if (pred e)
            (loop (- i 1))
            (c128vector-copy vec 0 (+ i 1))))))))

(define (c128vector-index pred vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c128vector-ref vec i)) i]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (+ i 1))])))))
(define (c128vector-index-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (c128vector-ref vec i)) i]
              [else (loop (- i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) i]
              [else (loop (- i 1))])))))
(define (c128vector-skip pred vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c128vector-ref vec i)) (loop (+ i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (+ i 1))]
              [else i])))))
(define (c128vector-skip-right pred vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(pred (c128vector-ref vec i)) (loop (- i 1))]
              [else i])))
    (let1 len (%minlen vec vecs)
      (let loop ([i (- len 1)])
        (cond [(< i 0) #f]
              [(apply pred (%vecrefs i vec vecs)) (loop (- i 1))]
              [else i])))))
(define (c128vector-any pred vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(pred (c128vector-ref vec i))]
              [else (loop (+ i 1))])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0])
        (cond [(= i len) #f]
              [(apply pred (%vecrefs i vec vecs))]
              [else (loop (+ i 1))])))))
(define (c128vector-every pred vec . vecs)
  (if (null? vecs)
    (let1 len (c128vector-length vec)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(pred (c128vector-ref vec i)) => (^r (loop (+ i 1) r))]
              [else #f])))
    (let1 len (%minlen vec vecs)
      (let loop ([i 0] [last #t])
        (cond [(= i len) last]
              [(apply pred (%vecrefs i vec vecs)) => (^r (loop (+ i 1) r))]
              [else #f])))))
(define (c128vector-partition pred vec)
  (let1 len (c128vector-length vec)
    (let loop ([i 0] [ins '()] [outs '()])
      (if (= i len)
        (do ([rvec (make-c128vector len)]
             [rs (reverse ins (reverse outs)) (cdr rs)]
             [i 0 (+ i 1)])
            [(= i len) (values rvec (length ins))]
          (c128vector-set! rvec i (car rs)))
        (let1 e (c128vector-ref vec i)
          (if (pred e)
            (loop (+ i 1) (cons e ins) outs)
            (loop (+ i 1) ins (cons e outs))))))))

(define (c128vector-filter pred vec)
  (let1 len (c128vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->c128vector (reverse rs))
        (let1 e (c128vector-ref vec i)
          (loop (+ i 1) (if (pred e) (cons e rs) rs)))))))
(define (c128vector-remove pred vec)
  (let1 len (c128vector-length vec)
    (let loop ([i 0] [rs '()])
      (if (= i len)
        (list->c128vector (reverse rs))
        (let1 e (c128vector-ref vec i)
          (loop (+ i 1) (if (pred e) rs (cons e rs))))))))

;; Mutators

(define-cproc c128vector-swap! (v::<c128vector> i::<fixnum> j::<fixnum>) ::<void>
  (SCM_UVECTOR_CHECK_MUTABLE v)
  (unless (and (<= 0 i) (< i (SCM_C128VECTOR_SIZE v)))
    (Scm_Error "Index i out of bound: %d" i))
  (unless (and (<= 0 j) (< j (SCM_C128VECTOR_SIZE v)))
    (Scm_Error "Index j out of bound: %d" j))
  (let* ([e::(ScmDoubleComplex) (SCM_C128VECTOR_ELEMENT v i)])
    (set! (SCM_C128VECTOR_ELEMENT v i) (SCM_C128VECTOR_ELEMENT v j))
    (set! (SCM_C128VECTOR_ELEMENT v j) e)))

(define-cproc c128vector-reverse!
 (v::<c128vector> :optional (start::<fixnum> 0) (end::<fixnum> -1)) ::<void>
 (SCM_UVECTOR_CHECK_MUTABLE v)
 (let* ([len::ScmSmallInt (SCM_C128VECTOR_SIZE v)])
    (SCM_CHECK_START_END start end len)
    (let* ([i::ScmSmallInt start]
           [j::ScmSmallInt (- end 1)]
           [e::(ScmDoubleComplex)])
      (while (< i j)
        (set! e (SCM_C128VECTOR_ELEMENT v i))
        (set! (SCM_C128VECTOR_ELEMENT v i) (SCM_C128VECTOR_ELEMENT v j))
        (set! (SCM_C128VECTOR_ELEMENT v j) e)
        (pre++ i)
        (pre-- j)))))

(define (c128vector-unfold! f v start end seed)
  (let loop ([i start] [seed seed])
    (when (< i end)
      (receive (e seed) (f seed)
        (c128vector-set! v i e)
        (loop (+ i 1) seed)))))

(define (c128vector-unfold-right! f v start end seed)
  (let loop ([i (- end 1)] [seed seed])
    (when (>= i start)
      (receive (e seed) (f seed)
        (c128vector-set! v i e)
        (loop (- i 1) seed)))))

;; Generators

(define (make-c128vector-generator vec)
  (assume-type vec <c128vector>)
  (uvector->generator vec))

;; Comparator

(define c128vector-comparator
  (make-comparator c128vector? c128vector= 
                   (^[a b] (< (compare a b) 0))
                   default-hash))

;; Output

(define (write-c128vector vec :optional (port (current-output-port)))
  (assume-type vec <c128vector>)
  (write vec port))

;;;
;;; Sequence protocol implementation
;;;

;; call-with-iterator - in gauche.collection

(define-method call-with-builder ((v <c128vector-meta>) proc :key (size #f))
  (if size
    (let ([v (make-c128vector size)] [i 0])
      (proc (^[item] (c128vector-set! v i item) (inc! i))
            (^[] v)))
    (let1 q '()
      (proc (^[item] (push! q item))
            (^[] (reverse-list->c128vector q))))
    ))

(define-method referencer ((v <c128vector>)) c128vector-ref)
(define-method modifier   ((v <c128vector>)) c128vector-set!)
(define-method size-of    ((v <c128vector>)) (c128vector-length v))
(define-method coerce-to  ((c <list-meta>) (v <c128vector>))
  (c128vector->list v))
(define-method coerce-to  ((c <c128vector-meta>) (v <list>))
  (list->c128vector v))
(define-method coerce-to  ((c <vector-meta>) (v <c128vector>))
  (c128vector->vector v))
(define-method coerce-to  ((c <c128vector-meta>) (v <vector>))
  (vector->c128vector v))
(define-method coerce-to  ((c <c128vector-meta>) (v <c128vector>))
  (c128vector-copy v))
(define-method subseq ((v <c128vector>) . args)
  (apply c128vector-copy v args))


(define-cproc s8vector-add (v0::<s8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S8VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc s8vector-add! (v0::<s8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S8VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u8vector-add (v0::<u8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U8VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc u8vector-add! (v0::<u8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U8VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s16vector-add (v0::<s16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S16VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc s16vector-add! (v0::<s16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S16VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u16vector-add (v0::<u16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U16VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc u16vector-add! (v0::<u16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U16VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s32vector-add (v0::<s32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S32VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc s32vector-add! (v0::<s32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S32VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u32vector-add (v0::<u32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U32VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc u32vector-add! (v0::<u32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U32VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s64vector-add (v0::<s64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S64VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc s64vector-add! (v0::<s64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S64VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u64vector-add (v0::<u64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U64VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc u64vector-add! (v0::<u64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U64VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f16vector-add (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc f16vector-add! (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f32vector-add (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc f32vector-add! (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f64vector-add (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc f64vector-add! (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c32vector-add (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc c32vector-add! (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c64vector-add (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc c64vector-add! (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c128vector-add (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorAdd v0 v1 (Scm_ClampMode clamp))))

(define-cproc c128vector-add! (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorAddX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s8vector-sub (v0::<s8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S8VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc s8vector-sub! (v0::<s8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S8VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u8vector-sub (v0::<u8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U8VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc u8vector-sub! (v0::<u8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U8VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s16vector-sub (v0::<s16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S16VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc s16vector-sub! (v0::<s16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S16VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u16vector-sub (v0::<u16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U16VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc u16vector-sub! (v0::<u16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U16VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s32vector-sub (v0::<s32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S32VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc s32vector-sub! (v0::<s32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S32VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u32vector-sub (v0::<u32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U32VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc u32vector-sub! (v0::<u32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U32VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s64vector-sub (v0::<s64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S64VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc s64vector-sub! (v0::<s64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S64VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u64vector-sub (v0::<u64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U64VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc u64vector-sub! (v0::<u64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U64VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f16vector-sub (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc f16vector-sub! (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f32vector-sub (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc f32vector-sub! (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f64vector-sub (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc f64vector-sub! (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c32vector-sub (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc c32vector-sub! (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c64vector-sub (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc c64vector-sub! (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c128vector-sub (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorSub v0 v1 (Scm_ClampMode clamp))))

(define-cproc c128vector-sub! (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorSubX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s8vector-mul (v0::<s8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S8VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc s8vector-mul! (v0::<s8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S8VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u8vector-mul (v0::<u8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U8VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc u8vector-mul! (v0::<u8vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U8VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s16vector-mul (v0::<s16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S16VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc s16vector-mul! (v0::<s16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S16VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u16vector-mul (v0::<u16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U16VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc u16vector-mul! (v0::<u16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U16VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s32vector-mul (v0::<s32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S32VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc s32vector-mul! (v0::<s32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S32VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u32vector-mul (v0::<u32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U32VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc u32vector-mul! (v0::<u32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U32VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s64vector-mul (v0::<s64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S64VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc s64vector-mul! (v0::<s64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_S64VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc u64vector-mul (v0::<u64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U64VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc u64vector-mul! (v0::<u64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_U64VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f16vector-mul (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc f16vector-mul! (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f32vector-mul (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc f32vector-mul! (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f64vector-mul (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc f64vector-mul! (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c32vector-mul (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc c32vector-mul! (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c64vector-mul (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc c64vector-mul! (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c128vector-mul (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorMul v0 v1 (Scm_ClampMode clamp))))

(define-cproc c128vector-mul! (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorMulX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f16vector-div (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorDiv v0 v1 (Scm_ClampMode clamp))))

(define-cproc f16vector-div! (v0::<f16vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F16VectorDivX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f32vector-div (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorDiv v0 v1 (Scm_ClampMode clamp))))

(define-cproc f32vector-div! (v0::<f32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F32VectorDivX v0 v1 (Scm_ClampMode clamp))))
(define-cproc f64vector-div (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorDiv v0 v1 (Scm_ClampMode clamp))))

(define-cproc f64vector-div! (v0::<f64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_F64VectorDivX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c32vector-div (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorDiv v0 v1 (Scm_ClampMode clamp))))

(define-cproc c32vector-div! (v0::<c32vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C32VectorDivX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c64vector-div (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorDiv v0 v1 (Scm_ClampMode clamp))))

(define-cproc c64vector-div! (v0::<c64vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C64VectorDivX v0 v1 (Scm_ClampMode clamp))))
(define-cproc c128vector-div (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorDiv v0 v1 (Scm_ClampMode clamp))))

(define-cproc c128vector-div! (v0::<c128vector> v1 :optional clamp)
  :fast-flonum
  (return (Scm_C128VectorDivX v0 v1 (Scm_ClampMode clamp))))
(define-cproc s8vector-and (v0::<s8vector> v1)
  (return (Scm_S8VectorAnd v0 v1)))

(define-cproc s8vector-and! (v0::<s8vector> v1)
  (return (Scm_S8VectorAndX v0 v1)))
(define-cproc s8vector-ior (v0::<s8vector> v1)
  (return (Scm_S8VectorIor v0 v1)))

(define-cproc s8vector-ior! (v0::<s8vector> v1)
  (return (Scm_S8VectorIorX v0 v1)))
(define-cproc s8vector-xor (v0::<s8vector> v1)
  (return (Scm_S8VectorXor v0 v1)))

(define-cproc s8vector-xor! (v0::<s8vector> v1)
  (return (Scm_S8VectorXorX v0 v1)))
(define-cproc u8vector-and (v0::<u8vector> v1)
  (return (Scm_U8VectorAnd v0 v1)))

(define-cproc u8vector-and! (v0::<u8vector> v1)
  (return (Scm_U8VectorAndX v0 v1)))
(define-cproc u8vector-ior (v0::<u8vector> v1)
  (return (Scm_U8VectorIor v0 v1)))

(define-cproc u8vector-ior! (v0::<u8vector> v1)
  (return (Scm_U8VectorIorX v0 v1)))
(define-cproc u8vector-xor (v0::<u8vector> v1)
  (return (Scm_U8VectorXor v0 v1)))

(define-cproc u8vector-xor! (v0::<u8vector> v1)
  (return (Scm_U8VectorXorX v0 v1)))
(define-cproc s16vector-and (v0::<s16vector> v1)
  (return (Scm_S16VectorAnd v0 v1)))

(define-cproc s16vector-and! (v0::<s16vector> v1)
  (return (Scm_S16VectorAndX v0 v1)))
(define-cproc s16vector-ior (v0::<s16vector> v1)
  (return (Scm_S16VectorIor v0 v1)))

(define-cproc s16vector-ior! (v0::<s16vector> v1)
  (return (Scm_S16VectorIorX v0 v1)))
(define-cproc s16vector-xor (v0::<s16vector> v1)
  (return (Scm_S16VectorXor v0 v1)))

(define-cproc s16vector-xor! (v0::<s16vector> v1)
  (return (Scm_S16VectorXorX v0 v1)))
(define-cproc u16vector-and (v0::<u16vector> v1)
  (return (Scm_U16VectorAnd v0 v1)))

(define-cproc u16vector-and! (v0::<u16vector> v1)
  (return (Scm_U16VectorAndX v0 v1)))
(define-cproc u16vector-ior (v0::<u16vector> v1)
  (return (Scm_U16VectorIor v0 v1)))

(define-cproc u16vector-ior! (v0::<u16vector> v1)
  (return (Scm_U16VectorIorX v0 v1)))
(define-cproc u16vector-xor (v0::<u16vector> v1)
  (return (Scm_U16VectorXor v0 v1)))

(define-cproc u16vector-xor! (v0::<u16vector> v1)
  (return (Scm_U16VectorXorX v0 v1)))
(define-cproc s32vector-and (v0::<s32vector> v1)
  (return (Scm_S32VectorAnd v0 v1)))

(define-cproc s32vector-and! (v0::<s32vector> v1)
  (return (Scm_S32VectorAndX v0 v1)))
(define-cproc s32vector-ior (v0::<s32vector> v1)
  (return (Scm_S32VectorIor v0 v1)))

(define-cproc s32vector-ior! (v0::<s32vector> v1)
  (return (Scm_S32VectorIorX v0 v1)))
(define-cproc s32vector-xor (v0::<s32vector> v1)
  (return (Scm_S32VectorXor v0 v1)))

(define-cproc s32vector-xor! (v0::<s32vector> v1)
  (return (Scm_S32VectorXorX v0 v1)))
(define-cproc u32vector-and (v0::<u32vector> v1)
  (return (Scm_U32VectorAnd v0 v1)))

(define-cproc u32vector-and! (v0::<u32vector> v1)
  (return (Scm_U32VectorAndX v0 v1)))
(define-cproc u32vector-ior (v0::<u32vector> v1)
  (return (Scm_U32VectorIor v0 v1)))

(define-cproc u32vector-ior! (v0::<u32vector> v1)
  (return (Scm_U32VectorIorX v0 v1)))
(define-cproc u32vector-xor (v0::<u32vector> v1)
  (return (Scm_U32VectorXor v0 v1)))

(define-cproc u32vector-xor! (v0::<u32vector> v1)
  (return (Scm_U32VectorXorX v0 v1)))
(define-cproc s64vector-and (v0::<s64vector> v1)
  (return (Scm_S64VectorAnd v0 v1)))

(define-cproc s64vector-and! (v0::<s64vector> v1)
  (return (Scm_S64VectorAndX v0 v1)))
(define-cproc s64vector-ior (v0::<s64vector> v1)
  (return (Scm_S64VectorIor v0 v1)))

(define-cproc s64vector-ior! (v0::<s64vector> v1)
  (return (Scm_S64VectorIorX v0 v1)))
(define-cproc s64vector-xor (v0::<s64vector> v1)
  (return (Scm_S64VectorXor v0 v1)))

(define-cproc s64vector-xor! (v0::<s64vector> v1)
  (return (Scm_S64VectorXorX v0 v1)))
(define-cproc u64vector-and (v0::<u64vector> v1)
  (return (Scm_U64VectorAnd v0 v1)))

(define-cproc u64vector-and! (v0::<u64vector> v1)
  (return (Scm_U64VectorAndX v0 v1)))
(define-cproc u64vector-ior (v0::<u64vector> v1)
  (return (Scm_U64VectorIor v0 v1)))

(define-cproc u64vector-ior! (v0::<u64vector> v1)
  (return (Scm_U64VectorIorX v0 v1)))
(define-cproc u64vector-xor (v0::<u64vector> v1)
  (return (Scm_U64VectorXor v0 v1)))

(define-cproc u64vector-xor! (v0::<u64vector> v1)
  (return (Scm_U64VectorXorX v0 v1)))
(define-cproc s8vector-dot (v0::<s8vector> v1) Scm_VMS8VectorDotProd)
(define-cproc u8vector-dot (v0::<u8vector> v1) Scm_VMU8VectorDotProd)
(define-cproc s16vector-dot (v0::<s16vector> v1) Scm_VMS16VectorDotProd)
(define-cproc u16vector-dot (v0::<u16vector> v1) Scm_VMU16VectorDotProd)
(define-cproc s32vector-dot (v0::<s32vector> v1) Scm_VMS32VectorDotProd)
(define-cproc u32vector-dot (v0::<u32vector> v1) Scm_VMU32VectorDotProd)
(define-cproc s64vector-dot (v0::<s64vector> v1) Scm_VMS64VectorDotProd)
(define-cproc u64vector-dot (v0::<u64vector> v1) Scm_VMU64VectorDotProd)
(define-cproc f16vector-dot (v0::<f16vector> v1) Scm_VMF16VectorDotProd)
(define-cproc f32vector-dot (v0::<f32vector> v1) Scm_VMF32VectorDotProd)
(define-cproc f64vector-dot (v0::<f64vector> v1) Scm_VMF64VectorDotProd)
(define-cproc c32vector-dot (v0::<c32vector> v1) Scm_VMC32VectorDotProd)
(define-cproc c64vector-dot (v0::<c64vector> v1) Scm_VMC64VectorDotProd)
(define-cproc c128vector-dot (v0::<c128vector> v1) Scm_VMC128VectorDotProd)
(define-cproc s8vector-range-check (v0::<s8vector> min max)
  Scm_S8VectorRangeCheck)
(define-cproc s8vector-clamp (v0::<s8vector> min max)
  Scm_S8VectorClamp)
(define-cproc s8vector-clamp! (v0::<s8vector> min max)
  Scm_S8VectorClampX)
(define-cproc u8vector-range-check (v0::<u8vector> min max)
  Scm_U8VectorRangeCheck)
(define-cproc u8vector-clamp (v0::<u8vector> min max)
  Scm_U8VectorClamp)
(define-cproc u8vector-clamp! (v0::<u8vector> min max)
  Scm_U8VectorClampX)
(define-cproc s16vector-range-check (v0::<s16vector> min max)
  Scm_S16VectorRangeCheck)
(define-cproc s16vector-clamp (v0::<s16vector> min max)
  Scm_S16VectorClamp)
(define-cproc s16vector-clamp! (v0::<s16vector> min max)
  Scm_S16VectorClampX)
(define-cproc u16vector-range-check (v0::<u16vector> min max)
  Scm_U16VectorRangeCheck)
(define-cproc u16vector-clamp (v0::<u16vector> min max)
  Scm_U16VectorClamp)
(define-cproc u16vector-clamp! (v0::<u16vector> min max)
  Scm_U16VectorClampX)
(define-cproc s32vector-range-check (v0::<s32vector> min max)
  Scm_S32VectorRangeCheck)
(define-cproc s32vector-clamp (v0::<s32vector> min max)
  Scm_S32VectorClamp)
(define-cproc s32vector-clamp! (v0::<s32vector> min max)
  Scm_S32VectorClampX)
(define-cproc u32vector-range-check (v0::<u32vector> min max)
  Scm_U32VectorRangeCheck)
(define-cproc u32vector-clamp (v0::<u32vector> min max)
  Scm_U32VectorClamp)
(define-cproc u32vector-clamp! (v0::<u32vector> min max)
  Scm_U32VectorClampX)
(define-cproc s64vector-range-check (v0::<s64vector> min max)
  Scm_S64VectorRangeCheck)
(define-cproc s64vector-clamp (v0::<s64vector> min max)
  Scm_S64VectorClamp)
(define-cproc s64vector-clamp! (v0::<s64vector> min max)
  Scm_S64VectorClampX)
(define-cproc u64vector-range-check (v0::<u64vector> min max)
  Scm_U64VectorRangeCheck)
(define-cproc u64vector-clamp (v0::<u64vector> min max)
  Scm_U64VectorClamp)
(define-cproc u64vector-clamp! (v0::<u64vector> min max)
  Scm_U64VectorClampX)
(define-cproc f16vector-range-check (v0::<f16vector> min max)
  Scm_F16VectorRangeCheck)
(define-cproc f16vector-clamp (v0::<f16vector> min max)
  Scm_F16VectorClamp)
(define-cproc f16vector-clamp! (v0::<f16vector> min max)
  Scm_F16VectorClampX)
(define-cproc f32vector-range-check (v0::<f32vector> min max)
  Scm_F32VectorRangeCheck)
(define-cproc f32vector-clamp (v0::<f32vector> min max)
  Scm_F32VectorClamp)
(define-cproc f32vector-clamp! (v0::<f32vector> min max)
  Scm_F32VectorClampX)
(define-cproc f64vector-range-check (v0::<f64vector> min max)
  Scm_F64VectorRangeCheck)
(define-cproc f64vector-clamp (v0::<f64vector> min max)
  Scm_F64VectorClamp)
(define-cproc f64vector-clamp! (v0::<f64vector> min max)
  Scm_F64VectorClampX)
(define-cproc s16vector-swap-bytes (v0::<s16vector>) Scm_S16VectorSwapBytes)
(define-cproc s16vector-swap-bytes!(v0::<s16vector>) Scm_S16VectorSwapBytesX)
(define-cproc u16vector-swap-bytes (v0::<u16vector>) Scm_U16VectorSwapBytes)
(define-cproc u16vector-swap-bytes!(v0::<u16vector>) Scm_U16VectorSwapBytesX)
(define-cproc s32vector-swap-bytes (v0::<s32vector>) Scm_S32VectorSwapBytes)
(define-cproc s32vector-swap-bytes!(v0::<s32vector>) Scm_S32VectorSwapBytesX)
(define-cproc u32vector-swap-bytes (v0::<u32vector>) Scm_U32VectorSwapBytes)
(define-cproc u32vector-swap-bytes!(v0::<u32vector>) Scm_U32VectorSwapBytesX)
(define-cproc s64vector-swap-bytes (v0::<s64vector>) Scm_S64VectorSwapBytes)
(define-cproc s64vector-swap-bytes!(v0::<s64vector>) Scm_S64VectorSwapBytesX)
(define-cproc u64vector-swap-bytes (v0::<u64vector>) Scm_U64VectorSwapBytes)
(define-cproc u64vector-swap-bytes!(v0::<u64vector>) Scm_U64VectorSwapBytesX)
(define-cproc f16vector-swap-bytes (v0::<f16vector>) Scm_F16VectorSwapBytes)
(define-cproc f16vector-swap-bytes!(v0::<f16vector>) Scm_F16VectorSwapBytesX)
(define-cproc f32vector-swap-bytes (v0::<f32vector>) Scm_F32VectorSwapBytes)
(define-cproc f32vector-swap-bytes!(v0::<f32vector>) Scm_F32VectorSwapBytesX)
(define-cproc f64vector-swap-bytes (v0::<f64vector>) Scm_F64VectorSwapBytes)
(define-cproc f64vector-swap-bytes!(v0::<f64vector>) Scm_F64VectorSwapBytesX)
