My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matvec.cpp
Go to the documentation of this file.
1 /*
2  * matvec.cpp - matrix vector class implementation
3  *
4  * Copyright (C) 2004-2009 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: matvec.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <assert.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34 
35 #include "logging.h"
36 #include "object.h"
37 #include "complex.h"
38 #include "vector.h"
39 #include "matrix.h"
40 #include "matvec.h"
41 
42 #if !HAVE_STRCHR
43 # define strchr index
44 # define strrchr rindex
45 #endif
46 
47 // Constructor creates an unnamed instance of the matvec class.
49  size = 0;
50  rows = cols = 0;
51  name = NULL;
52  data = NULL;
53 }
54 
55 /* Constructor creates an unnamed instance of the matvec class with a
56  certain number of empty matrices. */
57 matvec::matvec (int length, int r, int c) {
58  size = length;
59  rows = r;
60  cols = c;
61  name = NULL;
62  if (size > 0) {
63  data = new matrix[size];
64  for (int i = 0; i < size; i++) data[i] = matrix (r, c);
65  } else {
66  data = NULL;
67  }
68 }
69 
70 /* The copy constructor creates a new instance based on the given
71  matvec object. */
72 matvec::matvec (const matvec & m) {
73  size = m.size;
74  rows = m.rows;
75  cols = m.cols;
76  name = m.name ? strdup (m.name) : NULL;
77  data = NULL;
78 
79  // copy matvec elements
80  if (size > 0) {
81  data = new matrix[size];
82  for (int i = 0; i < size; i++) data[i] = m.data[i];
83  }
84 }
85 
86 // Destructor deletes a matvec object.
88  if (name) free (name);
89  if (data) delete[] data;
90 }
91 
92 // Sets the name of the matvec object.
93 void matvec::setName (const char * n) {
94  if (name) free (name);
95  name = n ? strdup (n) : NULL;
96 }
97 
98 // Returns the name of the matvec object.
99 char * matvec::getName (void) {
100  return name;
101 }
102 
103 /* This function saves the given vector to the matvec object with the
104  appropriate matrix indices. */
105 void matvec::set (vector v, int r, int c) {
106  assert (v.getSize () == size &&
107  r >= 0 && r < rows && c >= 0 && c < cols);
108  for (int i = 0; i < size; i++) data[i].set (r, c, v.get (i));
109 }
110 
111 /* The function returns the vector specified by the given matrix
112  indices. If the matrix vector has a valid name 'A' the returned
113  vector gets the name 'A[r,c]'. */
114 vector matvec::get (int r, int c) {
115  assert (r >= 0 && r < rows && c >= 0 && c < cols);
116  vector res;
117  for (int i = 0; i < size; i++) res.add (data[i].get (r, c));
118  if (name != NULL) {
119  res.setName (createMatrixString (name, r, c));
120  }
121  return res;
122 }
123 
124 /* This function returns a static text representation with the
125  'n[r,c]' scheme indicating a matrix (vector) entry. */
126 char * matvec::createMatrixString (const char * n, int r, int c) {
127  static char str[256]; // hopefully enough
128  sprintf (str, "%s[%d,%d]", n, r + 1, c + 1);
129  return str;
130 }
131 
132 /* This function also returns a static text representation with the
133  'n[r,c]' scheme indicating a matrix (vector) entry but with
134  different arguments. */
135 char * matvec::createMatrixString (char n, int r, int c) {
136  static char str[256]; // hopefully enough
137  sprintf (str, "%c[%d,%d]", n, r + 1, c + 1);
138  return str;
139 }
140 
141 /* The function investigates the given vectors name. If this name
142  matches the 'n[r,c]' pattern it returns the name 'n' and saves the
143  row and column indices as well. The caller is responsible to
144  'free()' the returned string. If the vectors name does not match
145  the pattern the function returns NULL. */
146 char * matvec::isMatrixVector (char * n, int& r, int& c) {
147  char * p; int len;
148  if (n == NULL) return NULL; // nothing todo here
149  if ((p = strchr (n, '[')) != NULL) { // find first '['
150  r = atoi (p + 1) - 1; // get first index
151  if ((p = strchr (p, ',')) != NULL) { // find the ','
152  c = atoi (p + 1) - 1; // get second index
153  if ((p = strchr (p, ']')) != NULL) { // find trailing ']'
154  if (p[1] == '\0') { // identifier must end in ']'
155  // parse actual identifier
156  if ((len = strchr (n, '[') - n) > 0) {
157  p = (char *) malloc (len + 1);
158  memcpy (p, n, len);
159  p[len] = '\0';
160  return p;
161  }
162  }
163  }
164  }
165  }
166  return NULL;
167 }
168 
169 /* This function looks through the vector list given in `data' to find
170  matrix entries specified by `name' and returns the matrix vector
171  dimensions. */
173  int& rs, int& cs, int& ss) {
174  vector * v;
175  char * vn, * n;
176  int r, c, s;
177  rs = cs = ss = -1;
178  // go through vector list
179  for (v = data; v != NULL; v = (vector *) v->getNext ()) {
180  vn = v->getName ();
181  // requested matrix name found?
182  if (strstr (vn, name) == vn) {
183  if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) {
184  if (rs < r) rs = r;
185  if (cs < c) cs = c;
186  s = v->getSize ();
187  if (ss < s) ss = s;
188  free (n);
189  }
190  }
191  }
192 }
193 
194 /* This function looks through the vector list given in `data' to find
195  matrix entries specified by `name' and returns a matrix vector
196  object. If there are no such matrices the function returns
197  NULL. */
199 
200  // obtain matrix vector dimensions
201  int rs, cs, ss;
202  getMatrixVectorSize (data, name, rs, cs, ss);
203 
204  vector * v;
205  char * vn, * n;
206  int r, c;
207  // valid matrix entries found
208  if (rs >= 0 && cs >= 0 && ss > 0) {
209  // create matrix vector
210  matvec * mv = new matvec (ss, rs + 1, cs + 1);
211  mv->setName (name);
212  // go through vector list again and fill in matrix vectors
213  for (v = data; v; v = (vector *) v->getNext ()) {
214  vn = v->getName ();
215  if (strstr (vn, name) == vn) {
216  if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) {
217  mv->set (*v, r, c);
218  free (n);
219  }
220  }
221  }
222  return mv;
223  }
224  return NULL;
225 }
226 
227 /* This function saves the given matrix in the matrix vector at the
228  specified position. */
229 void matvec::set (matrix m, int idx) {
230  assert (m.getRows () == rows && m.getCols () == cols &&
231  idx >= 0 && idx < size);
232  data[idx] = m;
233 }
234 
235 /* The function returns the matrix stored within the matrix vector at
236  the given position. */
237 matrix matvec::get (int idx) {
238  assert (idx >= 0 && idx < size);
239  matrix res (data[idx]);
240  return res;
241 }
242 
243 // Matrix vector addition.
245  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols () &&
246  a.getSize () == b.getSize ());
247  matvec res (a.getSize (), a.getRows (), a.getCols ());
248  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + b.get (i), i);
249  return res;
250 }
251 
252 // Matrix vector addition with single matrix.
254  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
255  matvec res (a.getSize (), a.getRows (), a.getCols ());
256  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + b, i);
257  return res;
258 }
259 
260 // Matrix vector addition with vector.
262  assert (a.getSize () == b.getSize ());
263  matvec res (a.getSize (), a.getRows (), a.getCols ());
264  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + b.get (i), i);
265  return res;
266 }
267 
268 // Matrix vector addition with vector in different order.
270  return a + b;
271 }
272 
273 // Matrix vector addition with single matrix in different order.
275  return b + a;
276 }
277 
278 // Matrix vector scalar addition.
280  matvec res (a.getSize (), a.getRows (), a.getCols ());
281  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + z, i);
282  return res;
283 }
284 
285 // Matrix vector scalar addition in different order.
287  matvec res (a.getSize (), a.getRows (), a.getCols ());
288  for (int i = 0; i < a.getSize (); i++) res.set (z + a.get (i), i);
289  return res;
290 }
291 
292 // Matrix vector scalar addition.
293 matvec operator + (matvec a, nr_double_t d) {
294  matvec res (a.getSize (), a.getRows (), a.getCols ());
295  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + d, i);
296  return res;
297 }
298 
299 // Matrix vector scalar addition in different order.
300 matvec operator + (nr_double_t d, matvec a) {
301  matvec res (a.getSize (), a.getRows (), a.getCols ());
302  for (int i = 0; i < a.getSize (); i++) res.set (d + a.get (i), i);
303  return res;
304 }
305 
306 // Matrix vector scalar subtraction.
308  matvec res (a.getSize (), a.getRows (), a.getCols ());
309  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - z, i);
310  return res;
311 }
312 
313 // Matrix vector scalar subtraction in different order.
315  matvec res (a.getSize (), a.getRows (), a.getCols ());
316  for (int i = 0; i < a.getSize (); i++) res.set (z - a.get (i), i);
317  return res;
318 }
319 
320 // Matrix vector scalar subtraction.
321 matvec operator - (matvec a, nr_double_t d) {
322  matvec res (a.getSize (), a.getRows (), a.getCols ());
323  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - d, i);
324  return res;
325 }
326 
327 // Matrix vector scalar subtraction in different order.
328 matvec operator - (nr_double_t d, matvec a) {
329  matvec res (a.getSize (), a.getRows (), a.getCols ());
330  for (int i = 0; i < a.getSize (); i++) res.set (d - a.get (i), i);
331  return res;
332 }
333 
334 // Intrinsic matrix vector addition.
336  assert (a.getRows () == rows && a.getCols () == cols &&
337  a.getSize () == size);
338  for (int i = 0; i < size; i++) data[i] += a.get (i);
339  return *this;
340 }
341 
342 // Matrix vector subtraction.
344  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols () &&
345  a.getSize () == b.getSize ());
346  matvec res (a.getSize (), a.getRows (), a.getCols ());
347  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - b.get (i), i);
348  return res;
349 }
350 
351 // Matrix vector subtraction with single matrix.
353  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
354  matvec res (a.getSize (), a.getRows (), a.getCols ());
355  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - b, i);
356  return res;
357 }
358 
359 // Matrix vector subtraction with single matrix in different order.
361  return -b + a;
362 }
363 
364 // Matrix vector subtraction with vector.
366  return -b + a;
367 }
368 
369 // Matrix vector subtraction with vector in different order.
371  return -a + b;
372 }
373 
374 // Unary minus.
376  matvec res (getSize (), getRows (), getCols ());
377  for (int i = 0; i < getSize (); i++) res.set (-data[i], i);
378  return res;
379 }
380 
381 // Intrinsic matrix vector subtraction.
383  assert (a.getRows () == rows && a.getCols () == cols &&
384  a.getSize () == size);
385  for (int i = 0; i < a.getSize (); i++) data[i] -= a.get (i);
386  return *this;
387 }
388 
389 // Matrix vector scaling.
391  matvec res (a.getSize (), a.getRows (), a.getCols ());
392  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * z, i);
393  return res;
394 }
395 
396 // Matrix vector scaling in different order.
398  return a * z;
399 }
400 
401 // Scalar matrix vector scaling.
402 matvec operator * (matvec a, nr_double_t d) {
403  matvec res (a.getSize (), a.getRows (), a.getCols ());
404  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * d, i);
405  return res;
406 }
407 
408 // Scalar matrix vector scaling in different order.
409 matvec operator * (nr_double_t d, matvec a) {
410  return a * d;
411 }
412 
413 // Matrix vector scaling by a second vector.
415  assert (a.getSize () == b.getSize ());
416  matvec res (a.getSize (), a.getRows (), a.getCols ());
417  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * b.get (i), i);
418  return res;
419 }
420 
421 // Matrix vector scaling by a second vector in different order.
423  return b * a;
424 }
425 
426 // Matrix vector scaling.
428  matvec res (a.getSize (), a.getRows (), a.getCols ());
429  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) / z, i);
430  return res;
431 }
432 
433 // Scalar matrix vector scaling.
434 matvec operator / (matvec a, nr_double_t d) {
435  matvec res (a.getSize (), a.getRows (), a.getCols ());
436  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) / d, i);
437  return res;
438 }
439 
440 // Matrix vector scaling by a second vector.
442  assert (a.getSize () == b.getSize ());
443  matvec res (a.getSize (), a.getRows (), a.getCols ());
444  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) / b.get (i), i);
445  return res;
446 }
447 
448 // Matrix vector multiplication.
450  assert (a.getCols () == b.getRows () && a.getSize () == b.getSize ());
451  matvec res (a.getSize (), a.getRows (), b.getCols ());
452  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * b.get (i), i);
453  return res;
454 }
455 
456 // Matrix vector multiplication with a single matrix.
458  assert (a.getCols () == b.getRows ());
459  matvec res (a.getSize (), a.getRows (), b.getCols ());
460  for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * b, i);
461  return res;
462 }
463 
464 // Matrix vector multiplication with a single matrix in different order.
466  return b * a;
467 }
468 
469 // Compute determinants of the given matrix vector.
471  vector res (a.getSize ());
472  for (int i = 0; i < a.getSize (); i++) res.set (det (a.get (i)), i);
473  return res;
474 }
475 
476 // Compute inverse matrices of the given matrix vector.
478  matvec res (a.getSize (), a.getRows (), a.getCols ());
479  for (int i = 0; i < a.getSize (); i++) res.set (inverse (a.get (i)), i);
480  return res;
481 }
482 
483 // Compute n-th power of the given matrix vector.
484 matvec pow (matvec a, int n) {
485  matvec res (a.getSize (), a.getRows (), a.getCols ());
486  for (int i = 0; i < a.getSize (); i++) res.set (pow (a.get (i), n), i);
487  return res;
488 }
489 
490 // Compute n-th powers in the vector of the given matrix vector.
492  assert (a.getSize () == v.getSize ());
493  matvec res (a.getSize (), a.getRows (), a.getCols ());
494  for (int i = 0; i < a.getSize (); i++)
495  res.set (pow (a.get (i), (int) real (v.get (i))), i);
496  return res;
497 }
498 
499 // Conjugate complex matrix vector.
501  matvec res (a.getSize (), a.getRows (), a.getCols ());
502  for (int i = 0; i < a.getSize (); i++) res.set (conj (a.get (i)), i);
503  return res;
504 }
505 
506 // Computes magnitude of each matrix vector element.
508  matvec res (a.getSize (), a.getRows (), a.getCols ());
509  for (int i = 0; i < a.getSize (); i++) res.set (abs (a.get (i)), i);
510  return res;
511 }
512 
513 // Computes magnitude in dB of each matrix vector element.
515  matvec res (a.getSize (), a.getRows (), a.getCols ());
516  for (int i = 0; i < a.getSize (); i++) res.set (dB (a.get (i)), i);
517  return res;
518 }
519 
520 // Computes the argument of each matrix vector element.
522  matvec res (a.getSize (), a.getRows (), a.getCols ());
523  for (int i = 0; i < a.getSize (); i++) res.set (arg (a.get (i)), i);
524  return res;
525 }
526 
527 // Real part matrix vector.
529  matvec res (a.getSize (), a.getRows (), a.getCols ());
530  for (int i = 0; i < a.getSize (); i++) res.set (real (a.get (i)), i);
531  return res;
532 }
533 
534 // Real part matrix vector.
536  matvec res (a.getSize (), a.getRows (), a.getCols ());
537  for (int i = 0; i < a.getSize (); i++) res.set (imag (a.get (i)), i);
538  return res;
539 }
540 
541 /* The function returns the adjoint complex matrix vector. This is
542  also called the adjugate or transpose conjugate. */
544  matvec res (a.getSize (), a.getRows (), a.getCols ());
545  for (int i = 0; i < a.getSize (); i++) res.set (adjoint (a.get (i)), i);
546  return res;
547 }
548 
549 // Transpose the matrix vector.
551  matvec res (a.getSize (), a.getCols (), a.getRows ());
552  for (int i = 0; i < a.getSize (); i++) res.set (transpose (a.get (i)), i);
553  return res;
554 }
555 
556 /* Convert scattering parameters with the reference impedance 'zref'
557  to scattering parameters with the reference impedance 'z0'. */
559  assert (s.getCols () == s.getRows () &&
560  s.getCols () == zref.getSize () && s.getCols () == z0.getSize ());
561  matvec res (s.getSize (), s.getCols (), s.getRows ());
562  for (int i = 0; i < s.getSize (); i++)
563  res.set (stos (s.get (i), zref, z0), i);
564  return res;
565 }
566 
568  int d = s.getRows ();
569  return stos (s, vector (d, zref), vector (d, z0));
570 }
571 
572 matvec stos (matvec s, nr_double_t zref, nr_double_t z0) {
573  return stos (s, rect (zref, 0), rect (z0, 0));
574 }
575 
577  return stos (s, zref, vector (zref.getSize (), z0));
578 }
579 
581  return stos (s, vector (z0.getSize (), zref), z0);
582 }
583 
584 // Convert scattering parameters to admittance matrix vector.
586  assert (s.getCols () == s.getRows () && s.getCols () == z0.getSize ());
587  matvec res (s.getSize (), s.getCols (), s.getRows ());
588  for (int i = 0; i < s.getSize (); i++) res.set (stoy (s.get (i), z0), i);
589  return res;
590 }
591 
593  return stoy (s, vector (s.getCols (), z0));
594 }
595 
596 // Convert admittance matrix to scattering parameter matrix vector.
598  assert (y.getCols () == y.getRows () && y.getCols () == z0.getSize ());
599  matvec res (y.getSize (), y.getCols (), y.getRows ());
600  for (int i = 0; i < y.getSize (); i++) res.set (ytos (y.get (i), z0), i);
601  return res;
602 }
603 
605  return ytos (y, vector (y.getCols (), z0));
606 }
607 
608 // Convert scattering parameters to impedance matrix vector.
610  assert (s.getCols () == s.getRows () && s.getCols () == z0.getSize ());
611  matvec res (s.getSize (), s.getCols (), s.getRows ());
612  for (int i = 0; i < s.getSize (); i++) res.set (stoz (s.get (i), z0), i);
613  return res;
614 }
615 
617  return stoz (s, vector (s.getCols (), z0));
618 }
619 
620 // Convert impedance matrix vector scattering parameter matrix vector.
622  assert (z.getCols () == z.getRows () && z.getCols () == z0.getSize ());
623  matvec res (z.getSize (), z.getCols (), z.getRows ());
624  for (int i = 0; i < z.getSize (); i++) res.set (ztos (z.get (i), z0), i);
625  return res;
626 }
627 
629  return ztos (z, vector (z.getCols (), z0));
630 }
631 
632 // Convert impedance matrix vector to admittance matrix vector.
634  assert (z.getCols () == z.getRows ());
635  matvec res (z.getSize (), z.getCols (), z.getRows ());
636  for (int i = 0; i < z.getSize (); i++) res.set (ztoy (z.get (i)), i);
637  return res;
638 }
639 
640 // Convert admittance matrix vector to impedance matrix vector.
642  assert (y.getCols () == y.getRows ());
643  matvec res (y.getSize (), y.getCols (), y.getRows ());
644  for (int i = 0; i < y.getSize (); i++) res.set (ytoz (y.get (i)), i);
645  return res;
646 }
647 
648 /* This function converts 2x2 matrix vectors from any of the matrix
649  forms Y, Z, H, G and A to any other. Also converts S<->(A, T, H, Y
650  and Z) matrix vectors. */
651 matvec twoport (matvec m, char in, char out) {
652  assert (m.getCols () >= 2 && m.getRows () >= 2);
653  matvec res (m.getSize (), 2, 2);
654  for (int i = 0; i < m.getSize (); i++)
655  res.set (twoport (m.get (i), in, out), i);
656  return res;
657 }
658 
659 /* The function returns the Rollet stability factor vector of the
660  given S-parameter matrix vector. */
662  assert (m.getCols () >= 2 && m.getRows () >= 2);
663  vector res (m.getSize ());
664  for (int i = 0; i < m.getSize (); i++) res.set (rollet (m.get (i)), i);
665  return res;
666 }
667 
668 /* The function returns the stability measure B1 vector of the given
669  S-parameter matrix vector. */
671  assert (m.getCols () >= 2 && m.getRows () >= 2);
672  vector res (m.getSize ());
673  for (int i = 0; i < m.getSize (); i++) res.set (b1 (m.get (i)), i);
674  return res;
675 }