OverSim
yang.cc
Go to the documentation of this file.
1 // classes for vectors and matrices
2 // From D. Yang: C++ and Object-Oriented Numeric Computing,
3 // Springer-Verlag, 2000
4 //
5 #include <iostream>
6 #include <cmath>
7 #include <cstdlib>
8 #include <ctime>
9 #include "yang.h"
10 
11 void error(const char* v) {
12  std::cout << v << "\n";
13  exit(1);
14 }
15 
16 // *********** definitions of members in class Vtr.
17 
18 Vtr::Vtr(int n, double* abd) {
19  ets = new double [lenth =n];
20  for (int i = 0; i < lenth; i++) ets[i]= *(abd +i);
21 }
22 
23 Vtr::Vtr(int n, double a) {
24  ets = new double [lenth =n];
25  for (int i = 0; i < lenth; i++) ets[i] = a;
26 }
27 
28 Vtr::Vtr(const Vtr & v) {
29  ets = new double [lenth = v.lenth];
30  for (int i = 0; i < lenth; i++) ets[i] = v[i];
31 }
32 
33 
34 
35 
36 
37 Vtr& Vtr::operator=(const Vtr& v) {
38  if (this != &v) {
39  if (lenth != v.lenth ) error("Vtr::op=: Error: Bad vector sizes");
40  for (int i = 0; i < lenth; i++) ets[i] = v[i];
41  }
42  return *this;
43 }
44 
45 Vtr & Vtr::operator+=(const Vtr& v) {
46  if (lenth != v.lenth ) error("bad vector sizes");
47  for (int i = 0; i < lenth; i++) ets[i] += v[i];
48  return *this;
49 }
50 
51 Vtr & Vtr::operator-=(const Vtr& v) {
52  if (lenth != v.lenth ) error("bad vtor sizes");
53  for (int i = 0; i < lenth; i++) ets[i] -= v[i];
54  return *this;
55 }
56 
57 Vtr operator+(const Vtr & v) { // usage: v1 = + v2;
58  return v;
59 }
60 
61 Vtr operator-(const Vtr& v) { // usage: v1 = - v2;
62  return Vtr(v.lenth) - v;
63 }
64 
65 Vtr operator+(const Vtr& v1, const Vtr & v2) { // v=v1+v2
66  if (v1.lenth != v2.lenth ) error("Vtr::op+: Error Bad vtor sizes");
67  Vtr sum = v1; // It would cause problem without copy constructor
68  sum += v2;
69  return sum;
70 }
71 
72 Vtr operator-(const Vtr& v1, const Vtr& v2) { // v=v1-v2
73 // if (v1.lenth != v2.lenth ) error("bad vtor sizes");
74  Vtr sum = v1; // It would cause problem without copy constructor
75  sum -= v2;
76  return sum;
77 }
78 
79 std::ostream& operator<<(std::ostream& s, const Vtr& v ) {
80  for (int i =0; i < v.lenth; i++ ) {
81  s << v[i] << " ";
82  if (i%10 == 9) s << "\n";
83  }
84  return s;
85 }
86 
87 double Vtr::twonorm() const{
88  double norm = std::abs(ets[0]);
89  for (int i = 1; i < lenth; i++) {
90  double vi = std::abs(ets[i]);
91  if (norm < 100) norm = std::sqrt(norm*norm + vi*vi);
92  else { // to avoid overflow for fn "sqrt" when norm is large
93  double tm = vi/norm;
94  norm *= std::sqrt(1.0 + tm*tm);
95  }
96  }
97  return norm;
98 }
99 
100 double Vtr::maxnorm() const {
101  double norm = std::abs(ets[0]);
102  for (int i = 1; i < lenth; i++)
103  if (norm < std::abs(ets[i])) norm = std::abs(ets[i]);
104  return norm;
105 }
106 
107 Vtr operator*(const double scalar, const Vtr & v) {
108  Vtr tm(v.lenth);
109  for (int i = 0; i < v.lenth; i++) tm[i] = scalar*v[i];
110  return tm;
111 }
112 
113 Vtr operator*(const Vtr & v1, const Vtr & v2) {
114  int sz = v1.lenth;
115  if (sz != v2.lenth ) error("bad vtor sizes");
116  Vtr tm(sz);
117  for (int i = 0; i < sz; i++)
118  tm[i] = v1[i]*v2[i];
119  return tm;
120 }
121 
122 Vtr operator/(const Vtr & v, const double scalar) {
123  if (scalar == 0) error("division by zero in vector-scalar division");
124  return (1.0/scalar)*v;
125 }
126 
127 double dot(const Vtr & v1, const Vtr & v2) {
128  int sz = v1.lenth;
129  if (sz != v2.lenth ) error("bad vtor sizes");
130  double tm = v1[0]*v2[0];
131  for (int i = 1; i < sz; i++) tm += v1[i]*v2[i];
132  return tm;
133 }
134 
135 // Matrix matrix
136 
137 Mtx::Mtx(int n, int m, double** dbp) { // construct from double pointer
138  nrows = n;
139  ncols = m;
140  ets = new double* [nrows];
141  for (int i = 0; i < nrows; i++) {
142  ets[i] = new double [ncols];
143  for (int j = 0; j < ncols; j++) ets[i][j] = dbp[i][j];
144  }
145 }
146 
147 Mtx::Mtx(int n, int m, double a) { // construct from a double
148  ets = new double* [nrows = n];
149  for (int i = 0; i< nrows; i++) {
150  ets[i] = new double [ncols = m];
151  for (int j = 0; j < ncols; j++) ets[i][j] = a;
152  }
153 }
154 
155 Mtx::Mtx(const Mtx & mat) { // copy constructor
156  ets = new double* [nrows = mat.nrows];
157  for (int i = 0; i< nrows; i++) {
158  ets[i] = new double [ncols = mat.ncols];
159  for (int j = 0; j < ncols; j++) ets[i][j] = mat[i][j];
160  }
161 }
162 
163 Mtx::~Mtx(){ // destructor
164  for (int i = 0; i< nrows; i++) delete[] ets[i];
165  delete[] ets;
166 }
167 
168 Mtx& Mtx::operator=(const Mtx& mat) { // copy assignment
169  if (this != &mat) {
170  if (nrows != mat.nrows || ncols != mat.ncols) error("bad matrix sizes");
171  for (int i = 0; i < nrows; i++)
172  for (int j = 0; j < ncols; j++) ets[i][j] = mat[i][j];
173  }
174  return *this;
175 }
176 
177 Mtx& Mtx::operator+=(const Mtx& mat) { // add-assign
178  if (nrows != mat.nrows || ncols != mat.ncols) error("bad matrix sizes");
179  for (int i = 0; i < nrows; i++)
180  for (int j = 0; j < ncols; j++) ets[i][j] += mat[i][j];
181  return *this;
182 }
183 
184 Mtx& Mtx::operator-=(const Mtx& mat) { // subtract-assign
185  if (nrows != mat.nrows || ncols != mat.ncols) error("bad matrix sizes");
186  for (int i = 0; i < nrows; i++)
187  for (int j = 0; j < ncols; j++) ets[i][j] -= mat[i][j];
188  return *this;
189 }
190 
191 Mtx& Mtx::operator+() { // usage: mat1 = + mat2;
192  return *this;
193 }
194 
195 Mtx operator-(const Mtx & mat) { // usage: mat1 = - mat2;
196  return Mtx(mat.nrows,mat.ncols) - mat;
197 }
198 
199 Mtx Mtx::operator+(const Mtx & mat) { // usage: m = m1 + m2
200  Mtx sum = *this; // user-defined copy constructor
201  sum += mat; // is important here
202  return sum; // otherwise m1 would be changed
203 }
204 
205 Vtr Mtx::operator*(const Vtr& v) const { // matrix-vector multiply
206  if (ncols != v.size())
207  error("Mtx::op*(Vtr): Error: Mat. and vec. sizes do not match.");
208  Vtr tm(nrows);
209  for (int i = 0; i < nrows; i++)
210  for (int j = 0; j < ncols; j++) tm[i] += ets[i][j]*v[j];
211  return tm;
212 }
213 
214 Vtr operator*(const Vtr& v, const Mtx& mat)
215 {
216  if (v.lenth != mat.nrows)
217  error("op*(Vtr, Mtx): Error: Mat. and vec. size do no match.");
218  Vtr res(mat.ncols, 0.0);
219  for (int i=0; i<mat.ncols; i++)
220  for (int j=0; j<v.lenth; j++)
221  res[i] = v.ets[j] * mat.ets[j][i];
222  return res;
223 }
224 
225 
226 Mtx operator-(const Mtx& m1, const Mtx& m2) { // matrix subtract
227  if(m1.nrows !=m2.nrows || m1.ncols !=m2.ncols)
228  error("bad matrix sizes");
229  Mtx sum = m1;
230  sum -= m2;
231  return sum;
232 }
233 
234 // Added by Peter Seidler
235 void Mtx::getcol(int n, Vtr& vec) const
236 {
237  if (vec.size() != nrows)
238  error("Mtx::getcol(): Bad vector size.");
239  for (int i = 0; i < nrows; i++)
240  vec[i] = ets[i][n];
241 }
242 
243 void Mtx::setcol(int n, const Vtr& vec)
244 {
245  if (vec.size() != nrows)
246  error("Mtx::getcol(): Bad vector size.");
247  for (int i = 0; i < nrows; i++)
248  ets[i][n] = vec[i];
249 }
250 
252 {
253  for (int i = 0; i < nrows; i++)
254  for (int j = 0; j < ncols; j++)
255  ets[i][j] = 0;
256 }
257 
258 int Mtx::transpose(Mat_DP& dest) const
259 {
260  if ((nrows != dest.cols()) || (ncols != dest.rows())) {
261  std::cerr << "Mtx::transpose(): Error: Matrix dim."
262  << std::endl;
263  return -1;
264  }
265 
266  for (int i=0; i<nrows; i++)
267  for (int j=0; j<ncols; j++)
268  dest(j, i) = ets[i][j];
269  return 0;
270 }
271 
272 std::ostream& operator<<(std::ostream& s, const Mtx& mat)
273 {
274  for (int i = 0; i < mat.rows(); i++) {
275  s << "| ";
276  for(int j = 0; j < mat.cols(); j++) {
277  s.setf(std::ios_base::fixed, std::ios_base::floatfield);
278  s.precision(4);
279  s.width(8);
280  s << mat.ets[i][j];
281  }
282  s << " |" << std::endl;
283  }
284  return s;
285 }
286 
287 Mtx Mtx::operator*(const Mtx& mat) const
288 {
289  Mtx tmp(nrows, mat.ncols);
290 
291  if (ncols != mat.nrows)
292  error("Mtx::op*=: Bad matrix sizes.");
293 
294  for (int i = 0; i < nrows; i++)
295  for (int j = 0; j < mat.ncols; j++)
296  for (int k = 0; k < ncols; k++)
297  tmp(i,j) += ets[i][k] * mat.ets[k][j];
298 
299  return tmp;
300 }
301 
302 int Mtx::QRdecomp(Mtx& Q, Mtx& R)
303 {
304  if ((Q.nrows != nrows) || (Q.ncols != ncols) ||
305  (R.nrows != ncols) || (R.ncols != ncols)) {
306  std::cerr << "Mtx::QRdecomp(): Error: Bad matrix size.";
307  return -1;
308  }
309 
310  double** tmp;
311  double norm, dot;
312 
313  // tmp = A transpose
314  int tmprows = ncols;
315  int tmpcols = nrows;
316  tmp = new double* [tmprows];
317  for (int i=0; i<tmprows; i++) {
318  tmp[i] = new double [tmpcols];
319  for (int j=0; j<tmpcols; j++)
320  tmp[i][j] = ets[j][i];
321  }
322  Mat_DP QT(tmprows,tmpcols);
323 
324  R.clear();
325 
326  for (int i=0; i<tmprows; i++) {
327  norm = 0;
328  for (int k=0; k<tmpcols; k++)
329  norm += tmp[i][k]*tmp[i][k];
330  norm = std::sqrt(norm);
331  R.ets[i][i] = norm;
332  for (int k=0; k<tmpcols; k++)
333  QT.ets[i][k] = tmp[i][k] / norm;
334 
335  for (int j=i+1; j<tmprows; j++) {
336  dot = 0;
337  for (int k=0; k<tmpcols; k++)
338  dot += QT.ets[i][k]*tmp[j][k];
339  R.ets[i][j] = dot;
340  for (int k=0; k<tmpcols; k++)
341  tmp[j][k] = tmp[j][k] - dot*QT.ets[i][k];
342  }
343  }
344 
345  QT.transpose(Q);
346 
347  for (int i=0; i<tmprows; i++)
348  delete[] tmp[i];
349  return 0;
350 }
351 
353 {
354  if ((Q.nrows != nrows) || (Q.ncols != ncols) ||
355  (R.nrows != ncols) || (R.ncols != ncols)) {
356  std::cerr << "Mtx::QRdecomp(): Error: Bad matrix size.";
357  return -1;
358  }
359 
360  double** tmp;
361  double norm, dot;
362 
363  tmp = new double* [nrows];
364  for (int i=0; i<nrows; i++) {
365  tmp[i] = new double [ncols];
366  for (int j=0; j<ncols; j++)
367  tmp[i][j] = ets[i][j];
368  }
369 
370  R.clear();
371 
372  for (int i=0; i<ncols; i++) {
373  norm = 0;
374  for (int k=0; k<nrows; k++)
375  norm += tmp[k][i]*tmp[k][i];
376  norm = std::sqrt(norm);
377  R.ets[i][i] = norm;
378  for (int k=0; k<nrows; k++)
379  Q.ets[k][i] = tmp[k][i] / norm;
380 
381  for (int j=i+1; j<ncols; j++) {
382  dot = 0;
383  for (int k=0; k<nrows; k++)
384  dot += Q.ets[k][i]*tmp[k][j];
385  R.ets[i][j] = dot;
386  for (int k=0; k<nrows; k++)
387  tmp[k][j] = tmp[k][j] - dot*Q.ets[k][i];
388  }
389  }
390 
391  for (int i=0; i<nrows; i++)
392  delete[] tmp[i];
393  return 0;
394 }
395 
396