yang.cc

Go to the documentation of this file.
00001 // classes for vectors and matrices
00002 // From D. Yang: C++ and Object-Oriented Numeric Computing,
00003 // Springer-Verlag, 2000
00004 //
00005 #include <iostream>
00006 #include <cmath>
00007 #include <cstdlib>
00008 #include <ctime>
00009 #include "yang.h"
00010 
00011 void error(const char* v) {
00012   std::cout << v << "\n";
00013   exit(1);
00014 }
00015 
00016 // ***********  definitions of members in class Vtr.
00017 
00018 Vtr::Vtr(int n, double* abd) {
00019   ets = new double [lenth =n];
00020   for (int i = 0; i < lenth; i++)  ets[i]= *(abd +i);
00021 }
00022 
00023 Vtr::Vtr(int n, double a) {
00024   ets = new double [lenth =n];
00025   for (int i = 0; i < lenth; i++)  ets[i] = a;
00026 }
00027 
00028 Vtr::Vtr(const Vtr & v) {
00029   ets = new double [lenth = v.lenth];
00030   for (int i = 0; i < lenth; i++)  ets[i] = v[i];
00031 }
00032 
00033 
00034 
00035 
00036 
00037 Vtr& Vtr::operator=(const Vtr& v) {
00038   if (this != &v) {
00039     if (lenth != v.lenth ) error("Vtr::op=: Error: Bad vector sizes");
00040     for (int i = 0; i < lenth; i++) ets[i] = v[i];
00041   }
00042   return *this;
00043 }
00044 
00045 Vtr & Vtr::operator+=(const Vtr& v) {
00046   if (lenth != v.lenth ) error("bad vector sizes");
00047   for (int i = 0; i < lenth; i++) ets[i] += v[i];
00048   return *this;
00049 }
00050 
00051 Vtr & Vtr::operator-=(const Vtr& v) {
00052   if (lenth != v.lenth ) error("bad vtor sizes");
00053   for (int i = 0; i < lenth; i++) ets[i] -= v[i];
00054   return *this;
00055 }
00056 
00057 Vtr operator+(const Vtr & v) {  // usage: v1 = + v2;
00058   return v;
00059 }
00060 
00061 Vtr operator-(const Vtr& v) {    // usage: v1 = - v2;
00062   return Vtr(v.lenth) - v;
00063 }
00064 
00065 Vtr operator+(const Vtr& v1, const Vtr & v2) {          // v=v1+v2
00066   if (v1.lenth != v2.lenth ) error("Vtr::op+: Error Bad vtor sizes");
00067   Vtr sum = v1; // It would cause problem without copy constructor
00068   sum += v2;
00069   return sum;
00070 }
00071 
00072 Vtr operator-(const Vtr& v1, const Vtr& v2) { // v=v1-v2
00073 //  if (v1.lenth != v2.lenth ) error("bad vtor sizes");
00074   Vtr sum = v1; // It would cause problem without copy constructor
00075   sum -= v2;
00076   return sum;
00077 }
00078 
00079 std::ostream&  operator<<(std::ostream& s, const Vtr& v ) {
00080   for (int i =0; i < v.lenth; i++ ) {
00081     s << v[i] << "  ";
00082     if (i%10 == 9) s << "\n";
00083   }
00084   return s;
00085 }
00086 
00087 double Vtr::twonorm() const{
00088   double norm = std::abs(ets[0]);
00089   for (int i = 1; i < lenth; i++) {
00090     double vi = std::abs(ets[i]);
00091     if (norm < 100) norm = std::sqrt(norm*norm + vi*vi);
00092     else {  // to avoid overflow for fn "sqrt" when norm is large
00093       double tm = vi/norm;
00094       norm *= std::sqrt(1.0 + tm*tm);
00095     }
00096   }
00097   return norm;
00098 }
00099 
00100 double Vtr::maxnorm() const {
00101   double norm = std::abs(ets[0]);
00102   for (int i = 1; i < lenth; i++)
00103     if (norm < std::abs(ets[i])) norm = std::abs(ets[i]);
00104   return norm;
00105 }
00106 
00107 Vtr operator*(const double scalar, const Vtr & v) {
00108   Vtr tm(v.lenth);
00109   for (int i = 0; i < v.lenth; i++) tm[i] = scalar*v[i];
00110   return tm;
00111 }
00112 
00113 Vtr operator*(const Vtr & v1, const Vtr & v2) {
00114   int sz = v1.lenth;
00115   if (sz != v2.lenth ) error("bad vtor sizes");
00116   Vtr tm(sz);
00117   for (int i = 0; i < sz; i++)
00118       tm[i] = v1[i]*v2[i];
00119   return tm;
00120 }
00121 
00122 Vtr operator/(const Vtr & v, const double scalar) {
00123   if (scalar == 0) error("division by zero in vector-scalar division");
00124   return (1.0/scalar)*v;
00125 }
00126 
00127 double dot(const Vtr & v1, const Vtr & v2) {
00128   int sz = v1.lenth;
00129   if (sz != v2.lenth ) error("bad vtor sizes");
00130   double tm = v1[0]*v2[0];
00131   for (int i = 1; i < sz; i++) tm += v1[i]*v2[i];
00132   return tm;
00133 }
00134 
00135 // Matrix matrix
00136 
00137 Mtx::Mtx(int n, int m, double** dbp) {         // construct from double pointer
00138   nrows = n;
00139   ncols = m;
00140   ets = new double* [nrows];
00141   for (int i =  0; i < nrows; i++) {
00142     ets[i] = new double [ncols];
00143     for (int j = 0; j < ncols; j++) ets[i][j] = dbp[i][j];
00144   }
00145 }
00146 
00147 Mtx::Mtx(int n, int m, double a) {              // construct from a double
00148   ets = new double* [nrows = n];
00149   for (int i =  0; i< nrows; i++) {
00150     ets[i] = new double [ncols = m];
00151     for (int j = 0; j < ncols; j++) ets[i][j] = a;
00152   }
00153 }
00154 
00155 Mtx::Mtx(const Mtx & mat) {                      // copy constructor
00156   ets = new double* [nrows = mat.nrows];
00157   for (int i =  0; i< nrows; i++) {
00158     ets[i] = new double [ncols = mat.ncols];
00159     for (int j = 0; j < ncols; j++) ets[i][j] = mat[i][j];
00160   }
00161 }
00162 
00163 Mtx::~Mtx(){                                    // destructor
00164   for (int i = 0; i< nrows; i++) delete[]  ets[i];
00165   delete[] ets;
00166 }
00167 
00168 Mtx& Mtx::operator=(const Mtx& mat) {           // copy assignment
00169   if (this != &mat) {
00170     if (nrows != mat.nrows || ncols != mat.ncols) error("bad matrix sizes");
00171     for (int i = 0; i < nrows; i++)
00172       for (int j = 0; j < ncols; j++) ets[i][j]  = mat[i][j];
00173   }
00174   return *this;
00175 }
00176 
00177 Mtx& Mtx::operator+=(const Mtx&  mat) {         // add-assign
00178   if (nrows != mat.nrows || ncols != mat.ncols) error("bad matrix sizes");
00179   for (int i = 0; i < nrows; i++)
00180     for (int j = 0; j < ncols; j++) ets[i][j] += mat[i][j];
00181   return *this;
00182 }
00183 
00184 Mtx& Mtx::operator-=(const Mtx&  mat) {         // subtract-assign
00185   if (nrows != mat.nrows || ncols != mat.ncols) error("bad matrix sizes");
00186   for (int i = 0; i < nrows; i++)
00187     for (int j = 0; j < ncols; j++) ets[i][j] -= mat[i][j];
00188   return *this;
00189 }
00190 
00191 Mtx& Mtx::operator+() {                         // usage: mat1 = + mat2;
00192   return *this;
00193 }
00194 
00195 Mtx operator-(const Mtx &  mat) {               // usage: mat1 = - mat2;
00196   return Mtx(mat.nrows,mat.ncols) - mat;
00197 }
00198 
00199 Mtx Mtx::operator+(const Mtx & mat) {           // usage: m = m1 + m2
00200  Mtx sum = *this;                               // user-defined copy constructor
00201  sum += mat;                                    // is important here
00202  return sum;                                    // otherwise m1 would be changed
00203 }
00204 
00205 Vtr Mtx::operator*(const Vtr& v) const {        // matrix-vector multiply
00206   if (ncols != v.size())
00207           error("Mtx::op*(Vtr): Error: Mat. and vec. sizes do not match.");
00208   Vtr tm(nrows);
00209   for (int i = 0; i < nrows; i++)
00210     for (int j = 0; j < ncols; j++) tm[i] += ets[i][j]*v[j];
00211   return tm;
00212 }
00213 
00214 Vtr operator*(const Vtr& v, const Mtx& mat)
00215 {
00216         if (v.lenth != mat.nrows)
00217                 error("op*(Vtr, Mtx): Error: Mat. and vec. size do no match.");
00218         Vtr res(mat.ncols, 0.0);
00219         for (int i=0; i<mat.ncols; i++)
00220                 for (int j=0; j<v.lenth; j++)
00221                         res[i] = v.ets[j] * mat.ets[j][i];
00222         return res;
00223 }
00224 
00225 
00226 Mtx operator-(const Mtx& m1, const Mtx&  m2) {  // matrix subtract
00227  if(m1.nrows !=m2.nrows || m1.ncols !=m2.ncols)
00228    error("bad matrix sizes");
00229  Mtx sum = m1;
00230  sum -= m2;
00231  return sum;
00232 }
00233 
00234 // Added by Peter Seidler
00235 void Mtx::getcol(int n, Vtr& vec) const
00236 {
00237         if (vec.size() != nrows)
00238                 error("Mtx::getcol(): Bad vector size.");
00239         for (int i = 0; i < nrows; i++)
00240                 vec[i] = ets[i][n];
00241 }
00242 
00243 void Mtx::setcol(int n, const Vtr& vec)
00244 {
00245         if (vec.size() != nrows)
00246                 error("Mtx::getcol(): Bad vector size.");
00247         for (int i = 0; i < nrows; i++)
00248                 ets[i][n] = vec[i];
00249 }
00250 
00251 void Mtx::clear()
00252 {
00253         for (int i = 0; i < nrows; i++)
00254                 for (int j = 0; j < ncols; j++)
00255                         ets[i][j] = 0;
00256 }
00257 
00258 int Mtx::transpose(Mat_DP& dest) const
00259 {
00260         if ((nrows != dest.cols()) || (ncols != dest.rows())) {
00261                 std::cerr << "Mtx::transpose(): Error: Matrix dim."
00262                           << std::endl;
00263                 return -1;
00264         }
00265 
00266         for (int i=0; i<nrows; i++)
00267                 for (int j=0; j<ncols; j++)
00268                         dest(j, i) = ets[i][j];
00269         return 0;
00270 }
00271 
00272 std::ostream& operator<<(std::ostream& s, const Mtx& mat)
00273 {
00274         for (int i = 0; i < mat.rows(); i++) {
00275                 s << "| ";
00276                 for(int j = 0; j < mat.cols(); j++) {
00277                         s.setf(std::ios_base::fixed, std::ios_base::floatfield);
00278                         s.precision(4);
00279                         s.width(8);
00280                         s << mat.ets[i][j];
00281                 }
00282                 s << " |" << std::endl;
00283         }
00284         return s;
00285 }
00286 
00287 Mtx Mtx::operator*(const Mtx& mat) const
00288 {
00289         Mtx tmp(nrows, mat.ncols);
00290 
00291         if (ncols != mat.nrows)
00292                 error("Mtx::op*=: Bad matrix sizes.");
00293 
00294         for (int i = 0; i < nrows; i++)
00295                 for (int j = 0; j < mat.ncols; j++)
00296                         for (int k = 0; k < ncols; k++)
00297                                 tmp(i,j) += ets[i][k] * mat.ets[k][j];
00298 
00299         return tmp;
00300 }
00301 
00302 int Mtx::QRdecomp(Mtx& Q, Mtx& R)
00303 {
00304         if ((Q.nrows != nrows) || (Q.ncols != ncols) ||
00305             (R.nrows != ncols) || (R.ncols != ncols))   {
00306                 std::cerr << "Mtx::QRdecomp(): Error: Bad matrix size.";
00307                 return -1;
00308         }
00309 
00310         double** tmp;
00311         double norm, dot;
00312 
00313         // tmp = A transpose
00314         int tmprows = ncols;
00315         int tmpcols = nrows;
00316         tmp = new double* [tmprows];
00317         for (int i=0; i<tmprows; i++) {
00318                 tmp[i] = new double [tmpcols];
00319                 for (int j=0; j<tmpcols; j++)
00320                         tmp[i][j] = ets[j][i];
00321         }
00322         Mat_DP QT(tmprows,tmpcols);
00323 
00324         R.clear();
00325 
00326         for (int i=0; i<tmprows; i++) {
00327                 norm = 0;
00328                 for (int k=0; k<tmpcols; k++)
00329                         norm += tmp[i][k]*tmp[i][k];
00330                 norm = std::sqrt(norm);
00331                 R.ets[i][i] = norm;
00332                 for (int k=0; k<tmpcols; k++)
00333                         QT.ets[i][k] = tmp[i][k] / norm;
00334 
00335                 for (int j=i+1; j<tmprows; j++) {
00336                         dot = 0;
00337                         for (int k=0; k<tmpcols; k++)
00338                                 dot += QT.ets[i][k]*tmp[j][k];
00339                         R.ets[i][j] = dot;
00340                         for (int k=0; k<tmpcols; k++)
00341                                 tmp[j][k] = tmp[j][k] - dot*QT.ets[i][k];
00342                 }
00343         }
00344 
00345         QT.transpose(Q);
00346 
00347         for (int i=0; i<tmprows; i++)
00348                 delete[] tmp[i];
00349         return 0;
00350 }
00351 
00352 int Mtx::QRdecomp_slow(Mtx& Q, Mtx& R)
00353 {
00354         if ((Q.nrows != nrows) || (Q.ncols != ncols) ||
00355             (R.nrows != ncols) || (R.ncols != ncols))   {
00356                 std::cerr << "Mtx::QRdecomp(): Error: Bad matrix size.";
00357                 return -1;
00358         }
00359 
00360         double** tmp;
00361         double norm, dot;
00362 
00363         tmp = new double* [nrows];
00364         for (int i=0; i<nrows; i++) {
00365                 tmp[i] = new double [ncols];
00366                 for (int j=0; j<ncols; j++)
00367                         tmp[i][j] = ets[i][j];
00368         }
00369 
00370         R.clear();
00371 
00372         for (int i=0; i<ncols; i++) {
00373                 norm = 0;
00374                 for (int k=0; k<nrows; k++)
00375                         norm += tmp[k][i]*tmp[k][i];
00376                 norm = std::sqrt(norm);
00377                 R.ets[i][i] = norm;
00378                 for (int k=0; k<nrows; k++)
00379                         Q.ets[k][i] = tmp[k][i] / norm;
00380 
00381                 for (int j=i+1; j<ncols; j++) {
00382                         dot = 0;
00383                         for (int k=0; k<nrows; k++)
00384                                 dot += Q.ets[k][i]*tmp[k][j];
00385                         R.ets[i][j] = dot;
00386                         for (int k=0; k<nrows; k++)
00387                                 tmp[k][j] = tmp[k][j] - dot*Q.ets[k][i];
00388                 }
00389         }
00390 
00391         for (int i=0; i<nrows; i++)
00392                 delete[] tmp[i];
00393         return 0;
00394 }
00395 
00396 
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3