
********************************************************************************

                              Linear algebra

********************************************************************************


Files
-----

cmatrix.c      Complex matrix algebra (single-precision version)

cmatrix_dble.c Complex matrix algebra (double-precision version)

liealg.c       Basic functions for fields with values in the Lie 
               algebra of SU(3)

salg.c         Generic linear algebra routines for single-precision 
               spinor fields

salg_dble.c    Generic linear algebra routines for double-precision 
               spinor fields

valg.c         Generic linear algebra routines for single-precision 
               complex fields

valg_dble.c    Generic linear algebra routines for double-precision 
               complex fields


Include file
------------

The file linalg.h defines the prototypes for all externally accessible
functions that are defined in the *.c files listed above.


List of functions
-----------------

void cmat_vec(int n,complex *a,complex *v,complex *w)
  Computes w=a*v, where v and w are n-vectors and a an nxn matrix.

void cmat_vec_assign(int n,complex *a,complex *v,complex *w)
  Adds a*v to w, where v and w are n-vectors and a an nxn matrix.
  
void cmat_add(int n,complex *a,complex *b,complex *c)
  Computes the sum c=a+b of two nxn matrices a and b.

void cmat_sub(int n,complex *a,complex *b,complex *c)
  Computes the difference c=a-b of two nxn matrices a and b.

void cmat_mul(int n,complex *a,complex *b,complex *c)
  Computes the product c=a*b of two nxn matrices a and b.

void cmat_dag(int n,complex *a,complex *b)
  Assigns the hermitian conjugate of a to b.

void cmat_vec_dble(int n,complex_dble *a,complex_dble *v,complex_dble *w)
  Computes w=a*v, where v and w are n-vectors and a an nxn matrix.

void cmat_vec_assign_dble(int n,complex_dble *a,complex_dble *v,
                          complex_dble *w)
  Adds a*v to w, where v and w are n-vectors and a an nxn matrix.
  
void cmat_add_dble(int n,complex_dble *a,complex_dble *b,complex_dble *c)
  Computes the sum c=a+b of two nxn matrices a and b.

void cmat_sub_dble(int n,complex_dble *a,complex_dble *b,complex_dble *c)
  Computes the difference c=a-b of two nxn matrices a and b.

void cmat_mul_dble(int n,complex_dble *a,complex_dble *b,complex_dble *c)
  Computes the product c=a*b of two nxn matrices a and b.

void cmat_dag_dble(int n,complex_dble *a,complex_dble *b)
  Assigns the hermitian conjugate of a to b.

int cmat_inv_dble(int n,complex_dble *a,complex_dble *b,double *k)
  Computes the inverse b of the nxn matrix a, using Householder
  reflections. The Frobenius condition number k of a is also computed.
  A non-zero return value indicates that the input matrix was found to
  be singular within rounding errors and that the program terminated
  prematurely.

void random_alg(int vol,su3_alg_dble *X)
  Initializes the Lie algebra elements X to random values
  with distribution proportional to exp{tr[X^2]}.

double norm_square_alg(int vol,int icom,su3_alg_dble *X)
  Computes the square of the norm of the norm squared of the field X.

double scalar_prod_alg(int vol,int icom,su3_alg_dble *X,su3_alg_dble *Y)
  Computes the scalar product of the fields X and Y.

void set_alg2zero(int vol,su3_alg_dble *X)
  Sets the array elements X to zero.

void set_ualg2zero(int vol,u3_alg_dble *X)
  Sets the array elements X to zero.

void assign_alg2alg(int vol,su3_alg_dble *X,su3_alg_dble *Y)
  Assigns the field X to the field Y.

void swap_alg(int vol,su3_alg_dble *X,su3_alg_dble *Y)
  Swaps the fields X and Y.

void muladd_assign_alg(int vol,double r,su3_alg_dble *X,su3_alg_dble *Y)
  Adds r*X to Y.

complex spinor_prod(int vol,int icom,spinor *s,spinor *r)
  Computes the scalar product of the fields s and r.

float spinor_prod_re(int vol,int icom,spinor *s,spinor *r)
  Computes the real part of the scalar product of the fields
  s and r.

float norm_square(int vol,int icom,spinor *s)
  Computes the square of the norm of the field s.

void mulc_spinor_add(int vol,spinor *s,spinor *r,complex z)
  Replaces the field s by s+z*r.

void mulr_spinor_add(int vol,spinor *s,spinor *r,float c)
  Replaces the field s by s+c*r.

void project(int vol,int icom,spinor *s,spinor *r)
  Replaces the field s by s-(r,s)*r.

void scale(int vol,float c,spinor *s)
  Replaces the field s by c*s.

float normalize(int vol,int icom,spinor *s)
  Replaces the field s by s/||s|| and returns the norm ||s||.

void rotate(int vol,int n,spinor **ppk,complex *v)
  Replaces the fields pk[] by sum_j pj*v[n*j+k] where 0<=k,j<n
  and pk=ppk[k].

void mulg5(int vol,spinor *s)
  Multiplies the field s with gamma_5.

void mulmg5(int vol,spinor *s)
  Multiplies the field s with -gamma_5.

complex_dble spinor_prod_dble(int vol,int icom,spinor_dble *s,
                              spinor_dble *r)
  Computes the scalar product of the fields s and r.

double spinor_prod_re_dble(int vol,int icom,spinor_dble *s,
                           spinor_dble *r)
  Computes the real part of the scalar product of the fields
  s and r.

complex_dble spinor_prod5_dble(int vol,int icom,spinor_dble *s,
                               spinor_dble *r)
  Computes the scalar product of the fields s and gamma_5*r.

double norm_square_dble(int vol,int icom,spinor_dble *s)
  Computes the square of the norm of the field s.

void mulc_spinor_add_dble(int vol,spinor_dble *s,spinor_dble *r,
                          complex_dble z)
  Replaces the field s by s+z*r.

void mulr_spinor_add_dble(int vol,spinor_dble *s,spinor_dble *r,
                          double c)
  Replaces the field s by s+c*r.

void project_dble(int vol,int icom,spinor_dble *s,spinor_dble *r)
  Replaces the field s by s-(r,s)*r.

void scale_dble(int vol,double c,spinor_dble *s)
  Replaces the field s by c*s.

double normalize_dble(int vol,int icom,spinor_dble *s)
  Replaces the field s by s/||s|| and returns the norm ||s||.

void rotate_dble(int vol,int n,spinor_dble **ppk,complex_dble *v)
  Replaces the fields pk by sum_j pj*v[n*j+k] where 0<=k,j<n and
  pk=ppk[k].

void mulg5_dble(int vol,spinor_dble *s)
  Multiplies the field s with gamma_5.

void mulmg5_dble(int vol,spinor_dble *s)
  Multiplies the field s with -gamma_5.

complex vprod(int n,int icom,complex *v,complex *w)
  Computes the scalar product of the n-vectors v and w.

float vnorm_square(int n,int icom,complex *v)
  Computes the square of the norm of the n-vector v.

void mulc_vadd(int n,complex *v,complex *w,complex z)
  Replaces the n-vector v by v+z*w.

void vproject(int n,int icom,complex *v,complex *w)
  Replaces the n-vector v by v-(w,v)*w.

void vscale(int n,float r,complex_dble *v)
  Replaces the n-vector v by r*v.

float vnormalize(int n,int icom,complex *v)
  Normalizes the n-vector v to unity and returns the norm of the
  input vector.

void vrotate(int n,int nv,complex **pv,complex *a)
  Replaces the n-vectors vk=pv[k], k=0,..,nv-1, by the linear
  combinations sum_{j=0}^{nv-1} vj*a[n*j+k].

complex_dble vprod_dble(int n,int icom,complex_dble *v,complex_dble *w)
  Computes the scalar product of the n-vectors v and w. 

float vnorm_square_dble(int n,int icom,complex_dble *v)
  Computes the square of the norm of the n-vector v.

void mulc_vadd_dble(int n,complex_dble *v,complex_dble *w,complex_dble z)
  Replaces the n-vector v by v+z*w.

void vproject_dble(int n,int icom,complex_dble *v,complex_dble *w)
  Replaces the n-vector v by v-(w,v)*w.

void vscale_dble(int n,double r,complex_dble *v)
  Replaces the n-vector v by r*v.

float vnormalize_dble(int n,int icom,complex_dble *v)
  Normalizes the n-vector v to unity and returns the norm of the
  input vector.

void vrotate_dble(int n,int nv,complex_dble **pv,complex_dble *a)
  Replaces the n-vectors vk=pv[k], k=0,..,nv-1, by the linear
  combinations sum_{j=0}^{nv-1} vj*a[n*j+k].
