_matrix.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:7k
开发平台:

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _matrix.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. #include <LEDA/matrix.h>
  12. #include <math.h>
  13. #define EPSILON 1e-12
  14. //------------------------------------------------------------------------------
  15. //  matrix member functions
  16. //------------------------------------------------------------------------------
  17. void matrix::flip_rows(int i,int j)
  18. { vector* p = v[i];
  19.   v[i] = v[j];
  20.   v[j] = p;
  21.  }
  22. matrix::matrix(int dim1, int dim2)  
  23. {
  24.   if (dim1<0 || dim2<0) 
  25.   error_handler(1,"matrix: negative dimension."); 
  26.   d1=dim1; 
  27.   d2=dim2; 
  28.   if (d1 > 0) 
  29.   { v = new vector*[d1];
  30.     for (int i=0;i<d1;i++) v[i] = new vector(d2); 
  31.    }
  32.   else v = nil;
  33. }
  34. matrix::matrix(const matrix& p)  
  35.   d1 = p.d1;
  36.   d2 = p.d2;
  37.     
  38.   if (d1 > 0) 
  39.   { v = new vector*[d1];
  40.     for (int i=0;i<d1;i++) v[i] = new vector(*p.v[i]); 
  41.    }
  42.   else v = nil;
  43. }
  44. matrix::matrix(int dim1, int dim2, double** p)  
  45. { d1=dim1; 
  46.   d2=dim2; 
  47.   v = new vector*[d1];
  48.   for(int i=0;i<d1;i++) 
  49.   { v[i] = new vector(d2); 
  50.     for(int j=0;j<d2;j++) elem(i,j) = p[i][j];
  51.    }
  52.  }
  53. matrix::~matrix()  
  54. { if (v) 
  55.   { while(d1--) delete v[d1]; 
  56.     delete v;
  57.    }
  58. }
  59. void matrix::check_dimensions(const matrix& mat) const
  60. { if (d1 != mat.d1 || d2 != mat.d2)
  61.    error_handler(1,"incompatible matrix types.");
  62.  }
  63. matrix::matrix(const vector& vec)
  64. { d1 = vec.d;
  65.   d2 = 1;
  66.   v = new vector*[d1];
  67.   for(int i=0; i<d1; i++)
  68.   { v[i] = new vector(1);
  69.     elem(i,0) = vec[i];
  70.    }
  71.     
  72. }
  73. matrix& matrix::operator=(const matrix& mat)
  74. { register int i,j;
  75.   if (d1 != mat.d1 || d2 != mat.d2)
  76.   { for(i=0;i<d1;i++) delete v[i];
  77.     delete v;
  78.     d1 = mat.d1;
  79.     d2 = mat.d2;
  80.     v = new vector*[d1];
  81.     for(i=0;i<d1;i++) v[i] = new vector(d2);
  82.    }
  83.   for(i=0;i<d1;i++)
  84.     for(j=0;j<d2;j++) elem(i,j) = mat.elem(i,j);
  85.   return *this;
  86. }
  87. int matrix::operator==(const matrix& x) const
  88. { register int i,j;
  89.   if (d1 != x.d1 || d2 != x.d2) return false;
  90.   for(i=0;i<d1;i++)
  91.     for(j=0;j<d2;j++)
  92.       if (elem(i,j) != x.elem(i,j)) return false;
  93.   return true;
  94.  }
  95. vector& matrix::row(int i) const
  96. { if ( i<0 || i>=d1 )  error_handler(1,"matrix: row index out of range");
  97.    return *v[i];
  98. }
  99. double& matrix::operator()(int i, int j)
  100. { if ( i<0 || i>=d1 )  error_handler(1,"matrix: row index out of range");
  101.   if ( j<0 || j>=d2 )  error_handler(1,"matrix: col index out of range");
  102.   return elem(i,j);
  103. }
  104. double matrix::operator()(int i, int j) const
  105. { if ( i<0 || i>=d1 )  error_handler(1,"matrix: row index out of range");
  106.   if ( j<0 || j>=d2 )  error_handler(1,"matrix: col index out of range");
  107.   return elem(i,j);
  108. }
  109. vector matrix::col(int i)  const
  110. { if ( i<0 || i>=d2 )  error_handler(1,"matrix: col index out of range");
  111.   vector result(d1);
  112.   int j = d1;
  113.   while (j--) result.v[j] = elem(j,i);
  114.   return result;
  115. }
  116. matrix::operator vector() const
  117. { if (d2!=1) 
  118.    error_handler(1,"error: cannot make vector from matrixn");
  119.   return col(0);
  120. }
  121. matrix matrix::operator+(const matrix& mat)
  122. { register int i,j;
  123.   check_dimensions(mat);
  124.   matrix result(d1,d2);
  125.   for(i=0;i<d1;i++)
  126.    for(j=0;j<d2;j++)
  127.       result.elem(i,j) = elem(i,j) + mat.elem(i,j);
  128.   return result;
  129. }
  130. matrix& matrix::operator+=(const matrix& mat) 
  131. { register int i,j;
  132.   check_dimensions(mat);
  133.   for(i=0;i<d1;i++)
  134.    for(j=0;j<d2;j++)
  135.       elem(i,j) += mat.elem(i,j);
  136.   return *this;
  137. }
  138. matrix& matrix::operator-=(const matrix& mat) 
  139. { register int i,j;
  140.   check_dimensions(mat);
  141.   for(i=0;i<d1;i++)
  142.    for(j=0;j<d2;j++)
  143.       elem(i,j) -= mat.elem(i,j);
  144.   return *this;
  145. }
  146. matrix matrix::operator-(const matrix& mat)
  147. { register int i,j;
  148.   check_dimensions(mat);
  149.   matrix result(d1,d2);
  150.   for(i=0;i<d1;i++)
  151.    for(j=0;j<d2;j++)
  152.       result.elem(i,j) = elem(i,j) - mat.elem(i,j);
  153.   return result;
  154. }
  155. matrix matrix::operator-()  // unary
  156. { register int i,j;
  157.   matrix result(d1,d2);
  158.   for(i=0;i<d1;i++)
  159.    for(j=0;j<d2;j++)
  160.       result.elem(i,j) = -elem(i,j);
  161.   return result;
  162. }
  163. matrix matrix::operator*(double f)
  164. { register int i,j;
  165.   matrix result(d1,d2);
  166.   for(i=0;i<d1;i++)
  167.    for(j=0;j<d2;j++)
  168.       result.elem(i,j) = elem(i,j) *f;
  169.   return result;
  170. }
  171. matrix matrix::operator*(const matrix& mat)
  172. { if (d2!=mat.d1)
  173.      error_handler(1,"matrix multiplication: incompatible matrix typesn");
  174.   
  175.   matrix result(d1, mat.d2);
  176.   register int i,j;
  177.   for (i=0;i<mat.d2;i++)
  178.   for (j=0;j<d1;j++) result.elem(j,i) = *v[j] * mat.col(i);
  179.  return result;
  180. }
  181. double matrix::det() const
  182. {
  183.  if (d1!=d2)  
  184.    error_handler(1,"matrix::det: matrix not quadratic.n");
  185.  int n = d1;
  186.  matrix M(n,1);
  187.  int flips;
  188.  double** A = triang(M,flips);
  189.  if (A == NULL)  return 0;
  190.  double Det = 1;
  191.  int i;
  192.  for(i=0;i<n;i++) Det *= A[i][i];
  193.  for(i=0;i<n;i++) delete A[i];
  194.  delete A;
  195.  return (flips % 2) ? -Det : Det;
  196. }
  197. double** matrix::triang(const matrix& M, int& flips)  const
  198. {
  199.  register double **p, **q;
  200.  register double *l, *r, *s;
  201.  register double pivot_el,tmp;
  202.  register int i,j, col, row;
  203.  int n = d1;
  204.  int d = M.d2;
  205.  int m = n+d;
  206.  double** A = new double*[n];
  207.  p = A;
  208.  for(i=0;i<n;i++) 
  209.  { *p = new double[m];
  210.    l = *p++;
  211.    for(j=0;j<n;j++) *l++ = elem(i,j);
  212.    for(j=0;j<d;j++) *l++ = M.elem(i,j);
  213.   }
  214.  flips = 0;
  215.  for (col=0, row=0; row<n; row++, col++)
  216.  { 
  217.    // search for row j with maximal absolute entry in current col
  218.    j = row;
  219.    for (i=row+1; i<n; i++)
  220.      if (fabs(A[j][col]) < fabs(A[i][col])) j = i;
  221.    if ( n > j && j > row) 
  222.    { double* p = A[j];
  223.      A[j] = A[row];
  224.      A[row] = p;
  225.      flips++;
  226.     }
  227.    tmp = A[row][col];
  228.    q  = &A[row];
  229.    if (fabs(tmp) < EPSILON) // matrix has not full rank
  230.    { p = A;
  231.      for(i=0;i<n;i++) delete A[i];
  232.      delete A;
  233.      return NULL;
  234.     }
  235.    for (p = &A[n-1]; p != q; p--)
  236.    { 
  237.      l = *p+col;
  238.      s = *p+m;
  239.      r = *q+col;
  240.      if (*l != 0.0)
  241.      { pivot_el = *l/tmp;
  242.         while(l < s) *l++ -= *r++ * pivot_el;
  243.       }
  244.     }
  245.   }
  246.  return A;
  247. }
  248. matrix matrix::inv() const
  249. {
  250.  if (d1!=d2)  
  251.      error_handler(1,"matrix::inv: matrix not quadratic.n");
  252.  int n = d1;
  253.  matrix I(n,n);
  254.  for(int i=0; i<n; i++) I(i,i) = 1;
  255.  return solve(I);
  256. }
  257. matrix matrix::solve(const matrix& M) const
  258. {
  259. if (d1 != d2 || d1 != M.d1)
  260.      error_handler(1, "Solve: wrong dimensionsn");
  261.  register double **p, ** q;
  262.  register double *l, *r, *s;
  263.  int      n = d1;
  264.  int      d = M.d2;
  265.  int      m = n+d;
  266.  int      row, col,i;
  267.  double** A = triang(M,i);
  268.  if (A == NULL) 
  269.    error_handler(1,"matrix::solve: matrix has not full rank.");
  270.  for (col = n-1, p = &A[n-1]; col>=0; p--, col--)
  271.  { 
  272.    s = *p+m;
  273.    double tmp = (*p)[col];
  274.    for(l=*p+n; l < s; l++) *l /=tmp;
  275.    for(q = A; q != p; q++ )
  276.    { tmp = (*q)[col];
  277.      l = *q+n;
  278.      r = *p+n;
  279.      while(r < s)  *l++ -= *r++ * tmp;
  280.     }
  281.                  
  282.   } 
  283.   matrix result(n,d);
  284.   for(row=0; row<n; row++)
  285.   { l = A[row]+n;
  286.     for(col=0; col<d; col++) result.elem(row,col) = *l++;
  287.     delete A[row];
  288.    }
  289.   delete A;
  290.   return result;
  291. }
  292. matrix matrix::trans() const
  293. { matrix result(d2,d1);
  294.   for(int i = 0; i < d2; i++)
  295.     for(int j = 0; j < d1; j++)
  296.       result.elem(i,j) = elem(j,i);
  297.   return result;
  298. }
  299.      
  300. ostream& operator<<(ostream& s, const matrix& M)
  301. { int i;
  302.   s <<"n";
  303.   for (i=0;i<M.d1;i++) s << M[i] << "n"; 
  304.   return s;
  305. }
  306. istream& operator>>(istream& s, matrix& M)
  307. { int i=0;
  308.   while (i<M.d1 && s >> M[i++]);
  309.   return s;
  310. }