Esempio n. 1
0
/*
 * Argument a contains pointers to the rows of a symmetrix matrix.  The
 * in each row is the row number + 1.  These rows are stored in
 * contiguous memory starting with 0.  Evecs also contains pointers to
 * contiguous memory.  N is the dimension.
 */
void
cmat_diag(double**a, double*evals, double**evecs, int n,
              int matz, double tol)
{
  int i,j;
  int diagonal=1;
  double*fv1;

 /* I'm having problems with diagonalizing matrices which are already
  * diagonal.  So let's first check to see if _a_ is diagonal, and if it
  * is, then just return the diagonal elements in evals and a unit matrix
  * in evecs
  */

  for (i=1; i < n; i++) {
    for (j=0; j < i; j++) {
      if (fabs(a[i][j]) > tol) diagonal=0;
      }
    }

  if (diagonal) {
    for(i=0; i < n; i++) {
      evals[i] = a[i][i];
      evecs[i][i] = 1.0;

      for(j=0; j < i; j++) {
        evecs[i][j] = evecs[j][i] = 0.0;
        }
      }
    eigsort(n,evals,evecs);
    return;
    }

  fv1 = (double*) malloc(sizeof(double)*n);
  if (!fv1) {
    fprintf(stderr,"cmat_diag: malloc fv1 failed\n");
    abort();
  }

  for(i=0; i < n; i++) {
      for(j=0; j <= i; j++) {
          evecs[i][j] = evecs[j][i] = a[i][j];
        }
    }

  tred2(n,evecs,evals,fv1,1);

  cmat_transpose_square_matrix(evecs,n);
  tqli(n,evals,evecs,fv1,1,tol);
  cmat_transpose_square_matrix(evecs,n);

  eigsort(n,evals,evecs);

  free(fv1);
  }
Esempio n. 2
0
/********************************************************************
*
*   Function    : jacobi
*   Goal        : 
*
*    
*   input parameters   : mat   : original Matrix
*
*   output parameters  : d     : contains the eigenvalues
*                        eig_v : contains the eigenvectors as columna
*
*   returnted Value    : success or error messages
*
********************************************************************/
extern int jacobi( Matrix* mat, Vector *d, Matrix *eig_v )
{
  int    j, iq, ip, i, n, nrot;
  double tresh, theta, tau, t, sm, s, h, g, c;
  Vector *b, 
         *z;       /* this vector accumulate terms */
  double **mval, **vval, **bval, **dval, **zval;
  Matrix *msave;

  if( (mat == NULL) || (d == NULL) || (eig_v == NULL) )
    { printf(" jacobi: you gave me a NULL-pointer\n");
      return( MATH_FATAL_ERROR );
    }

  if( (MDim1(mat) != MDim2(mat)) || (VDim(d) != MDim1(mat)) ||
      (MDim1(eig_v) != MDim2(eig_v)) || (MDim1(mat) != MDim1(eig_v)) )
    { printf(" jacobi: wrong dimensions of the matrices or the vector\n");
      return( MATH_WARNING );
    }
  
  msave = matrix_alloc( MDim1(mat), MDim2(mat) );
  matrix_copy( mat, msave );

  n = MDim1(msave);
  mval = msave->val;
  vval = eig_v->val;
  dval = d->val;
  b = vector_alloc( n );   bval = b->val;
  z = vector_alloc( n );   zval = z->val;

  /* Initialize */
  for( ip = 0; ip < n; ip++ )      /* initialize to the identiy matrix */
    { for( iq = 0; iq < n; iq ++ )
	MVal(vval,ip,iq) = 0.0;
      MVal(vval,ip,ip) = 1.0;
    }
  for( ip = 0; ip < n; ip++ )              /* initialize b and d to the */
    { VVal(bval,ip) = VVal(dval,ip) = MVal(mval,ip,ip) ; /* diagonal of msave */
      VVal(zval,ip) = 0.0;
    }
  nrot = 0;

  for( i = 0; i < 50; i++ )
    { 
      sm = 0.0;
      for( ip = 0; ip < n-1; ip++) 
	for( iq = ip+1; iq < n; iq++) sm += SYS_FABS(MVal(mval,ip,iq));

      if( sm == 0.0) 
	{ vector_free( b );
	  vector_free( z );
	  matrix_free( msave );
	  eigsort( eig_v, d );
	  return( MATH_SUCCESS );
	}

      if (i < 4) tresh = 0.2 * sm / (n * n);
      else       tresh = 0.0;

      for( ip = 0; ip < n-1;ip++) 
	for( iq = ip+1; iq < n; iq++) 
	  { g = 100.0 * SYS_FABS( MVal(mval,ip,iq) );

	    if ( (i > 4) && 
		((double) SYS_FABS(VVal(dval,ip))+g)==(double) SYS_FABS(VVal(dval,ip)) &&
		((double) SYS_FABS(VVal(dval,iq))+g)==(double) SYS_FABS(VVal(dval,iq)) )
	      { MVal(mval,ip,iq) = 0.0;
	      }
	    else if( SYS_FABS( MVal(mval,ip,iq) ) > tresh )
	      { h = VVal(dval,iq) - VVal(dval,ip);
                if( (double) (SYS_FABS(h) + g) == (double)SYS_FABS(h)) 
		  { t = ( MVal(mval,ip,iq) ) / h;
		  }
                else 
		  {  theta = 0.5 * h / ( MVal(mval,ip,iq) );
                     t     = 1.0 / (SYS_FABS(theta) + sqrt(1.0 + theta*theta));
                     if( theta < 0.0 ) t = -t;
		   }
                c   = 1.0 / sqrt( 1 + t*t);
                s   = t * c;
                tau = s / (1.0 + c);
                h   = t * MVal(mval,ip,iq);
                VVal(zval,ip) -= h;
                VVal(zval,iq) += h;
                VVal(dval,ip) -= h;
                VVal(dval,iq) += h;
                MVal( mval,ip,iq) = 0.0;

                for (j = 0;    j < ip; j++) ROTATE( mval,j, ip,j, iq);
                for (j = ip+1; j < iq; j++) ROTATE( mval,ip,j, j, iq);
                for (j = iq+1; j < n;  j++) ROTATE( mval,ip,j, iq,j);
                for (j = 0;    j < n;  j++) ROTATE( vval,j, ip,j, iq);
                ++nrot;
           }
        }
      
      for( ip = 0; ip < n; ip++ )
	{ VVal(bval,ip) += VVal(zval,ip);
	  VVal(dval,ip)  = VVal(bval,ip);
	  VVal(zval,ip)  = 0.0;
	}
    }
  printf(" jacobi: to many iterations in routine\n");
  return( MATH_WARNING );
}