/*---------\
 | VECTOR.H |
/+----------+---------------------------------\
|                                             |
| Designed and Implimented by Adam Freidin    |
|                                             |
| This vector library provides a              |
|  fairly straitforward set of routines for   |
|  most linear functions.                     |
|                                             |
| Namespacing is similar to the OpenGL API    |
|                                             |
| Notes on usage:                             |
| Src and dst may be the same                 |
|  for all functions, but cases when they     |
|  overlap partially are undefined.           | 
|                                             |
| This library is designed to be a core       |
|  vector processing library.                 |
| For an example of a layers on               |
|  top of vector.c see geom.c,                |
|  a geometry library.  And matrix.c.         |
|                                             |
\--------------------------------------------*/

/*--------------------------------------\
| Disclaimer:
|   This code is certified by me to work, and work well,
|   Since I have no credentials as yet,
|    (perhaps other than this code here)
|   my certification means nothing whatsoever.
|
| Simply stated: USE AT YOUR OWN RISK
|
| You have permision to use this library free
|  free programs free of charge. 
| However for anything commercial, I get 
|  a copy of the product.
\---------------------------------------*/

#ifndef VECTOR_H_
#define VECTOR_H_

#include<math.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef VECTOR_MT_SAFE
# define VECTOR_MT_SAFE 0
#endif

#ifdef _REENTRANT
# undef  VECTOR_MT_SAFE
# define VECTOR_MT_SAFE 1
#endif

#if defined(WIN32) && !defined(VCTR_NO_DLL)
# ifdef VCTR_BUILD_DLL
#  define VCTR_SPEC __declspec(dllexport)
# else
#  define VCTR_SPEC __declspec(dllimport)
#  ifndef CZ_NOLIBPRAGMA
#   pragma comment(lib, "vector")
#  endif
# endif
# define VCTR_CALL __stdcall
#else
# ifdef WIN32
#  define VCTR_SPEC
#  define VCTR_CALL __stdcall
# else
#  define VCTR_SPEC
#  define VCTR_CALL
# endif
#endif

#define VCTR_R(ret) VCTR_SPEC ret VCTR_CALL

#ifdef __GNUC__
/* this is a minor optimization in gcc */
# define CFUNC __attribute__ ((const))
#else
# define CFUNC 
#endif

/* RunTime VECTOR Multi-Thread SAFE function: 
 |
 | The one and only library management function
 | returns the library compile-time value of VECTOR_MT_SAFE
 */
VCTR_R(int) rtVECTOR_MT_SAFE();

/* (u) + (v) */
VCTR_R(float *)add2f(float  dst[2], 
               const float  src[2], const float  src2[2]);
VCTR_R(double*)add2d(double dst[2], 
               const double src[2], const double src2[2]);
VCTR_R(float *)add3f(float  dst[3],
               const float  src[3], const float  src2[3]);
VCTR_R(double*)add3d(double dst[3]
             , const double src[3], const double src2[3]);
VCTR_R(float *)add4f(float  dst[4]
             , const float  src[4], const float  src2[4]);
VCTR_R(double*)add4d(double dst[4],
               const double src[4], const double src2[4]);
VCTR_R(float *)addNf(float  *dst, int n, 
               const float  *src, const float  *src2);
VCTR_R(double*)addNd(double *dst, int n,
               const double *src, const double *src2);

/* (u) - (v) */
VCTR_R(float *)sub2f(float  dst[2],
               const float  src[2], const float  src2[2]);
VCTR_R(double*)sub2d(double dst[2],
               const double src[2], const double src2[2]);
VCTR_R(float *)sub3f(float  dst[3],
               const float  src[3], const float  src2[3]);
VCTR_R(double*)sub3d(double dst[3],
               const double src[3], const double src2[3]);
VCTR_R(float *)sub4f(float  dst[4],
               const float  src[4], const float  src2[4]);
VCTR_R(double*)sub4d(double dst[4],
               const double src[4], const double src2[4]);
VCTR_R(float *)subNf(float  *dst, int n,
               const float  *src, const float  *src2);
VCTR_R(double*)subNd(double *dst, int n,
               const double *src, const double *src2);

/* a(v) */
VCTR_R(float *)mul2f(float  dst[2],
               const float  src[2], const float  src2);
VCTR_R(double*)mul2d(double dst[2],
               const double src[2], const double src2);
VCTR_R(float *)mul3f(float  dst[3],
               const float  src[3], const float  src2);
VCTR_R(double*)mul3d(double dst[3],
               const double src[3], const double src2);
VCTR_R(float *)mul4f(float  dst[4],
               const float  src[4], const float  src2);
VCTR_R(double*)mul4d(double dst[4],
               const double src[4], const double src2);
VCTR_R(float *)mulNf(float  *dst, int n,
               const float  *src, float  mul);
VCTR_R(double*)mulNd(double *dst, int n,
               const double *src, double mul);

/* v+a(u) */
VCTR_R(float *)mad2f(float  dst[2],
               const float  src[2], const float  src2[2], float  mul);
VCTR_R(double*)mad2d(double dst[2],
               const double src[2], const double src2[2], double mul);
VCTR_R(float *)mad3f(float  dst[3],
               const float  src[3], const float  src2[3], float  mul);
VCTR_R(double*)mad3d(double dst[3],
               const double src[3], const double src2[3], double mul);
VCTR_R(float *)mad4f(float  dst[4],
               const float  src[4], const float  src2[4], float  mul);
VCTR_R(double*)mad4d(double dst[4],
               const double src[4], const double src2[4], double mul);
VCTR_R(float *)madNf(float  *dst, int n,
               const float  *src, const float  *src2, float  mul);
VCTR_R(double*)madNd(double *dst, int n,
               const double *src, const double *src2, double mul);

/* -v */
VCTR_R(float *)neg2f(float  d[2], const float  s[2]);
VCTR_R(double*)neg2d(double d[2], const double s[2]);
VCTR_R(float *)neg3f(float  d[3], const float  s[3]);
VCTR_R(double*)neg3d(double d[3], const double s[3]);
VCTR_R(float *)neg4f(float  d[4], const float  s[4]);
VCTR_R(double*)neg4d(double d[4], const double s[4]);
VCTR_R(float *)negNf(float  *dst, int n, const float  *src);
VCTR_R(double*)negNd(double *dst, int n, const double *src);

VCTR_R(float *)set2f(float  v[2], float  a, float  b) CFUNC;
VCTR_R(double*)set2d(double v[2], double a, double b) CFUNC;
VCTR_R(float *)set3f(float  v[3], float  a, float  b, float  c) CFUNC;
VCTR_R(double*)set3d(double v[3], double a, double b, double c) CFUNC;
VCTR_R(float *)set4f(float  v[4], float  a, float  b,
                                  float  c, float  d) CFUNC;
VCTR_R(double*)set4d(double v[4], double a, double b,
                                  double c, double d) CFUNC;
VCTR_R(float *)setNf(float  *v, int n, ...) CFUNC;
VCTR_R(double*)setNd(double *v, int n, ...) CFUNC;

/* (u)<dot>(v) */
VCTR_R(float )dot2f(const float  src[2], const float  src2[2]);
VCTR_R(double)dot2d(const double src[2], const double src2[2]);
VCTR_R(float )dot3f(const float  src[3], const float  src2[3]);
VCTR_R(double)dot3d(const double src[3], const double src2[3]);
VCTR_R(float )dot4f(const float  src[4], const float  src2[4]);
VCTR_R(double)dot4d(const double src[4], const double src2[4]);
VCTR_R(float )dotNf(int n, const float  *src, const float  *src2);
VCTR_R(double)dotNd(int n, const double *src, const double *src2);

/* project (v) onto (d) */
VCTR_R(float *)project2f(float  dst[2],
                   const float  v[2], const float  d[2]);
VCTR_R(double*)project2d(double dst[2],
                   const double v[2], const double d[2]);
VCTR_R(float *)project3f(float  dst[3],
                   const float  v[3], const float  d[3]);
VCTR_R(double*)project3d(double dst[3],
                   const double v[3], const double d[3]);
VCTR_R(float *)project4f(float  dst[4],
                   const float  v[4], const float  d[4]);
VCTR_R(double*)project4d(double dst[4],
                   const double v[4], const double d[4]);
VCTR_R(float *)projectNf(float  *dst, int n,
                   const float  *v, const float  *d);
VCTR_R(double*)projectNd(double *dst, int n,
                   const double *v, const double *d);

/* project (v) onto UNIT (d) */
VCTR_R(float *)projectu2f(float  dst[2],
                    const float  v[2], const float  d[2]);
VCTR_R(double*)projectu2d(double dst[2],
                    const double v[2], const double d[2]);
VCTR_R(float *)projectu3f(float  dst[3],
                    const float  v[3], const float  d[3]);
VCTR_R(double*)projectu3d(double dst[3],
                    const double v[3], const double d[3]);
VCTR_R(float *)projectu4f(float  dst[4], 
                    const float  v[4], const float  d[4]);
VCTR_R(double*)projectu4d(double dst[4],
                    const double v[4], const double d[4]);
VCTR_R(float *)projectuNf(float  *dst, int n,
                    const float  *v, const float  *d);
VCTR_R(double*)projectuNd(double *dst, int n,
                    const double *v, const double *d);

/* ||(v)|| */
VCTR_R(float )norm2f(const float  src[2]);
VCTR_R(double)norm2d(const double src[2]);
VCTR_R(float )norm3f(const float  src[3]);
VCTR_R(double)norm3d(const double src[3]);
VCTR_R(float )norm4f(const float  src[4]);
VCTR_R(double)norm4d(const double src[4]);
VCTR_R(float )normNf(const float  *src, int n);
VCTR_R(double)normNd(const double *src, int n);

/* (v)/||(v)|| */
VCTR_R(float *)unit2f(float  dst[2], const float  src[2]);
VCTR_R(double*)unit2d(double dst[2], const double src[2]);
VCTR_R(float *)unit3f(float  dst[3], const float  src[3]);
VCTR_R(double*)unit3d(double dst[3], const double src[3]);
VCTR_R(float *)unit4f(float  dst[4], const float  src[4]);
VCTR_R(double*)unit4d(double dst[4], const double src[4]);
VCTR_R(float *)unitNf(float  *dst, int n, const float  *src);
VCTR_R(double*)unitNd(double *dst, int n, const double *src);

/* (u)<cross>(v) */
VCTR_R(float *)crossf(float  dst[3],
                const float  src[3], const float  src2[3]);
VCTR_R(double*)crossd(double dst[3],
                const double src[3], const double src2[3]);

/* (v) rotated about (axis) by angle */
VCTR_R(float *)rotf(float  dst[3], const float  src[3], 
                    const float  axis[3], float  angle);
VCTR_R(double*)rotd(double dst[3], const double src[3], 
                    const double axis[3], double angle);

/* quaternion dot product */
VCTR_R(float *)qdotf(float  dst[4],
               const float  src[4], const float  src2[4]);
VCTR_R(double*)qdotd(double dst[4],
               const double src[4], const double src2[4]);

/* variant quaternion dot product, assumes src2[3] == 0 */
VCTR_R(float *)q3dotf(float  dst[4],
                const float  src[4], const float  src2[3]);
VCTR_R(double*)q3dotd(double dst[4],
                const double src[4], const double src2[3]);

/* variant quaternion dot product, only returns vector part */
VCTR_R(float *)qdot3f(float  dst[3],
                const float  src[4], const float  src2[4]);
VCTR_R(double*)qdot3d(double dst[3],
                const double src[4], const double src2[4]);

/* builds a rotation quaternion */
VCTR_R(float *)qrotf(float  dst[4],
               const float  axis[3], float  angle);
VCTR_R(double*)qrotd(double dst[4],
               const double axis[3], double angle);

/* applies a quarternion rotation */
VCTR_R(float *)qapplyf(float  dst[3],
                 const float  src[3], const float  rot[4]);
VCTR_R(double*)qapplyd(double dst[3],
                 const double src[3], const double rot[4]);

/* [I] */
VCTR_R(float *)ident2x2f(float  dst[4]);
VCTR_R(double*)ident2x2d(double dst[4]);
VCTR_R(float *)ident3x3f(float  dst[9]);
VCTR_R(double*)ident3x3d(double dst[9]);
VCTR_R(float *)ident4x4f(float  dst[16]);
VCTR_R(double*)ident4x4d(double dst[16]);
VCTR_R(float *)identNxNf(float  *dst, int n);
VCTR_R(double*)identNxNd(double *dst, int n);

/* [m] w/out row ix and column jx */
VCTR_R(float *)submatrix3x3f(float  dst[4], 
                       const float  src[9],
                       const int ix, const int jx);
VCTR_R(double*)submatrix3x3d(double dst[4], 
                       const double src[9],
                       const int ix, const int jx);
VCTR_R(float *)submatrix4x4f(float  dst[9], 
                       const float  src[16],
                       const int ix, const int jx);
VCTR_R(double*)submatrix4x4d(double dst[9], 
                       const double src[16],
                       const int ix, const int jx);
VCTR_R(float *)submatrixNxNf(float  *dst, int n, 
                       const float  *src,
                       const int ix, const int jx);
VCTR_R(double*)submatrixNxNd(double *dst, int n,
                       const double *src,
                       const int ix, const int jx);

/* Det([m]) */
VCTR_R(float )det2x2f(const float  src[ 4]);
VCTR_R(double)det2x2d(const double src[ 4]);
VCTR_R(float )det3x3f(const float  src[ 9]);
VCTR_R(double)det3x3d(const double src[ 9]);
VCTR_R(float )det4x4f(const float  src[16]);
VCTR_R(double)det4x4d(const double src[16]);
VCTR_R(float )detNxNf(int n, const float  *src);
VCTR_R(double)detNxNd(int n, const double *src);

/* [m]<dot>[n] */
VCTR_R(float *)mul2x2f(float  dst[4],
                 const float  m[4], const float  n[4]);
VCTR_R(double*)mul2x2d(double dst[4],
                 const double m[4], const double n[4]);
VCTR_R(float *)mul3x3f(float  dst[9],
                 const float  m[9], const float  n[9]);
VCTR_R(double*)mul3x3d(double dst[9],
                 const double m[9], const double n[9]);
VCTR_R(float *)mul4x4f(float  dst[16],
                 const float  m[16], const float  n[16]);
VCTR_R(double*)mul4x4d(double dst[16],
                 const double m[16], const double n[16]);
VCTR_R(float *)mulNxNf(float  *dst, int n,
                 const float  *m, const float  *m2);
VCTR_R(double*)mulNxNd(double *dst, int n,
                 const double *m, const double *m2);

/* a*[m] */
VCTR_R(float *)scale2x2f(float  dst[ 4],
                   const float  src[ 4], float  mul);
VCTR_R(double*)scale2x2d(double dst[ 4],
                   const double src[ 4], double mul);
VCTR_R(float *)scale3x3f(float  dst[ 9],
                   const float  src[ 9], float  mul);
VCTR_R(double*)scale3x3d(double dst[ 9],
                   const double src[ 9], double mul);
VCTR_R(float *)scale4x4f(float  dst[16],
                   const float  src[16], float  mul);
VCTR_R(double*)scale4x4d(double dst[16],
                   const double src[16], double mul);
VCTR_R(float *)scaleNxNf(float  *dst, int n,
                   const float  *src, float  mul);
VCTR_R(double*)scaleNxNd(double *dst, int n,
                   const double *src, double mul);

/* cofactor[M, i, j] */
/* must pass in det explicitly */
VCTR_R(float )cofactor2x2f(const float  m[ 4],
                           float  inv_det, int i, int j);
VCTR_R(double)cofactor2x2d(const double m[ 4],
                           double inv_det, int i, int j);
VCTR_R(float )cofactor3x3f(const float  m[ 9],
                           float  inv_det, int i, int j);
VCTR_R(double)cofactor3x3d(const double m[ 9],
                           double inv_det, int i, int j);
VCTR_R(float )cofactor4x4f(const float  m[16],
                           float  inv_det, int i, int j);
VCTR_R(double)cofactor4x4d(const double m[16],
                           double inv_det, int i, int j);
VCTR_R(float )cofactorNxNf(int n, const float  *m,
                           float  invdet, int i, int j);
VCTR_R(double)cofactorNxNd(int n, const double *m,
                           double invdet, int i, int j);

/* [m]^(-1) */
VCTR_R(float *)inverse2x2f(float  dst[ 4], const float  src[ 4]);
VCTR_R(double*)inverse2x2d(double dst[ 4], const double src[ 4]);
VCTR_R(float *)inverse3x3f(float  dst[ 9], const float  src[ 9]);
VCTR_R(double*)inverse3x3d(double dst[ 9], const double src[ 9]);
VCTR_R(float *)inverse4x4f(float  dst[16], const float  src[16]);
VCTR_R(double*)inverse4x4d(double dst[16], const double src[16]);
VCTR_R(float *)inverseNxNf(float  *dst, int n, const float  *src);
VCTR_R(double*)inverseNxNd(double *dst, int n, const double *src);

/* [m]^(-1)*det(m) */
VCTR_R(float *)invert2x2f(float  dst[ 4],
                    const float  src[ 4], float  det);
VCTR_R(double*)invert2x2d(double dst[ 4], 
                    const double src[ 4], double det);
VCTR_R(float *)invert3x3f(float  dst[ 9],
                    const float  src[ 9], float  det);
VCTR_R(double*)invert3x3d(double dst[ 9],
                    const double src[ 9], double det);
VCTR_R(float *)invert4x4f(float  dst[16],
                    const float  src[16], float  det);
VCTR_R(double*)invert4x4d(double dst[16],
                    const double src[16], double det);
VCTR_R(float *)invertNxNf(float  *dst, int n,
                    const float  *src, float  det);
VCTR_R(double*)invertNxNd(double *dst, int n,
                    const double *src, double det);

/* [M]^t */
VCTR_R(float *)transpose2x2f(float  dst[ 4], const float  src[ 4]);
VCTR_R(double*)transpose2x2d(double dst[ 4], const double src[ 4]);
VCTR_R(float *)transpose3x3f(float  dst[ 9], const float  src[ 9]);
VCTR_R(double*)transpose3x3d(double dst[ 9], const double src[ 9]);
VCTR_R(float *)transpose4x4f(float  dst[16], const float  src[16]);
VCTR_R(double*)transpose4x4d(double dst[16], const double src[16]);
VCTR_R(float *)transposeNxNf(float  *dst, int n, const float  *src);
VCTR_R(double*)transposeNxNd(double *dst, int n, const double *src);

/* [m]<dot>(v) */
VCTR_R(double*)transform2x2d(double dst[2],
                       const double m[4], const double v[2]);
VCTR_R(float *)transform2x2f(float  dst[2],
                       const float  m[4], const float  v[2]);
VCTR_R(double*)transform3x3d(double dst[3],
                       const double m[9], const double v[3]);
VCTR_R(float *)transform3x3f(float  dst[3],
                       const float  m[9], const float  v[3]);
VCTR_R(double*)transform4x4d(double dst[4],
                       const double m[16], const double v[4]);
VCTR_R(float *)transform4x4f(float  dst[4],
                       const float  m[16], const float  v[4]);
VCTR_R(float *)transformNxNf(float  *dst, int n,
                       const float  *m, const float  *v);
VCTR_R(double*)transformNxNd(double *dst, int n,
                       const double *m, const double *v);

/* (v)^T<dot>[m] */
VCTR_R(float *)postmultiply2x2f(float  dst[2],
                          const float  v[2], const float  m[ 4]);
VCTR_R(double*)postmultiply2x2d(double dst[2],
                          const double v[2], const double m[ 4]);
VCTR_R(float *)postmultiply3x3f(float  dst[3],
                          const float  v[3], const float  m[ 9]);
VCTR_R(double*)postmultiply3x3d(double dst[3],
                          const double v[3], const double m[ 9]);
VCTR_R(float *)postmultiply4x4f(float  dst[4],
                          const float  v[4], const float  m[16]);
VCTR_R(double*)postmultiply4x4d(double dst[4],
                          const double v[4], const double m[16]);
VCTR_R(float *)postmultiplyNxNf(float  *dst, int n,
                          const float  *v, const float  *m);
VCTR_R(double*)postmultiplyNxNd(double *dst, int n,
                          const double *v, const double *m);

/* (v)<dot>[m]<dot>(v) */
VCTR_R(float )tensor2x2f(const float  m[ 4], const float  v[2]);
VCTR_R(double)tensor2x2d(const double m[ 4], const double v[2]);
VCTR_R(float )tensor3x3f(const float  m[ 9], const float  v[3]);
VCTR_R(double)tensor3x3d(const double m[ 9], const double v[3]);
VCTR_R(float )tensor4x4f(const float  m[16], const float  v[4]);
VCTR_R(double)tensor4x4d(const double m[16], const double v[4]);
VCTR_R(float )tensorNxNf(int n, const float  *m, const float  *v);
VCTR_R(double)tensorNxNd(int n, const double *m, const double *v);

/* vector copying */
VCTR_R(float *)cpy2f(float  d[2], const float  s[2]);
VCTR_R(double*)cpy2d(double d[2], const double s[2]);
VCTR_R(float *)cpy3f(float  d[3], const float  s[3]);
VCTR_R(double*)cpy3d(double d[3], const double s[3]);
VCTR_R(float *)cpy4f(float  d[4], const float  s[4]);
VCTR_R(double*)cpy4d(double d[4], const double s[4]);
VCTR_R(float *)cpyNf(float  *d, int n, const float  *s);
VCTR_R(double*)cpyNd(double *d, int n, const double *s);

/* matrix copying */
VCTR_R(float *)cpy2x2f(float  d[ 4], const float  s[ 4]);
VCTR_R(double*)cpy2x2d(double d[ 4], const double s[ 4]);
VCTR_R(float *)cpy3x3f(float  d[ 9], const float  s[ 9]);
VCTR_R(double*)cpy3x3d(double d[ 9], const double s[ 9]);
VCTR_R(float *)cpy4x4f(float  d[16], const float  s[16]);
VCTR_R(double*)cpy4x4d(double d[16], const double s[16]);
VCTR_R(float *)cpyNxNf(float  *dst, int n, const float  *src);
VCTR_R(double*)cpyNxNd(double *dst, int n, const double *src);

/* multisize matrix copying */
VCTR_R(float *)cpy2x2to3x3f(float  dst[ 9], const float  src[ 4]);
VCTR_R(double*)cpy2x2to3x3d(double dst[ 9], const double src[ 4]);
VCTR_R(float *)cpy3x3to2x2f(float  dst[ 4], const float  src[ 9]);
VCTR_R(double*)cpy3x3to2x2d(double dst[ 4], const double src[ 9]);
VCTR_R(float *)cpy3x3to4x4f(float  dst[16], const float  src[ 9]);
VCTR_R(double*)cpy3x3to4x4d(double dst[16], const double src[ 9]);
VCTR_R(float *)cpy4x4to3x3f(float  dst[ 9], const float  src[16]);
VCTR_R(double*)cpy4x4to3x3d(double dst[ 9], const double src[16]);
VCTR_R(float *)cpyNxNtoMxMf(float  *dst, int n,
                      const float  *src, int m);
VCTR_R(double*)cpyNxNtoMxMd(double *dst, int n,
                      const double *src, int m);

VCTR_R(float *)getcolumn2x2f(float  v[3],
                       const float  m[ 4], int column);
VCTR_R(double*)getcolumn2x2d(double v[3],
                       const double m[ 4], int column);
VCTR_R(float *)getcolumn3x3f(float  v[3],
                       const float  m[ 9], int column);
VCTR_R(double*)getcolumn3x3d(double v[3],
                       const double m[ 9], int column);
VCTR_R(float *)getcolumn4x4f(float  v[4],
                       const float  m[16], int column);
VCTR_R(double*)getcolumn4x4d(double v[4],
                       const double m[16], int column);
VCTR_R(float *)getcolumnNxNf(float  *v, int n,
                       const float  *m, int column);
VCTR_R(double*)getcolumnNxNd(double *v, int n,
                       const double *m, int column);

VCTR_R(float *)setcolumn2x2f(float  m[ 4], const float  *v, 
                             int column, int vstart, int vend);
VCTR_R(double*)setcolumn2x2d(double m[ 4], const double *v, 
                             int column, int vstart, int vend);
VCTR_R(float *)setcolumn3x3f(float  m[ 9], const float  *v, 
                             int column, int vstart, int vend);
VCTR_R(double*)setcolumn3x3d(double m[ 9], const double *v, 
                             int column, int vstart, int vend);
VCTR_R(float *)setcolumn4x4f(float  m[16], const float  *v, 
                             int column, int vstart, int vend);
VCTR_R(double*)setcolumn4x4d(double m[16], const double *v,
                             int column, int vstart, int vend);
VCTR_R(float *)setcolumnNxNf(float  *m, int n, const float  *v,
                             int column, int vstart, int vend);
VCTR_R(double*)setcolumnNxNd(double *m, int n, const double *v,
                             int column, int vstart, int vend);

/* fast index of greatest (magnitude) component */
VCTR_R(int)absmaxindex2f(const float  v[2]);
VCTR_R(int)absmaxindex2d(const double v[2]);
VCTR_R(int)absmaxindex3f(const float  v[3]);
VCTR_R(int)absmaxindex3d(const double v[3]);
VCTR_R(int)absmaxindex4f(const float  v[4]);
VCTR_R(int)absmaxindex4d(const double v[4]);
VCTR_R(int)absmaxindexNf(const float  *v, int n);
VCTR_R(int)absmaxindexNd(const double *v, int n);

VCTR_R(double*)convfd(double *dst, int n, const float  *src);
VCTR_R(float *)convdf(float  *dst, int n, const double *src);

VCTR_R(float )sqrtf(float  f) CFUNC;
VCTR_R(double)sqrtd(double d) CFUNC;

VCTR_R(float )fabsf(float  f) CFUNC;
VCTR_R(double)fabsd(double d) CFUNC;

#define sqrtf(f) ( (float) sqrt( (double)(f) ) )
#define sqrtd(d) (         sqrt( (double)(d) ) )

#define fabsf(f) ( (float) fabs( (double)(f) ) )
#define fabsd(d) (         fabs( (double)(d) ) )

#ifdef __cplusplus
}
#include"vectorcpp.h"
#endif

#endif