;; Uniform vectors, as specified by SRFI-4.

(require kawa.lib.prim_imports)
(require kawa.lib.std_syntax)
(require kawa.lib.lists)
(require kawa.lib.syntax)

(export 
 f32vector f32vector? f32vector-length
 f32vector-ref f32vector-set! f32vector->list
 f64vector f64vector? f64vector-length
 f64vector-ref f64vector-set! f64vector->list
 list->f32vector list->f64vector
 list->s8vector list->s16vector list->s32vector list->s64vector
 list->u8vector list->u16vector list->u32vector list->u64vector
 make-f32vector make-f64vector
 make-s8vector make-s16vector make-s32vector make-s64vector
 make-u8vector make-u16vector make-u32vector make-u64vector
 s8vector s8vector? s8vector-length
 s8vector-ref s8vector-set! s8vector->list
 s16vector s16vector? s16vector-length
 s16vector-ref s16vector-set! s16vector->list
 s32vector s32vector? s32vector-length
 s32vector-ref s32vector-set! s32vector->list
 s64vector s64vector? s64vector-length
 s64vector-ref s64vector-set! s64vector->list
 u8vector u8vector? u8vector-length
 u8vector-ref u8vector-set! u8vector->list
 u16vector u16vector? u16vector-length
 u16vector-ref u16vector-set! u16vector->list
 u32vector u32vector? u32vector-length
 u32vector-ref u32vector-set! u32vector->list
 u64vector u64vector? u64vector-length
 u64vector-ref u64vector-set! u64vector->list)

(define (s8vector? x) :: <boolean>
  (instance? x <s8vector>))

(define (make-s8vector (n :: <int>) #!optional (init :: <int> 0)) :: <s8vector>
  (make <s8vector> n init))

(define (s8vector-length (v :: <s8vector>)) :: <int>
  (invoke v 'size))

(define (s8vector-ref (v :: <s8vector>) (i :: <int>)) :: byte
  (v:getByte i))

(define (s8vector-set! (v :: <s8vector>) (i :: <int>) (x ::byte)) :: <void>
  (v:setByte i x))

(define (s8vector->list (v :: <s8vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define-syntax %list->array
  (syntax-rules ()
    ((_ lst el-type arr-el-type)
     (let* ((n (length lst))
            (arr (arr-el-type[] length: n))
            (i ::int 0))
       (for-each (lambda (x)
                   (set! (arr i) (let ((v :: el-type x)) v))
                   (set! i (+ i 1)))
                 lst)
       arr))))

(define (list->s8vector (l :: <list>)) :: <s8vector>
  (make <s8vector> (%list->array l byte byte)))

(define (u8vector? x) :: <boolean>
  (instance? x <u8vector>))

(define (make-u8vector (n :: <int>) #!optional (init :: <int> 0)) :: <u8vector>
  (make <u8vector> n init))

(define (u8vector-length (v :: <u8vector>)) :: <int>
  (invoke v 'size))

(define (u8vector-ref (v :: <u8vector>) (i :: <int>)) :: ubyte
  (v:getByte i))

(define (u8vector-set! v::<u8vector> i::int x::ubyte) :: <void>
  (v:setByte i x))

(define (u8vector->list (v :: <u8vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->u8vector (l :: <list>)) :: <u8vector>
  (make <u8vector> (%list->array l ubyte byte)))

(define (s16vector? x) :: <boolean>
  (instance? x <s16vector>))

(define (make-s16vector (n :: <int>) #!optional (init :: <int> 0)) :: <s16vector>
  (make <s16vector> n init))

(define (s16vector-length (v :: <s16vector>)) :: <int>
  (invoke v 'size))

(define (s16vector-ref (v :: <s16vector>) (i :: <int>)) ::short
  (v:getShort i))

(define (s16vector-set! (v :: <s16vector>) (i :: <int>) (x ::short)) :: <void>
  (v:setShort i x))

(define (s16vector->list (v :: <s16vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->s16vector (l :: <list>)) :: <s16vector>
  (make <s16vector> (%list->array l short short)))

(define (u16vector? x) :: <boolean>
  (instance? x <u16vector>))

(define (make-u16vector (n :: <int>) #!optional (init :: <int> 0)) :: <u16vector>
  (make <u16vector> n init))

(define (u16vector-length (v :: <u16vector>)) :: <int>
  (invoke v 'size))

(define (u16vector-ref (v :: <u16vector>) (i :: <int>)) ::ushort
  (v:getShort i))

(define (u16vector-set! (v :: <u16vector>) (i :: <int>) (x ::ushort)) :: <void>
  (v:setShort i x))

(define (u16vector->list (v :: <u16vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->u16vector (l :: <list>)) :: <u16vector>
  (make <u16vector> (%list->array l ushort short)))

(define (s32vector? x) :: <boolean>
  (instance? x <s32vector>))

(define (make-s32vector (n :: <int>) #!optional (init :: <int> 0)) :: <s32vector>
  (make <s32vector> n init))

(define (s32vector-length (v :: <s32vector>)) :: <int>
  (invoke v 'size))

(define (s32vector-ref (v :: <s32vector>) (i :: <int>)) ::int
  (v:getInt i))

(define (s32vector-set! (v :: <s32vector>) (i :: <int>) (x :: <int>)) :: <void>
  (v:setInt i x))

(define (s32vector->list (v :: <s32vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->s32vector (l :: <list>)) :: <s32vector>
  (make <s32vector> (%list->array l int int)))

(define (u32vector? x) :: <boolean>
  (instance? x <u32vector>))

(define (make-u32vector (n :: <int>) #!optional (init :: <long> 0)) :: <u32vector>
  (make <u32vector> n init))

(define (u32vector-length (v :: <u32vector>)) :: <int>
  (invoke v 'size))

(define (u32vector-ref (v :: <u32vector>) (i :: <int>)) ::uint
  (v:getInt i))

(define (u32vector-set! (v :: <u32vector>) (i :: <int>) (x ::uint)) ::void
  (v:setInt i x))

(define (u32vector->list (v :: <u32vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->u32vector (l :: <list>)) :: <u32vector>
  (make <u32vector> (%list->array l uint int)))

(define (s64vector? x) :: <boolean>
  (instance? x <s64vector>))

(define (make-s64vector (n :: <int>) #!optional (init :: <long> 0)) :: <s64vector>
  (make <s64vector> n init))

(define (s64vector-length (v :: <s64vector>)) :: <int>
  (invoke v 'size))

(define (s64vector-ref (v :: <s64vector>) (i :: <int>)) ::long
  (v:getLong i))

(define (s64vector-set! (v :: <s64vector>) (i :: <int>) (x :: <long>)) :: <void>
  (v:setLong i x))

(define (s64vector->list (v :: <s64vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->s64vector (l :: <list>)) :: <s64vector>
  (make <s64vector> (%list->array l long long)))

(define (u64vector? x) :: <boolean>
  (instance? x <u64vector>))

(define (make-u64vector (n :: <int>) #!optional (init :: <integer> 0)) :: <u64vector>
  (make <u64vector> n init))

(define (u64vector-length (v :: <u64vector>)) :: <int>
  (invoke v 'size))

(define (u64vector-ref (v :: <u64vector>) (i :: <int>)) ::ulong
  (v:getLong i))

(define (u64vector-set! (v :: <u64vector>) (i :: <int>) (x ::ulong)) ::void
  (v:setLong i x))

(define (u64vector->list (v :: <u64vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->u64vector (l :: <list>)) :: <u64vector>
  (make <u64vector> (%list->array l ulong long)))

(define (f32vector? x) :: <boolean>
  (instance? x <f32vector>))

(define (make-f32vector (n :: <int>) #!optional (init :: <float> 0.0)) :: <f32vector>
  (make <f32vector> n init))

(define (f32vector-length (v :: <f32vector>)) :: <int>
  (invoke v 'size))

(define (f32vector-ref (v :: <f32vector>) (i :: <int>)) :: <float>
  (v:getFloat i))

(define (f32vector-set! (v :: <f32vector>) (i :: <int>) (x :: <float>)) :: <void>
  (v:setFloat i x))

(define (f32vector->list (v :: <f32vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->f32vector (l :: <list>)) :: <f32vector>
  (make <f32vector> (%list->array l float float)))

(define (f64vector? x) :: <boolean>
  (instance? x <f64vector>))

(define (make-f64vector (n :: <int>) #!optional (init :: <double> 0.0)) :: <f64vector>
  (make <f64vector> n init))

(define (f64vector-length (v :: <f64vector>)) :: <int>
  (invoke v 'size))

(define (f64vector-ref (v :: <f64vector>) (i :: <int>)) :: <double>
  (v:getDouble i))

(define (f64vector-set! (v :: <f64vector>) (i :: <int>) (x :: <double>)) :: <void>
  (v:setDouble i x))

(define (f64vector->list (v :: <f64vector>)) :: <list>
  (invoke-static <list> 'makeList v))

(define (list->f64vector (l :: <list>)) :: <f64vector>
  (make <f64vector> (%list->array l double double)))

#| Defined in LangObjType
(define (s8vector . values) :: <s8vector>
  (list->s8vector values))

(define (u8vector . values) :: <u8vector>
  (list->u8vector values))

(define (s16vector . values) :: <s16vector>
  (list->s16vector values))

(define (u16vector . values) :: <u16vector>
  (list->u16vector values))

(define (s32vector . values) :: <s32vector>
  (list->s32vector values))

(define (u32vector . values) :: <u32vector>
  (list->u32vector values))

(define (s64vector . values) :: <s64vector>
  (list->s64vector values))

(define (u64vector . values) :: <u64vector>
  (list->u64vector values))

(define (f32vector . values) :: <f32vector>
  (list->f32vector values))

(define (f64vector . values) :: <f64vector>
  (list->f64vector values))
|#
