/*
 * uvector - uniform (homogeneous) numeric vector types (SRFI-4)
 *
 *   Copyright (c) 1999-2004 Shiro Kawai, All rights reserved.
 * 
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 * 
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 *   3. Neither the name of the authors nor the names of its contributors
 *      may be used to endorse or promote products derived from this
 *      software without specific prior written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 *   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  This file is automatically generated.  DO NOT EDIT.
 *  $Id: uvector.h.tmpl,v 1.3 2004/11/11 12:14:43 shirok Exp $
 */

#ifndef GAUCHE_UVECT_H
#define GAUCHE_UVECT_H

#include <gauche.h>

/*
 * This header file is for other extension modules which need
 * to access uniform vectors in C level.
 */

/*
 * Common structure for generic uvector operation
 */
typedef struct ScmUVectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    void *elements;
} ScmUVector;

SCM_CLASS_DECL(Scm_UVectorClass);
#define SCM_CLASS_UVECTOR         (&Scm_UVectorClass)
#define SCM_UVECTOR(obj)          ((ScmUVector*)(obj))
#define SCM_UVECTORP(obj)         Scm_TypeP(obj, SCM_CLASS_UVECTOR)
#define SCM_UVECTOR_SIZE(obj)     (SCM_UVECTOR(obj)->size)
#define SCM_UVECTOR_IMMUTABLE_P(obj) (SCM_UVECTOR(obj)->immutable)
#define SCM_UVECTOR_OWNER(obj)    (SCM_UVECTOR(obj)->owner)
#define SCM_UVECTOR_ELEMENTS(obj) (SCM_UVECTOR(obj)->elements)

#define SCM_UVECTOR_CHECK_MUTABLE(obj)                 \
  do { if (SCM_UVECTOR_IMMUTABLE_P(obj)) {             \
    Scm_Error("uniform vector is immutable: %S", obj); \
  }} while (0)

extern int Scm_UVectorElementSize(ScmClass *klass);
extern ScmObj Scm_MakeUVector(ScmClass *klass, int size, void *init);
extern ScmObj Scm_MakeUVectorFull(ScmClass *klass, int size, void *init,
                                  int immutablep, void *owner);

extern ScmObj Scm_UVectorAlias(ScmClass *klass, ScmUVector *v,
                               int start, int end);

extern ScmObj Scm_UVectorCopy(ScmUVector *v, int start, int end);
extern ScmObj Scm_UVectorSwapBytes(ScmUVector *v);
extern ScmObj Scm_UVectorSwapBytesX(ScmUVector *v);

extern ScmObj Scm_ReadBlockX(ScmUVector *v, ScmPort *port,
                             int start, int end, ScmObj endian);
extern ScmObj Scm_WriteBlock(ScmUVector *v, ScmPort *port,
                             int start, int end, ScmObj endian);

/* S8Vector */

typedef struct ScmS8VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    signed char *elements;
} ScmS8Vector;

SCM_CLASS_DECL(Scm_S8VectorClass);
#define SCM_CLASS_S8VECTOR  (&Scm_S8VectorClass)

#define SCM_S8VECTOR(obj)        ((ScmS8Vector*)(obj))
#define SCM_S8VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_S8VECTOR)
#define SCM_S8VECTOR_SIZE(obj)   (SCM_S8VECTOR(obj)->size)
#define SCM_S8VECTOR_ELEMENTS(obj) (SCM_S8VECTOR(obj)->elements)

extern ScmObj Scm_MakeS8Vector(int size, signed char fill);
extern ScmObj Scm_MakeS8VectorFromArray(int size, const signed char array[]);
extern ScmObj Scm_MakeS8VectorFromArrayShared(int size, signed char array[]);
extern ScmObj Scm_S8VectorFill(ScmS8Vector *vec, signed char fill, int, int);
extern ScmObj Scm_S8VectorRef(ScmS8Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_S8VectorSet(ScmS8Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_S8VectorToList(ScmS8Vector *vec, int start, int end);
extern ScmObj Scm_ListToS8Vector(ScmObj list, int clamp);
extern ScmObj Scm_S8VectorCopy(ScmS8Vector *vec, int start, int end);
extern ScmObj Scm_S8VectorCopyX(ScmS8Vector *dst, int dstart,
                                  ScmS8Vector *src, int sstart, int send);
extern ScmObj Scm_S8VectorToVector(ScmS8Vector *vec, int start, int end);
extern ScmObj Scm_VectorToS8Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_S8VectorAdd(ScmS8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S8VectorAddX(ScmS8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S8VectorSub(ScmS8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S8VectorSubX(ScmS8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S8VectorMul(ScmS8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S8VectorMulX(ScmS8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S8VectorDiv(ScmS8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S8VectorDivX(ScmS8Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_S8VectorAnd(ScmS8Vector *s0, ScmObj s1);
extern ScmObj Scm_S8VectorAndX(ScmS8Vector *s0, ScmObj s1);
extern ScmObj Scm_S8VectorIor(ScmS8Vector *s0, ScmObj s1);
extern ScmObj Scm_S8VectorIorX(ScmS8Vector *s0, ScmObj s1);
extern ScmObj Scm_S8VectorXor(ScmS8Vector *s0, ScmObj s1);
extern ScmObj Scm_S8VectorXorX(ScmS8Vector *s0, ScmObj s1);

extern ScmObj Scm_S8VectorDotProd(ScmS8Vector *v0, ScmObj v1);
extern ScmObj Scm_S8VectorRangeCheck(ScmS8Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S8VectorClamp(ScmS8Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S8VectorClampX(ScmS8Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_S8VectorSwapBytes(ScmS8Vector *v0);
extern ScmObj Scm_S8VectorSwapBytesX(ScmS8Vector *v0);

/* U8Vector */

typedef struct ScmU8VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    unsigned char *elements;
} ScmU8Vector;

SCM_CLASS_DECL(Scm_U8VectorClass);
#define SCM_CLASS_U8VECTOR  (&Scm_U8VectorClass)

#define SCM_U8VECTOR(obj)        ((ScmU8Vector*)(obj))
#define SCM_U8VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_U8VECTOR)
#define SCM_U8VECTOR_SIZE(obj)   (SCM_U8VECTOR(obj)->size)
#define SCM_U8VECTOR_ELEMENTS(obj) (SCM_U8VECTOR(obj)->elements)

extern ScmObj Scm_MakeU8Vector(int size, unsigned char fill);
extern ScmObj Scm_MakeU8VectorFromArray(int size, const unsigned char array[]);
extern ScmObj Scm_MakeU8VectorFromArrayShared(int size, unsigned char array[]);
extern ScmObj Scm_U8VectorFill(ScmU8Vector *vec, unsigned char fill, int, int);
extern ScmObj Scm_U8VectorRef(ScmU8Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_U8VectorSet(ScmU8Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_U8VectorToList(ScmU8Vector *vec, int start, int end);
extern ScmObj Scm_ListToU8Vector(ScmObj list, int clamp);
extern ScmObj Scm_U8VectorCopy(ScmU8Vector *vec, int start, int end);
extern ScmObj Scm_U8VectorCopyX(ScmU8Vector *dst, int dstart,
                                  ScmU8Vector *src, int sstart, int send);
extern ScmObj Scm_U8VectorToVector(ScmU8Vector *vec, int start, int end);
extern ScmObj Scm_VectorToU8Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_U8VectorAdd(ScmU8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U8VectorAddX(ScmU8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U8VectorSub(ScmU8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U8VectorSubX(ScmU8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U8VectorMul(ScmU8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U8VectorMulX(ScmU8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U8VectorDiv(ScmU8Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U8VectorDivX(ScmU8Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_U8VectorAnd(ScmU8Vector *s0, ScmObj s1);
extern ScmObj Scm_U8VectorAndX(ScmU8Vector *s0, ScmObj s1);
extern ScmObj Scm_U8VectorIor(ScmU8Vector *s0, ScmObj s1);
extern ScmObj Scm_U8VectorIorX(ScmU8Vector *s0, ScmObj s1);
extern ScmObj Scm_U8VectorXor(ScmU8Vector *s0, ScmObj s1);
extern ScmObj Scm_U8VectorXorX(ScmU8Vector *s0, ScmObj s1);

extern ScmObj Scm_U8VectorDotProd(ScmU8Vector *v0, ScmObj v1);
extern ScmObj Scm_U8VectorRangeCheck(ScmU8Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U8VectorClamp(ScmU8Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U8VectorClampX(ScmU8Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_U8VectorSwapBytes(ScmU8Vector *v0);
extern ScmObj Scm_U8VectorSwapBytesX(ScmU8Vector *v0);

/* S16Vector */

typedef struct ScmS16VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    short *elements;
} ScmS16Vector;

SCM_CLASS_DECL(Scm_S16VectorClass);
#define SCM_CLASS_S16VECTOR  (&Scm_S16VectorClass)

#define SCM_S16VECTOR(obj)        ((ScmS16Vector*)(obj))
#define SCM_S16VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_S16VECTOR)
#define SCM_S16VECTOR_SIZE(obj)   (SCM_S16VECTOR(obj)->size)
#define SCM_S16VECTOR_ELEMENTS(obj) (SCM_S16VECTOR(obj)->elements)

extern ScmObj Scm_MakeS16Vector(int size, short fill);
extern ScmObj Scm_MakeS16VectorFromArray(int size, const short array[]);
extern ScmObj Scm_MakeS16VectorFromArrayShared(int size, short array[]);
extern ScmObj Scm_S16VectorFill(ScmS16Vector *vec, short fill, int, int);
extern ScmObj Scm_S16VectorRef(ScmS16Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_S16VectorSet(ScmS16Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_S16VectorToList(ScmS16Vector *vec, int start, int end);
extern ScmObj Scm_ListToS16Vector(ScmObj list, int clamp);
extern ScmObj Scm_S16VectorCopy(ScmS16Vector *vec, int start, int end);
extern ScmObj Scm_S16VectorCopyX(ScmS16Vector *dst, int dstart,
                                  ScmS16Vector *src, int sstart, int send);
extern ScmObj Scm_S16VectorToVector(ScmS16Vector *vec, int start, int end);
extern ScmObj Scm_VectorToS16Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_S16VectorAdd(ScmS16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S16VectorAddX(ScmS16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S16VectorSub(ScmS16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S16VectorSubX(ScmS16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S16VectorMul(ScmS16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S16VectorMulX(ScmS16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S16VectorDiv(ScmS16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S16VectorDivX(ScmS16Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_S16VectorAnd(ScmS16Vector *s0, ScmObj s1);
extern ScmObj Scm_S16VectorAndX(ScmS16Vector *s0, ScmObj s1);
extern ScmObj Scm_S16VectorIor(ScmS16Vector *s0, ScmObj s1);
extern ScmObj Scm_S16VectorIorX(ScmS16Vector *s0, ScmObj s1);
extern ScmObj Scm_S16VectorXor(ScmS16Vector *s0, ScmObj s1);
extern ScmObj Scm_S16VectorXorX(ScmS16Vector *s0, ScmObj s1);

extern ScmObj Scm_S16VectorDotProd(ScmS16Vector *v0, ScmObj v1);
extern ScmObj Scm_S16VectorRangeCheck(ScmS16Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S16VectorClamp(ScmS16Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S16VectorClampX(ScmS16Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_S16VectorSwapBytes(ScmS16Vector *v0);
extern ScmObj Scm_S16VectorSwapBytesX(ScmS16Vector *v0);

/* U16Vector */

typedef struct ScmU16VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    unsigned short *elements;
} ScmU16Vector;

SCM_CLASS_DECL(Scm_U16VectorClass);
#define SCM_CLASS_U16VECTOR  (&Scm_U16VectorClass)

#define SCM_U16VECTOR(obj)        ((ScmU16Vector*)(obj))
#define SCM_U16VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_U16VECTOR)
#define SCM_U16VECTOR_SIZE(obj)   (SCM_U16VECTOR(obj)->size)
#define SCM_U16VECTOR_ELEMENTS(obj) (SCM_U16VECTOR(obj)->elements)

extern ScmObj Scm_MakeU16Vector(int size, unsigned short fill);
extern ScmObj Scm_MakeU16VectorFromArray(int size, const unsigned short array[]);
extern ScmObj Scm_MakeU16VectorFromArrayShared(int size, unsigned short array[]);
extern ScmObj Scm_U16VectorFill(ScmU16Vector *vec, unsigned short fill, int, int);
extern ScmObj Scm_U16VectorRef(ScmU16Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_U16VectorSet(ScmU16Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_U16VectorToList(ScmU16Vector *vec, int start, int end);
extern ScmObj Scm_ListToU16Vector(ScmObj list, int clamp);
extern ScmObj Scm_U16VectorCopy(ScmU16Vector *vec, int start, int end);
extern ScmObj Scm_U16VectorCopyX(ScmU16Vector *dst, int dstart,
                                  ScmU16Vector *src, int sstart, int send);
extern ScmObj Scm_U16VectorToVector(ScmU16Vector *vec, int start, int end);
extern ScmObj Scm_VectorToU16Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_U16VectorAdd(ScmU16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U16VectorAddX(ScmU16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U16VectorSub(ScmU16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U16VectorSubX(ScmU16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U16VectorMul(ScmU16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U16VectorMulX(ScmU16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U16VectorDiv(ScmU16Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U16VectorDivX(ScmU16Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_U16VectorAnd(ScmU16Vector *s0, ScmObj s1);
extern ScmObj Scm_U16VectorAndX(ScmU16Vector *s0, ScmObj s1);
extern ScmObj Scm_U16VectorIor(ScmU16Vector *s0, ScmObj s1);
extern ScmObj Scm_U16VectorIorX(ScmU16Vector *s0, ScmObj s1);
extern ScmObj Scm_U16VectorXor(ScmU16Vector *s0, ScmObj s1);
extern ScmObj Scm_U16VectorXorX(ScmU16Vector *s0, ScmObj s1);

extern ScmObj Scm_U16VectorDotProd(ScmU16Vector *v0, ScmObj v1);
extern ScmObj Scm_U16VectorRangeCheck(ScmU16Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U16VectorClamp(ScmU16Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U16VectorClampX(ScmU16Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_U16VectorSwapBytes(ScmU16Vector *v0);
extern ScmObj Scm_U16VectorSwapBytesX(ScmU16Vector *v0);

/* S32Vector */

typedef struct ScmS32VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    ScmInt32 *elements;
} ScmS32Vector;

SCM_CLASS_DECL(Scm_S32VectorClass);
#define SCM_CLASS_S32VECTOR  (&Scm_S32VectorClass)

#define SCM_S32VECTOR(obj)        ((ScmS32Vector*)(obj))
#define SCM_S32VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_S32VECTOR)
#define SCM_S32VECTOR_SIZE(obj)   (SCM_S32VECTOR(obj)->size)
#define SCM_S32VECTOR_ELEMENTS(obj) (SCM_S32VECTOR(obj)->elements)

extern ScmObj Scm_MakeS32Vector(int size, ScmInt32 fill);
extern ScmObj Scm_MakeS32VectorFromArray(int size, const ScmInt32 array[]);
extern ScmObj Scm_MakeS32VectorFromArrayShared(int size, ScmInt32 array[]);
extern ScmObj Scm_S32VectorFill(ScmS32Vector *vec, ScmInt32 fill, int, int);
extern ScmObj Scm_S32VectorRef(ScmS32Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_S32VectorSet(ScmS32Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_S32VectorToList(ScmS32Vector *vec, int start, int end);
extern ScmObj Scm_ListToS32Vector(ScmObj list, int clamp);
extern ScmObj Scm_S32VectorCopy(ScmS32Vector *vec, int start, int end);
extern ScmObj Scm_S32VectorCopyX(ScmS32Vector *dst, int dstart,
                                  ScmS32Vector *src, int sstart, int send);
extern ScmObj Scm_S32VectorToVector(ScmS32Vector *vec, int start, int end);
extern ScmObj Scm_VectorToS32Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_S32VectorAdd(ScmS32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S32VectorAddX(ScmS32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S32VectorSub(ScmS32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S32VectorSubX(ScmS32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S32VectorMul(ScmS32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S32VectorMulX(ScmS32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S32VectorDiv(ScmS32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S32VectorDivX(ScmS32Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_S32VectorAnd(ScmS32Vector *s0, ScmObj s1);
extern ScmObj Scm_S32VectorAndX(ScmS32Vector *s0, ScmObj s1);
extern ScmObj Scm_S32VectorIor(ScmS32Vector *s0, ScmObj s1);
extern ScmObj Scm_S32VectorIorX(ScmS32Vector *s0, ScmObj s1);
extern ScmObj Scm_S32VectorXor(ScmS32Vector *s0, ScmObj s1);
extern ScmObj Scm_S32VectorXorX(ScmS32Vector *s0, ScmObj s1);

extern ScmObj Scm_S32VectorDotProd(ScmS32Vector *v0, ScmObj v1);
extern ScmObj Scm_S32VectorRangeCheck(ScmS32Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S32VectorClamp(ScmS32Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S32VectorClampX(ScmS32Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_S32VectorSwapBytes(ScmS32Vector *v0);
extern ScmObj Scm_S32VectorSwapBytesX(ScmS32Vector *v0);

/* U32Vector */

typedef struct ScmU32VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    ScmUInt32 *elements;
} ScmU32Vector;

SCM_CLASS_DECL(Scm_U32VectorClass);
#define SCM_CLASS_U32VECTOR  (&Scm_U32VectorClass)

#define SCM_U32VECTOR(obj)        ((ScmU32Vector*)(obj))
#define SCM_U32VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_U32VECTOR)
#define SCM_U32VECTOR_SIZE(obj)   (SCM_U32VECTOR(obj)->size)
#define SCM_U32VECTOR_ELEMENTS(obj) (SCM_U32VECTOR(obj)->elements)

extern ScmObj Scm_MakeU32Vector(int size, ScmUInt32 fill);
extern ScmObj Scm_MakeU32VectorFromArray(int size, const ScmUInt32 array[]);
extern ScmObj Scm_MakeU32VectorFromArrayShared(int size, ScmUInt32 array[]);
extern ScmObj Scm_U32VectorFill(ScmU32Vector *vec, ScmUInt32 fill, int, int);
extern ScmObj Scm_U32VectorRef(ScmU32Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_U32VectorSet(ScmU32Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_U32VectorToList(ScmU32Vector *vec, int start, int end);
extern ScmObj Scm_ListToU32Vector(ScmObj list, int clamp);
extern ScmObj Scm_U32VectorCopy(ScmU32Vector *vec, int start, int end);
extern ScmObj Scm_U32VectorCopyX(ScmU32Vector *dst, int dstart,
                                  ScmU32Vector *src, int sstart, int send);
extern ScmObj Scm_U32VectorToVector(ScmU32Vector *vec, int start, int end);
extern ScmObj Scm_VectorToU32Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_U32VectorAdd(ScmU32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U32VectorAddX(ScmU32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U32VectorSub(ScmU32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U32VectorSubX(ScmU32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U32VectorMul(ScmU32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U32VectorMulX(ScmU32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U32VectorDiv(ScmU32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U32VectorDivX(ScmU32Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_U32VectorAnd(ScmU32Vector *s0, ScmObj s1);
extern ScmObj Scm_U32VectorAndX(ScmU32Vector *s0, ScmObj s1);
extern ScmObj Scm_U32VectorIor(ScmU32Vector *s0, ScmObj s1);
extern ScmObj Scm_U32VectorIorX(ScmU32Vector *s0, ScmObj s1);
extern ScmObj Scm_U32VectorXor(ScmU32Vector *s0, ScmObj s1);
extern ScmObj Scm_U32VectorXorX(ScmU32Vector *s0, ScmObj s1);

extern ScmObj Scm_U32VectorDotProd(ScmU32Vector *v0, ScmObj v1);
extern ScmObj Scm_U32VectorRangeCheck(ScmU32Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U32VectorClamp(ScmU32Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U32VectorClampX(ScmU32Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_U32VectorSwapBytes(ScmU32Vector *v0);
extern ScmObj Scm_U32VectorSwapBytesX(ScmU32Vector *v0);

/* S64Vector */

typedef struct ScmS64VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    ScmInt64 *elements;
} ScmS64Vector;

SCM_CLASS_DECL(Scm_S64VectorClass);
#define SCM_CLASS_S64VECTOR  (&Scm_S64VectorClass)

#define SCM_S64VECTOR(obj)        ((ScmS64Vector*)(obj))
#define SCM_S64VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_S64VECTOR)
#define SCM_S64VECTOR_SIZE(obj)   (SCM_S64VECTOR(obj)->size)
#define SCM_S64VECTOR_ELEMENTS(obj) (SCM_S64VECTOR(obj)->elements)

extern ScmObj Scm_MakeS64Vector(int size, ScmInt64 fill);
extern ScmObj Scm_MakeS64VectorFromArray(int size, const ScmInt64 array[]);
extern ScmObj Scm_MakeS64VectorFromArrayShared(int size, ScmInt64 array[]);
extern ScmObj Scm_S64VectorFill(ScmS64Vector *vec, ScmInt64 fill, int, int);
extern ScmObj Scm_S64VectorRef(ScmS64Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_S64VectorSet(ScmS64Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_S64VectorToList(ScmS64Vector *vec, int start, int end);
extern ScmObj Scm_ListToS64Vector(ScmObj list, int clamp);
extern ScmObj Scm_S64VectorCopy(ScmS64Vector *vec, int start, int end);
extern ScmObj Scm_S64VectorCopyX(ScmS64Vector *dst, int dstart,
                                  ScmS64Vector *src, int sstart, int send);
extern ScmObj Scm_S64VectorToVector(ScmS64Vector *vec, int start, int end);
extern ScmObj Scm_VectorToS64Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_S64VectorAdd(ScmS64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S64VectorAddX(ScmS64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S64VectorSub(ScmS64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S64VectorSubX(ScmS64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S64VectorMul(ScmS64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S64VectorMulX(ScmS64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S64VectorDiv(ScmS64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_S64VectorDivX(ScmS64Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_S64VectorAnd(ScmS64Vector *s0, ScmObj s1);
extern ScmObj Scm_S64VectorAndX(ScmS64Vector *s0, ScmObj s1);
extern ScmObj Scm_S64VectorIor(ScmS64Vector *s0, ScmObj s1);
extern ScmObj Scm_S64VectorIorX(ScmS64Vector *s0, ScmObj s1);
extern ScmObj Scm_S64VectorXor(ScmS64Vector *s0, ScmObj s1);
extern ScmObj Scm_S64VectorXorX(ScmS64Vector *s0, ScmObj s1);

extern ScmObj Scm_S64VectorDotProd(ScmS64Vector *v0, ScmObj v1);
extern ScmObj Scm_S64VectorRangeCheck(ScmS64Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S64VectorClamp(ScmS64Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_S64VectorClampX(ScmS64Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_S64VectorSwapBytes(ScmS64Vector *v0);
extern ScmObj Scm_S64VectorSwapBytesX(ScmS64Vector *v0);

/* U64Vector */

typedef struct ScmU64VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    ScmUInt64 *elements;
} ScmU64Vector;

SCM_CLASS_DECL(Scm_U64VectorClass);
#define SCM_CLASS_U64VECTOR  (&Scm_U64VectorClass)

#define SCM_U64VECTOR(obj)        ((ScmU64Vector*)(obj))
#define SCM_U64VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_U64VECTOR)
#define SCM_U64VECTOR_SIZE(obj)   (SCM_U64VECTOR(obj)->size)
#define SCM_U64VECTOR_ELEMENTS(obj) (SCM_U64VECTOR(obj)->elements)

extern ScmObj Scm_MakeU64Vector(int size, ScmUInt64 fill);
extern ScmObj Scm_MakeU64VectorFromArray(int size, const ScmUInt64 array[]);
extern ScmObj Scm_MakeU64VectorFromArrayShared(int size, ScmUInt64 array[]);
extern ScmObj Scm_U64VectorFill(ScmU64Vector *vec, ScmUInt64 fill, int, int);
extern ScmObj Scm_U64VectorRef(ScmU64Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_U64VectorSet(ScmU64Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_U64VectorToList(ScmU64Vector *vec, int start, int end);
extern ScmObj Scm_ListToU64Vector(ScmObj list, int clamp);
extern ScmObj Scm_U64VectorCopy(ScmU64Vector *vec, int start, int end);
extern ScmObj Scm_U64VectorCopyX(ScmU64Vector *dst, int dstart,
                                  ScmU64Vector *src, int sstart, int send);
extern ScmObj Scm_U64VectorToVector(ScmU64Vector *vec, int start, int end);
extern ScmObj Scm_VectorToU64Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_U64VectorAdd(ScmU64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U64VectorAddX(ScmU64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U64VectorSub(ScmU64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U64VectorSubX(ScmU64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U64VectorMul(ScmU64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U64VectorMulX(ScmU64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U64VectorDiv(ScmU64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_U64VectorDivX(ScmU64Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_U64VectorAnd(ScmU64Vector *s0, ScmObj s1);
extern ScmObj Scm_U64VectorAndX(ScmU64Vector *s0, ScmObj s1);
extern ScmObj Scm_U64VectorIor(ScmU64Vector *s0, ScmObj s1);
extern ScmObj Scm_U64VectorIorX(ScmU64Vector *s0, ScmObj s1);
extern ScmObj Scm_U64VectorXor(ScmU64Vector *s0, ScmObj s1);
extern ScmObj Scm_U64VectorXorX(ScmU64Vector *s0, ScmObj s1);

extern ScmObj Scm_U64VectorDotProd(ScmU64Vector *v0, ScmObj v1);
extern ScmObj Scm_U64VectorRangeCheck(ScmU64Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U64VectorClamp(ScmU64Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_U64VectorClampX(ScmU64Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_U64VectorSwapBytes(ScmU64Vector *v0);
extern ScmObj Scm_U64VectorSwapBytesX(ScmU64Vector *v0);

/* F32Vector */

typedef struct ScmF32VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    float *elements;
} ScmF32Vector;

SCM_CLASS_DECL(Scm_F32VectorClass);
#define SCM_CLASS_F32VECTOR  (&Scm_F32VectorClass)

#define SCM_F32VECTOR(obj)        ((ScmF32Vector*)(obj))
#define SCM_F32VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_F32VECTOR)
#define SCM_F32VECTOR_SIZE(obj)   (SCM_F32VECTOR(obj)->size)
#define SCM_F32VECTOR_ELEMENTS(obj) (SCM_F32VECTOR(obj)->elements)

extern ScmObj Scm_MakeF32Vector(int size, float fill);
extern ScmObj Scm_MakeF32VectorFromArray(int size, const float array[]);
extern ScmObj Scm_MakeF32VectorFromArrayShared(int size, float array[]);
extern ScmObj Scm_F32VectorFill(ScmF32Vector *vec, float fill, int, int);
extern ScmObj Scm_F32VectorRef(ScmF32Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_F32VectorSet(ScmF32Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_F32VectorToList(ScmF32Vector *vec, int start, int end);
extern ScmObj Scm_ListToF32Vector(ScmObj list, int clamp);
extern ScmObj Scm_F32VectorCopy(ScmF32Vector *vec, int start, int end);
extern ScmObj Scm_F32VectorCopyX(ScmF32Vector *dst, int dstart,
                                  ScmF32Vector *src, int sstart, int send);
extern ScmObj Scm_F32VectorToVector(ScmF32Vector *vec, int start, int end);
extern ScmObj Scm_VectorToF32Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_F32VectorAdd(ScmF32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F32VectorAddX(ScmF32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F32VectorSub(ScmF32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F32VectorSubX(ScmF32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F32VectorMul(ScmF32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F32VectorMulX(ScmF32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F32VectorDiv(ScmF32Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F32VectorDivX(ScmF32Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_F32VectorAnd(ScmF32Vector *s0, ScmObj s1);
extern ScmObj Scm_F32VectorAndX(ScmF32Vector *s0, ScmObj s1);
extern ScmObj Scm_F32VectorIor(ScmF32Vector *s0, ScmObj s1);
extern ScmObj Scm_F32VectorIorX(ScmF32Vector *s0, ScmObj s1);
extern ScmObj Scm_F32VectorXor(ScmF32Vector *s0, ScmObj s1);
extern ScmObj Scm_F32VectorXorX(ScmF32Vector *s0, ScmObj s1);

extern ScmObj Scm_F32VectorDotProd(ScmF32Vector *v0, ScmObj v1);
extern ScmObj Scm_F32VectorRangeCheck(ScmF32Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_F32VectorClamp(ScmF32Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_F32VectorClampX(ScmF32Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_F32VectorSwapBytes(ScmF32Vector *v0);
extern ScmObj Scm_F32VectorSwapBytesX(ScmF32Vector *v0);

/* F64Vector */

typedef struct ScmF64VectorRec {
    SCM_HEADER;
    unsigned int immutable : 1;
    int size : (SIZEOF_INT*CHAR_BIT-1);
    void *owner;
    double *elements;
} ScmF64Vector;

SCM_CLASS_DECL(Scm_F64VectorClass);
#define SCM_CLASS_F64VECTOR  (&Scm_F64VectorClass)

#define SCM_F64VECTOR(obj)        ((ScmF64Vector*)(obj))
#define SCM_F64VECTORP(obj)       SCM_XTYPEP(obj, SCM_CLASS_F64VECTOR)
#define SCM_F64VECTOR_SIZE(obj)   (SCM_F64VECTOR(obj)->size)
#define SCM_F64VECTOR_ELEMENTS(obj) (SCM_F64VECTOR(obj)->elements)

extern ScmObj Scm_MakeF64Vector(int size, double fill);
extern ScmObj Scm_MakeF64VectorFromArray(int size, const double array[]);
extern ScmObj Scm_MakeF64VectorFromArrayShared(int size, double array[]);
extern ScmObj Scm_F64VectorFill(ScmF64Vector *vec, double fill, int, int);
extern ScmObj Scm_F64VectorRef(ScmF64Vector *vec, int index, ScmObj fallback);
extern ScmObj Scm_F64VectorSet(ScmF64Vector *vec, int index, ScmObj val, int clamp);
extern ScmObj Scm_F64VectorToList(ScmF64Vector *vec, int start, int end);
extern ScmObj Scm_ListToF64Vector(ScmObj list, int clamp);
extern ScmObj Scm_F64VectorCopy(ScmF64Vector *vec, int start, int end);
extern ScmObj Scm_F64VectorCopyX(ScmF64Vector *dst, int dstart,
                                  ScmF64Vector *src, int sstart, int send);
extern ScmObj Scm_F64VectorToVector(ScmF64Vector *vec, int start, int end);
extern ScmObj Scm_VectorToF64Vector(ScmVector *vec, int start, int end, int clamp);

/* arithmetics */
extern ScmObj Scm_F64VectorAdd(ScmF64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F64VectorAddX(ScmF64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F64VectorSub(ScmF64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F64VectorSubX(ScmF64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F64VectorMul(ScmF64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F64VectorMulX(ScmF64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F64VectorDiv(ScmF64Vector *s0, ScmObj s1, int clamp);
extern ScmObj Scm_F64VectorDivX(ScmF64Vector *s0, ScmObj s1, int clamp);

extern ScmObj Scm_F64VectorAnd(ScmF64Vector *s0, ScmObj s1);
extern ScmObj Scm_F64VectorAndX(ScmF64Vector *s0, ScmObj s1);
extern ScmObj Scm_F64VectorIor(ScmF64Vector *s0, ScmObj s1);
extern ScmObj Scm_F64VectorIorX(ScmF64Vector *s0, ScmObj s1);
extern ScmObj Scm_F64VectorXor(ScmF64Vector *s0, ScmObj s1);
extern ScmObj Scm_F64VectorXorX(ScmF64Vector *s0, ScmObj s1);

extern ScmObj Scm_F64VectorDotProd(ScmF64Vector *v0, ScmObj v1);
extern ScmObj Scm_F64VectorRangeCheck(ScmF64Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_F64VectorClamp(ScmF64Vector *v0, ScmObj min, ScmObj max);
extern ScmObj Scm_F64VectorClampX(ScmF64Vector *v0, ScmObj min, ScmObj max);

extern ScmObj Scm_F64VectorSwapBytes(ScmF64Vector *v0);
extern ScmObj Scm_F64VectorSwapBytesX(ScmF64Vector *v0);


#endif /* GAUCHE_UVECT_H */

