Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
matrix.cpp
Go to the documentation of this file.
1 /*
2  * matrix.cpp - matrix class implementation
3  *
4  * Copyright (C) 2003-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$
22  *
23  */
82 #if HAVE_CONFIG_H
83 # include <config.h>
84 #endif
85 
86 #include <assert.h>
87 #include <stdio.h>
88 #include <cstdlib>
89 #include <string.h>
90 #include <cmath>
91 
92 #include "logging.h"
93 #include "object.h"
94 #include "complex.h"
95 #include "vector.h"
96 #include "matrix.h"
97 
98 namespace qucs {
99 
105  rows = 0;
106  cols = 0;
107  data = NULL;
108 }
109 
118  rows = cols = s;
119  data = (s > 0) ? new nr_complex_t[s * s] : NULL;
120 }
121 
122 /* \brief Creates a matrix
123 
124  Constructor creates an unnamed instance of the matrix class with a
125  certain number of rows and columns.
126  \param[in] r number of rows
127  \param[in] c number of column
128  \todo Why not r and c constant
129  \todo Assert r >= 0 and c >= 0
130 */
131 matrix::matrix (int r, int c) {
132  rows = r;
133  cols = c;
134  data = (r > 0 && c > 0) ? new nr_complex_t[r * c] : NULL;
135 }
136 
137 /* \brief copy constructor
138 
139  The copy constructor creates a new instance based on the given
140  matrix object.
141  \todo Add assert tests
142 */
143 matrix::matrix (const matrix & m) {
144  rows = m.rows;
145  cols = m.cols;
146  data = NULL;
147 
148  // copy matrix elements
149  if (rows > 0 && cols > 0) {
150  data = new nr_complex_t[rows * cols];
151  memcpy (data, m.data, sizeof (nr_complex_t) * rows * cols);
152  }
153 }
154 
164 const matrix& matrix::operator=(const matrix & m) {
165  if (&m != this) {
166  rows = m.rows;
167  cols = m.cols;
168  if (data) {
169  delete[] data;
170  data = NULL;
171  }
172  if (rows > 0 && cols > 0) {
173  data = new nr_complex_t[rows * cols];
174  memcpy (data, m.data, sizeof (nr_complex_t) * rows * cols);
175  }
176  }
177  return *this;
178 }
179 
185  if (data) delete[] data;
186 }
187 
195  return data[r * cols + c];
196 }
197 
205 void matrix::set (int r, int c, nr_complex_t z) {
206  data[r * cols + c] = z;
207 }
208 
209 #ifdef DEBUG
210 
211 void matrix::print (void) {
212  for (int r = 0; r < rows; r++) {
213  for (int c = 0; c < cols; c++) {
214  fprintf (stderr, "%+.2e,%+.2e ", (double) real (get (r, c)),
215  (double) imag (get (r, c)));
216  }
217  fprintf (stderr, "\n");
218  }
219 }
220 #endif /* DEBUG */
221 
228 matrix operator + (matrix a, matrix b) {
229  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
230 
231  matrix res (a.getRows (), a.getCols ());
232  for (int r = 0; r < a.getRows (); r++)
233  for (int c = 0; c < a.getCols (); c++)
234  res.set (r, c, a.get (r, c) + b.get (r, c));
235  return res;
236 }
237 
244  assert (a.getRows () == rows && a.getCols () == cols);
245 
246  int r, c, i;
247  for (i = 0, r = 0; r < a.getRows (); r++)
248  for (c = 0; c < a.getCols (); c++, i++)
249  data[i] += a.get (r, c);
250  return *this;
251 }
252 
259 matrix operator - (matrix a, matrix b) {
260  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
261 
262  matrix res (a.getRows (), a.getCols ());
263  for (int r = 0; r < a.getRows (); r++)
264  for (int c = 0; c < a.getCols (); c++)
265  res.set (r, c, a.get (r, c) - b.get (r, c));
266  return res;
267 }
268 
271  matrix res (getRows (), getCols ());
272  int r, c, i;
273  for (i = 0, r = 0; r < getRows (); r++)
274  for (c = 0; c < getCols (); c++, i++)
275  res.set (r, c, -data[i]);
276  return res;
277 }
278 
284  assert (a.getRows () == rows && a.getCols () == cols);
285  int r, c, i;
286  for (i = 0, r = 0; r < a.getRows (); r++)
287  for (c = 0; c < a.getCols (); c++, i++)
288  data[i] -= a.get (r, c);
289  return *this;
290 }
291 
298 matrix operator * (matrix a, nr_complex_t z) {
299  matrix res (a.getRows (), a.getCols ());
300  for (int r = 0; r < a.getRows (); r++)
301  for (int c = 0; c < a.getCols (); c++)
302  res.set (r, c, a.get (r, c) * z);
303  return res;
304 }
305 
313 matrix operator * (nr_complex_t z, matrix a) {
314  return a * z;
315 }
316 
323 matrix operator * (matrix a, nr_double_t d) {
324  matrix res (a.getRows (), a.getCols ());
325  for (int r = 0; r < a.getRows (); r++)
326  for (int c = 0; c < a.getCols (); c++)
327  res.set (r, c, a.get (r, c) * d);
328  return res;
329 }
330 
338 matrix operator * (nr_double_t d, matrix a) {
339  return a * d;
340 }
341 
348 matrix operator / (matrix a, nr_complex_t z) {
349  matrix res (a.getRows (), a.getCols ());
350  for (int r = 0; r < a.getRows (); r++)
351  for (int c = 0; c < a.getCols (); c++)
352  res.set (r, c, a.get (r, c) / z);
353  return res;
354 }
355 
362 matrix operator / (matrix a, nr_double_t d) {
363  matrix res (a.getRows (), a.getCols ());
364  for (int r = 0; r < a.getRows (); r++)
365  for (int c = 0; c < a.getCols (); c++)
366  res.set (r, c, a.get (r, c) / d);
367  return res;
368 }
369 
378 matrix operator * (matrix a, matrix b) {
379  assert (a.getCols () == b.getRows ());
380 
381  int r, c, i, n = a.getCols ();
382  nr_complex_t z;
383  matrix res (a.getRows (), b.getCols ());
384  for (r = 0; r < a.getRows (); r++) {
385  for (c = 0; c < b.getCols (); c++) {
386  for (i = 0, z = 0; i < n; i++) z += a.get (r, i) * b.get (i, c);
387  res.set (r, c, z);
388  }
389  }
390  return res;
391 }
392 
399 matrix operator + (matrix a, nr_complex_t z) {
400  matrix res (a.getRows (), a.getCols ());
401  for (int r = 0; r < a.getRows (); r++)
402  for (int c = 0; c < a.getCols (); c++)
403  res.set (r, c, a.get (r, c) + z);
404  return res;
405 }
406 
414 matrix operator + (nr_complex_t z, matrix a) {
415  return a + z;
416 }
417 
424 matrix operator + (matrix a, nr_double_t d) {
425  matrix res (a.getRows (), a.getCols ());
426  for (int r = 0; r < a.getRows (); r++)
427  for (int c = 0; c < a.getCols (); c++)
428  res.set (r, c, a.get (r, c) + d);
429  return res;
430 }
431 
439 matrix operator + (nr_double_t d, matrix a) {
440  return a + d;
441 }
442 
450 matrix operator - (matrix a, nr_complex_t z) {
451  return -z + a;
452 }
453 
461 matrix operator - (nr_complex_t z, matrix a) {
462  return -a + z;
463 }
464 
472 matrix operator - (matrix a, nr_double_t d) {
473  return -d + a;
474 }
475 
483 matrix operator - (nr_double_t d, matrix a) {
484  return -a + d;
485 }
486 
492 matrix transpose (matrix a) {
493  matrix res (a.getCols (), a.getRows ());
494  for (int r = 0; r < a.getRows (); r++)
495  for (int c = 0; c < a.getCols (); c++)
496  res.set (c, r, a.get (r, c));
497  return res;
498 }
499 
505 matrix conj (matrix a) {
506  matrix res (a.getRows (), a.getCols ());
507  for (int r = 0; r < a.getRows (); r++)
508  for (int c = 0; c < a.getCols (); c++)
509  res.set (r, c, conj (a.get (r, c)));
510  return res;
511 }
512 
522 matrix adjoint (matrix a) {
523  return transpose (conj (a));
524 }
525 
531 matrix abs (matrix a) {
532  matrix res (a.getRows (), a.getCols ());
533  for (int r = 0; r < a.getRows (); r++)
534  for (int c = 0; c < a.getCols (); c++)
535  res.set (r, c, abs (a.get (r, c)));
536  return res;
537 }
538 
542 matrix dB (matrix a) {
543  matrix res (a.getRows (), a.getCols ());
544  for (int r = 0; r < a.getRows (); r++)
545  for (int c = 0; c < a.getCols (); c++)
546  res.set (r, c, dB (a.get (r, c)));
547  return res;
548 }
549 
555 matrix arg (matrix a) {
556  matrix res (a.getRows (), a.getCols ());
557  for (int r = 0; r < a.getRows (); r++)
558  for (int c = 0; c < a.getCols (); c++)
559  res.set (r, c, arg (a.get (r, c)));
560  return res;
561 }
562 
568 matrix real (matrix a) {
569  matrix res (a.getRows (), a.getCols ());
570  for (int r = 0; r < a.getRows (); r++)
571  for (int c = 0; c < a.getCols (); c++)
572  res.set (r, c, real (a.get (r, c)));
573  return res;
574 }
575 
581 matrix imag (matrix a) {
582  matrix res (a.getRows (), a.getCols ());
583  for (int r = 0; r < a.getRows (); r++)
584  for (int c = 0; c < a.getCols (); c++)
585  res.set (r, c, imag (a.get (r, c)));
586  return res;
587 }
588 
592 matrix sqr (matrix a) {
593  return a * a;
594 }
595 
603 matrix eye (int rs, int cs) {
604  matrix res (rs, cs);
605  for (int r = 0; r < res.getRows (); r++)
606  for (int c = 0; c < res.getCols (); c++)
607  if (r == c) res.set (r, c, 1);
608  return res;
609 }
610 
616 matrix eye (int s) {
617  return eye (s, s);
618 }
619 
624 matrix diagonal (qucs::vector diag) {
625  int size = diag.getSize ();
626  matrix res (size);
627  for (int i = 0; i < size; i++) res (i, i) = diag (i);
628  return res;
629 }
630 
631 // Compute n-th power of the given matrix.
632 matrix pow (matrix a, int n) {
633  matrix res;
634  if (n == 0) {
635  res = eye (a.getRows (), a.getCols ());
636  }
637  else {
638  res = a = n < 0 ? inverse (a) : a;
639  for (int i = 1; i < std::abs (n); i++)
640  res = res * a;
641  }
642  return res;
643 }
644 
657 nr_complex_t cofactor (matrix a, int u, int v) {
658  matrix res (a.getRows () - 1, a.getCols () - 1);
659  int r, c, ra, ca;
660  for (ra = r = 0; r < res.getRows (); r++, ra++) {
661  if (ra == u) ra++;
662  for (ca = c = 0; c < res.getCols (); c++, ca++) {
663  if (ca == v) ca++;
664  res.set (r, c, a.get (ra, ca));
665  }
666  }
667  nr_complex_t z = detLaplace (res);
668  return ((u + v) & 1) ? -z : z;
669 }
670 
687  assert (a.getRows () == a.getCols ());
688  int s = a.getRows ();
689  nr_complex_t res = 0;
690  if (s > 1) {
691  /* always use the first row for sub-determinant, but you should
692  use the row or column with most zeros in it */
693  int r = 0;
694  for (int i = 0; i < s; i++) {
695  res += a.get (r, i) * cofactor (a, r, i);
696  }
697  return res;
698  }
699  /* 1 by 1 matrix */
700  else if (s == 1) {
701  return a (0, 0);
702  }
703  /* 0 by 0 matrix */
704  return 1;
705 }
706 
717 nr_complex_t detGauss (matrix a) {
718  assert (a.getRows () == a.getCols ());
719  nr_double_t MaxPivot;
720  nr_complex_t f, res;
721  matrix b;
722  int i, c, r, pivot, n = a.getCols ();
723 
724  // return special matrix cases
725  if (n == 0) return 1;
726  if (n == 1) return a (0, 0);
727 
728  // make copy of original matrix
729  b = matrix (a);
730 
731  // triangulate the matrix
732  for (res = 1, i = 0; i < n; i++) {
733  // find maximum column value for pivoting
734  for (MaxPivot = 0, pivot = r = i; r < n; r++) {
735  if (abs (b.get (r, i)) > MaxPivot) {
736  MaxPivot = abs (b.get (r, i));
737  pivot = r;
738  }
739  }
740  // exchange rows if necessary
741  assert (MaxPivot != 0);
742  if (i != pivot) { b.exchangeRows (i, pivot); res = -res; }
743  // compute new rows and columns
744  for (r = i + 1; r < n; r++) {
745  f = b.get (r, i) / b.get (i, i);
746  for (c = i + 1; c < n; c++) {
747  b.set (r, c, b.get (r, c) - f * b.get (i, c));
748  }
749  }
750  }
751 
752  // now compute determinant by multiplying diagonal
753  for (i = 0; i < n; i++) res *= b.get (i, i);
754  return res;
755 }
756 
762 nr_complex_t det (matrix a) {
763 #if 0
764  return detLaplace (a);
765 #else
766  return detGauss (a);
767 #endif
768 }
769 
779 matrix inverseLaplace (matrix a) {
780  matrix res (a.getRows (), a.getCols ());
781  nr_complex_t d = detLaplace (a);
782  assert (abs (d) != 0); // singular matrix
783  for (int r = 0; r < a.getRows (); r++)
784  for (int c = 0; c < a.getCols (); c++)
785  res.set (r, c, cofactor (a, c, r) / d);
786  return res;
787 }
788 
798 matrix inverseGaussJordan (matrix a) {
799  nr_double_t MaxPivot;
800  nr_complex_t f;
801  matrix b, e;
802  int i, c, r, pivot, n = a.getCols ();
803 
804  // create temporary matrix and the result matrix
805  b = matrix (a);
806  e = eye (n);
807 
808  // create the eye matrix in 'b' and the result in 'e'
809  for (i = 0; i < n; i++) {
810  // find maximum column value for pivoting
811  for (MaxPivot = 0, pivot = r = i; r < n; r++) {
812  if (abs (b (r, i)) > MaxPivot) {
813  MaxPivot = abs (b (r, i));
814  pivot = r;
815  }
816  }
817  // exchange rows if necessary
818  assert (MaxPivot != 0); // singular matrix
819  if (i != pivot) {
820  b.exchangeRows (i, pivot);
821  e.exchangeRows (i, pivot);
822  }
823 
824  // compute current row
825  for (f = b (i, i), c = 0; c < n; c++) {
826  b (i, c) /= f;
827  e (i, c) /= f;
828  }
829 
830  // compute new rows and columns
831  for (r = 0; r < n; r++) {
832  if (r != i) {
833  for (f = b (r, i), c = 0; c < n; c++) {
834  b (r, c) -= f * b (i, c);
835  e (r, c) -= f * e (i, c);
836  }
837  }
838  }
839  }
840  return e;
841 }
842 
847 matrix inverse (matrix a) {
848 #if 0
849  return inverseLaplace (a);
850 #else
851  return inverseGaussJordan (a);
852 #endif
853 }
854 
890 matrix stos (matrix s, qucs::vector zref, qucs::vector z0) {
891  int d = s.getRows ();
892  matrix e, r, a;
893 
894  assert (d == s.getCols () && d == z0.getSize () && d == zref.getSize ());
895 
896  e = eye (d);
897  r = diagonal ((z0 - zref) / (z0 + zref));
898  a = diagonal (sqrt (z0 / zref) / (z0 + zref));
899  return inverse (a) * (s - r) * inverse (e - r * s) * a;
900 }
901 
910 matrix stos (matrix s, nr_complex_t zref, nr_complex_t z0) {
911  int d = s.getRows ();
912  return stos (s, qucs::vector (d, zref), qucs::vector (d, z0));
913 }
914 
923 matrix stos (matrix s, nr_double_t zref, nr_double_t z0) {
924  return stos (s, nr_complex_t (zref, 0), nr_complex_t (z0, 0));
925 }
926 
935 matrix stos (matrix s, qucs::vector zref, nr_complex_t z0) {
936  return stos (s, zref, qucs::vector (zref.getSize (), z0));
937 }
938 
947 matrix stos (matrix s, nr_complex_t zref, qucs::vector z0) {
948  return stos (s, qucs::vector (z0.getSize (), zref), z0);
949 }
950 
973 matrix stoz (matrix s, qucs::vector z0) {
974  int d = s.getRows ();
975  matrix e, zref, gref;
976 
977  assert (d == s.getCols () && d == z0.getSize ());
978 
979  e = eye (d);
980  zref = diagonal (z0);
981  gref = diagonal (sqrt (real (1 / z0)));
982  return inverse (gref) * inverse (e - s) * (s * zref + zref) * gref;
983 }
984 
992 matrix stoz (matrix s, nr_complex_t z0) {
993  return stoz (s, qucs::vector (s.getRows (), z0));
994 }
995 
1018 matrix ztos (matrix z, qucs::vector z0) {
1019  int d = z.getRows ();
1020  matrix e, zref, gref;
1021 
1022  assert (d == z.getCols () && d == z0.getSize ());
1023 
1024  e = eye (d);
1025  zref = diagonal (z0);
1026  gref = diagonal (sqrt (real (1 / z0)));
1027  return gref * (z - zref) * inverse (z + zref) * inverse (gref);
1028 }
1029 
1037 matrix ztos (matrix z, nr_complex_t z0) {
1038  return ztos (z, qucs::vector (z.getRows (), z0));
1039 }
1040 
1050 matrix ztoy (matrix z) {
1051  assert (z.getRows () == z.getCols ());
1052  return inverse (z);
1053 }
1054 
1082 matrix stoy (matrix s, qucs::vector z0) {
1083  int d = s.getRows ();
1084  matrix e, zref, gref;
1085 
1086  assert (d == s.getCols () && d == z0.getSize ());
1087 
1088  e = eye (d);
1089  zref = diagonal (z0);
1090  gref = diagonal (sqrt (real (1 / z0)));
1091  return inverse (gref) * inverse (s * zref + zref) * (e - s) * gref;
1092 }
1093 
1101 matrix stoy (matrix s, nr_complex_t z0) {
1102  return stoy (s, qucs::vector (s.getRows (), z0));
1103 }
1104 
1133 matrix ytos (matrix y, qucs::vector z0) {
1134  int d = y.getRows ();
1135  matrix e, zref, gref;
1136 
1137  assert (d == y.getCols () && d == z0.getSize ());
1138 
1139  e = eye (d);
1140  zref = diagonal (z0);
1141  gref = diagonal (sqrt (real (1 / z0)));
1142  return gref * (e - zref * y) * inverse (e + zref * y) * inverse (gref);
1143 }
1151 matrix ytos (matrix y, nr_complex_t z0) {
1152  return ytos (y, qucs::vector (y.getRows (), z0));
1153 }
1181 matrix stoa (matrix s, nr_complex_t z1, nr_complex_t z2) {
1182  nr_complex_t d = s (0, 0) * s (1, 1) - s (0, 1) * s (1, 0);
1183  nr_complex_t n = 2.0 * s (1, 0) * sqrt (fabs (real (z1) * real (z2)));
1184  matrix a (2);
1185 
1186  assert (s.getRows () >= 2 && s.getCols () >= 2);
1187 
1188  a.set (0, 0, (conj (z1) + z1 * s (0, 0) -
1189  conj (z1) * s (1, 1) - z1 * d) / n);
1190  a.set (0, 1, (conj (z1) * conj (z2) + z1 * conj (z2) * s (0, 0) +
1191  conj (z1) * z2 * s (1, 1) + z1 * z2 * d) / n);
1192  a.set (1, 0, (1.0 - s (0, 0) - s (1, 1) + d) / n);
1193  a.set (1, 1, (conj (z2) - conj (z2) * s (0, 0) +
1194  z2 * s (1, 1) - z2 * d) / n);
1195  return a;
1196 }
1197 
1198 
1222 matrix atos (matrix a, nr_complex_t z1, nr_complex_t z2) {
1223  nr_complex_t d = 2.0 * sqrt (fabs (real (z1) * real (z2)));
1224  nr_complex_t n = a (0, 0) * z2 + a (0, 1) +
1225  a (1, 0) * z1 * z2 + a (1, 1) * z1;
1226  matrix s (2);
1227 
1228  assert (a.getRows () >= 2 && a.getCols () >= 2);
1229 
1230  s.set (0, 0, (a (0, 0) * z2 + a (0, 1)
1231  - a (1, 0) * conj (z1) * z2 - a (1, 1) * conj (z1)) / n);
1232  s.set (0, 1, (a (0, 0) * a (1, 1) -
1233  a (0, 1) * a (1, 0)) * d / n);
1234  s.set (1, 0, d / n);
1235  s.set (1, 1, (a (1, 1) * z1 - a (0, 0) * conj (z2) +
1236  a (0, 1) - a (1, 0) * z1 * conj (z2)) / n);
1237  return s;
1238 }
1239 
1269 matrix stoh (matrix s, nr_complex_t z1, nr_complex_t z2) {
1270  nr_complex_t n = s (0, 1) * s (1, 0);
1271  nr_complex_t d = (1.0 - s (0, 0)) * (1.0 + s (1, 1)) + n;
1272  matrix h (2);
1273 
1274  assert (s.getRows () >= 2 && s.getCols () >= 2);
1275 
1276  h.set (0, 0, ((1.0 + s (0, 0)) * (1.0 + s (1, 1)) - n) * z1 / d);
1277  h.set (0, 1, +2.0 * s (0, 1) / d);
1278  h.set (1, 0, -2.0 * s (1, 0) / d);
1279  h.set (1, 1, ((1.0 - s (0, 0)) * (1.0 - s (1, 1)) - n) / z2 / d);
1280  return h;
1281 }
1282 
1307 matrix htos (matrix h, nr_complex_t z1, nr_complex_t z2) {
1308  nr_complex_t n = h (0, 1) * h (1, 0);
1309  nr_complex_t d = (1.0 + h (0, 0) / z1) * (1.0 + z2 * h (1, 1)) - n;
1310  matrix s (2);
1311 
1312  assert (h.getRows () >= 2 && h.getCols () >= 2);
1313 
1314  s.set (0, 0, ((h (0, 0) / z1 - 1.0) * (1.0 + z2 * h (1, 1)) - n) / d);
1315  s.set (0, 1, +2.0 * h (0, 1) / d);
1316  s.set (1, 0, -2.0 * h (1, 0) / d);
1317  s.set (1, 1, ((1.0 + h (0, 0) / z1) * (1.0 - z2 * h (1, 1)) + n) / d);
1318  return s;
1319 }
1320 
1321 /*\brief Converts scattering parameters to second hybrid matrix.
1322  \bug{Programmed formulae are valid only for Z real}
1323  \bug{Not documented and references}
1324  \param[in] s Scattering matrix
1325  \param[in] z1 impedance at input 1
1326  \param[in] z2 impedance at input 2
1327  \return second hybrid matrix
1328  \note Assert 2 by 2 matrix
1329  \todo Why not s,z1,z2 const
1330 */
1331 matrix stog (matrix s, nr_complex_t z1, nr_complex_t z2) {
1332  nr_complex_t n = s (0, 1) * s (1, 0);
1333  nr_complex_t d = (1.0 + s (0, 0)) * (1.0 - s (1, 1)) + n;
1334  matrix g (2);
1335 
1336  assert (s.getRows () >= 2 && s.getCols () >= 2);
1337 
1338  g.set (0, 0, ((1.0 - s (0, 0)) * (1.0 - s (1, 1)) - n) / z1 / d);
1339  g.set (0, 1, -2.0 * s (0, 1) / d);
1340  g.set (1, 0, +2.0 * s (1, 0) / d);
1341  g.set (1, 1, ((1.0 + s (0, 0)) * (1.0 + s (1, 1)) - n) * z2 / d);
1342  return g;
1343 }
1344 
1345 /*\brief Converts second hybrid matrix to scattering parameters.
1346  \bug{Programmed formulae are valid only for Z real}
1347  \bug{Not documented and references}
1348  \param[in] g second hybrid matrix
1349  \param[in] z1 impedance at input 1
1350  \param[in] z2 impedance at input 2
1351  \return scattering matrix
1352  \note Assert 2 by 2 matrix
1353  \todo Why not g,z1,z2 const
1354 */
1355 matrix gtos (matrix g, nr_complex_t z1, nr_complex_t z2) {
1356  nr_complex_t n = g (0, 1) * g (1, 0);
1357  nr_complex_t d = (1.0 + g (0, 0) * z1) * (1.0 + g (1, 1) / z2) - n;
1358  matrix s (2);
1359 
1360  assert (g.getRows () >= 2 && g.getCols () >= 2);
1361 
1362  s.set (0, 0, ((1.0 - g (0, 0) * z1) * (1.0 + g (1, 1) / z2) + n) / d);
1363  s.set (0, 1, -2.0 * g (0, 1) / d);
1364  s.set (1, 0, +2.0 * g (1, 0) / d);
1365  s.set (1, 1, ((g (0, 0) * z1 + 1.0) * (g (1, 1) / z2 - 1.0) - n) / d);
1366  return s;
1367 }
1368 
1380 matrix ytoz (matrix y) {
1381  assert (y.getRows () == y.getCols ());
1382  return inverse (y);
1383 }
1384 
1404 matrix cytocs (matrix cy, matrix s) {
1405  matrix e = eye (s.getRows ());
1406 
1407  assert (cy.getRows () == cy.getCols () && s.getRows () == s.getCols () &&
1408  cy.getRows () == s.getRows ());
1409 
1410  return (e + s) * cy * adjoint (e + s) / 4;
1411 }
1412 
1430 matrix cstocy (matrix cs, matrix y) {
1431  matrix e = eye (y.getRows ());
1432 
1433  assert (cs.getRows () == cs.getCols () && y.getRows () == y.getCols () &&
1434  cs.getRows () == y.getRows ());
1435 
1436  return (e + y) * cs * adjoint (e + y);
1437 }
1438 
1457 matrix cztocs (matrix cz, matrix s) {
1458  matrix e = eye (s.getRows ());
1459 
1460  assert (cz.getRows () == cz.getCols () && s.getRows () == s.getCols () &&
1461  cz.getRows () == s.getRows ());
1462 
1463  return (e - s) * cz * adjoint (e - s) / 4;
1464 }
1465 
1483 matrix cstocz (matrix cs, matrix z) {
1484  assert (cs.getRows () == cs.getCols () && z.getRows () == z.getCols () &&
1485  cs.getRows () == z.getRows ());
1486  matrix e = eye (z.getRows ());
1487  return (e + z) * cs * adjoint (e + z);
1488 }
1489 
1507 matrix cztocy (matrix cz, matrix y) {
1508  assert (cz.getRows () == cz.getCols () && y.getRows () == y.getCols () &&
1509  cz.getRows () == y.getRows ());
1510 
1511  return y * cz * adjoint (y);
1512 }
1513 
1531 matrix cytocz (matrix cy, matrix z) {
1532  assert (cy.getRows () == cy.getCols () && z.getRows () == z.getCols () &&
1533  cy.getRows () == z.getRows ());
1534  return z * cy * adjoint (z);
1535 }
1536 
1543 void matrix::exchangeRows (int r1, int r2) {
1544  nr_complex_t * s = new nr_complex_t[cols];
1545  int len = sizeof (nr_complex_t) * cols;
1546 
1547  assert (r1 >= 0 && r2 >= 0 && r1 < rows && r2 < rows);
1548 
1549  memcpy (s, &data[r1 * cols], len);
1550  memcpy (&data[r1 * cols], &data[r2 * cols], len);
1551  memcpy (&data[r2 * cols], s, len);
1552  delete[] s;
1553 }
1554 
1561 void matrix::exchangeCols (int c1, int c2) {
1562  nr_complex_t s;
1563 
1564  assert (c1 >= 0 && c2 >= 0 && c1 < cols && c2 < cols);
1565 
1566  for (int r = 0; r < rows * cols; r += cols) {
1567  s = data[r + c1];
1568  data[r + c1] = data[r + c2];
1569  data[r + c2] = s;
1570  }
1571 }
1572 
1594 matrix twoport (matrix m, char in, char out) {
1595  assert (m.getRows () >= 2 && m.getCols () >= 2);
1596  nr_complex_t d;
1597  matrix res (2);
1598 
1599  switch (in) {
1600  case 'Y':
1601  switch (out) {
1602  case 'Y': // Y to Y
1603  res = m;
1604  break;
1605  case 'Z': // Y to Z
1606  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1607  res.set (0, 0, m (1, 1) / d);
1608  res.set (0, 1, -m (0, 1) / d);
1609  res.set (1, 0, -m (1, 0) / d);
1610  res.set (1, 1, m (0, 0) / d);
1611  break;
1612  case 'H': // Y to H
1613  d = m (0, 0);
1614  res.set (0, 0, 1.0 / d);
1615  res.set (0, 1, -m (0, 1) / d);
1616  res.set (1, 0, m (1, 0) / d);
1617  res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
1618  break;
1619  case 'G': // Y to G
1620  d = m (1, 1);
1621  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1622  res.set (0, 1, m (0, 1) / d);
1623  res.set (1, 0, -m (1, 0) / d);
1624  res.set (1, 1, 1.0 / d);
1625  break;
1626  case 'A': // Y to A
1627  d = m (1, 0);
1628  res.set (0, 0, -m (1, 1) / d);
1629  res.set (0, 1, -1.0 / d);
1630  res.set (1, 0, m (0, 1) - m (1, 1) * m (0, 0) / d);
1631  res.set (1, 1, -m (0, 0) / d);
1632  break;
1633  case 'S': // Y to S
1634  res = ytos (m);
1635  break;
1636  }
1637  break;
1638  case 'Z':
1639  switch (out) {
1640  case 'Y': // Z to Y
1641  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1642  res.set (0, 0, m (1, 1) / d);
1643  res.set (0, 1, -m (0, 1) / d);
1644  res.set (1, 0, -m (1, 0) / d);
1645  res.set (1, 1, m (0, 0) / d);
1646  break;
1647  case 'Z': // Z to Z
1648  res = m;
1649  break;
1650  case 'H': // Z to H
1651  d = m (1, 1);
1652  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1653  res.set (0, 1, m (0, 1) / d);
1654  res.set (1, 0, -m (1, 0) / d);
1655  res.set (1, 1, 1.0 / d);
1656  break;
1657  case 'G': // Z to G
1658  d = m (0, 0);
1659  res.set (0, 0, 1.0 / d);
1660  res.set (0, 1, -m (0, 1) / d);
1661  res.set (1, 0, m (1, 0) / d);
1662  res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
1663  break;
1664  case 'A': // Z to A
1665  d = m (1, 0);
1666  res.set (0, 0, m (0, 0) / d);
1667  res.set (0, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
1668  res.set (1, 0, 1.0 / d);
1669  res.set (1, 1, m (1, 1) / d);
1670  break;
1671  case 'S': // Z to S
1672  res = ztos (m);
1673  break;
1674  }
1675  break;
1676  case 'H':
1677  switch (out) {
1678  case 'Y': // H to Y
1679  d = m (0, 0);
1680  res.set (0, 0, 1.0 / d);
1681  res.set (0, 1, -m (0, 1) / d);
1682  res.set (1, 0, m (1, 0) / d);
1683  res.set (1, 1, m (1, 1) - m (0, 1) * m.get(2, 1) / d);
1684  break;
1685  case 'Z': // H to Z
1686  d = m (1, 1);
1687  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1688  res.set (0, 1, m (0, 1) / d);
1689  res.set (1, 0, -m (1, 0) / d);
1690  res.set (1, 1, 1.0 / d);
1691  break;
1692  case 'H': // H to H
1693  res = m;
1694  break;
1695  case 'G': // H to G
1696  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1697  res.set (0, 0, m (1, 1) / d);
1698  res.set (0, 1, -m (0, 1) / d);
1699  res.set (1, 0, -m (1, 0) / d);
1700  res.set (1, 1, m (0, 0) / d);
1701  break;
1702  case 'A': // H to A
1703  d = m (1, 0);
1704  res.set (0, 0, m (0, 1) - m (0, 0) * m (1, 1) / d);
1705  res.set (0, 1, -m (0, 0) / d);
1706  res.set (1, 0, -m (1, 1) / d);
1707  res.set (1, 1, -1.0 / d);
1708  break;
1709  case 'S': // H to S
1710  res = htos (m);
1711  break;
1712  }
1713  break;
1714  case 'G':
1715  switch (out) {
1716  case 'Y': // G to Y
1717  d = m (1, 1);
1718  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1719  res.set (0, 1, m (0, 1) / d);
1720  res.set (1, 0, -m (1, 0) / d);
1721  res.set (1, 1, 1.0 / d);
1722  break;
1723  case 'Z': // G to Z
1724  d = m (0, 0);
1725  res.set (0, 0, 1.0 / d);
1726  res.set (0, 1, -m (0, 1) / d);
1727  res.set (1, 0, m (1, 0) / d);
1728  res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
1729  break;
1730  case 'H': // G to H
1731  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1732  res.set (0, 0, m (1, 1) / d);
1733  res.set (0, 1, -m (0, 1) / d);
1734  res.set (1, 0, -m (1, 0) / d);
1735  res.set (1, 1, m (0, 0) / d);
1736  break;
1737  case 'G': // G to G
1738  res = m;
1739  break;
1740  case 'A': // G to A
1741  d = m (1, 0);
1742  res.set (0, 0, 1.0 / d);
1743  res.set (0, 1, m (1, 1) / d);
1744  res.set (1, 0, m (0, 0) / d);
1745  res.set (1, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
1746  break;
1747  case 'S': // G to S
1748  res = gtos (m);
1749  break;
1750  }
1751  break;
1752  case 'A':
1753  switch (out) {
1754  case 'Y': // A to Y
1755  d = m (0, 1);
1756  res.set (0, 0, m (1, 1) / d);
1757  res.set (0, 1, m (1, 0) - m (0, 0) * m (1, 1) / d);
1758  res.set (1, 0, -1.0 / d);
1759  res.set (1, 1, m (0, 0) / d);
1760  break;
1761  case 'Z': // A to Z
1762  d = m (1, 0);
1763  res.set (0, 0, m (0, 0) / d);
1764  res.set (0, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
1765  res.set (1, 0, 1.0 / d);
1766  res.set (1, 1, m (1, 1) / d);
1767  break;
1768  case 'H': // A to H
1769  d = m (1, 1);
1770  res.set (0, 0, m (0, 1) / d);
1771  res.set (0, 1, m (0, 0) - m (0, 1) * m (1, 0) / d);
1772  res.set (1, 0, -1.0 / d);
1773  res.set (1, 1, m (1, 0) / d);
1774  break;
1775  case 'G': // A to G
1776  d = m (0, 0);
1777  res.set (0, 0, m (1, 0) / d);
1778  res.set (0, 1, m (1, 0) * m (0, 1) / d - m (1, 1));
1779  res.set (1, 0, 1.0 / d);
1780  res.set (1, 1, m (0, 1) / d);
1781  break;
1782  case 'A': // A to A
1783  res = m;
1784  break;
1785  case 'S': // A to S
1786  res = atos (m);
1787  break;
1788  }
1789  break;
1790  case 'S':
1791  switch (out) {
1792  case 'S': // S to S
1793  res = m;
1794  break;
1795  case 'T': // S to T
1796  d = m (1, 0);
1797  res.set (0, 0, m (0, 1) - m (0, 0) * m (1, 1) / d);
1798  res.set (0, 1, m (0, 0) / d);
1799  res.set (1, 0, -m (1, 1) / d);
1800  res.set (0, 1, 1.0 / d);
1801  break;
1802  case 'A': // S to A
1803  res = stoa (m);
1804  break;
1805  case 'H': // S to H
1806  res = stoh (m);
1807  break;
1808  case 'G': // S to G
1809  res = stog (m);
1810  break;
1811  case 'Y': // S to Y
1812  res = stoy (m);
1813  break;
1814  case 'Z': // S to Z
1815  res = stoz (m);
1816  break;
1817  }
1818  break;
1819  case 'T':
1820  switch (out) {
1821  case 'S': // T to S
1822  d = m (1, 1);
1823  res.set (0, 0, m (0, 1) / d);
1824  res.set (0, 1, m (0, 0) - m (0, 1) * m (1, 0) / d);
1825  res.set (1, 0, 1.0 / d);
1826  res.set (0, 1, -m (1, 0) / d);
1827  break;
1828  case 'T': // T to T
1829  res = m;
1830  break;
1831  }
1832  break;
1833  }
1834  return res;
1835 }
1836 
1854 nr_double_t rollet (matrix m) {
1855  assert (m.getRows () >= 2 && m.getCols () >= 2);
1856  nr_double_t res;
1857  res = (1 - norm (m (0, 0)) - norm (m (1, 1)) + norm (det (m))) /
1858  2 / abs (m (0, 1) * m (1, 0));
1859  return res;
1860 }
1861 
1862 /* Computes stability measure B1 of the given S-parameter matrix. */
1863 nr_double_t b1 (matrix m) {
1864  assert (m.getRows () >= 2 && m.getCols () >= 2);
1865  nr_double_t res;
1866  res = 1 + norm (m (0, 0)) - norm (m (1, 1)) - norm (det (m));
1867  return res;
1868 }
1869 
1870 } // namespace qucs
matrix operator-()
Unary minus.
Definition: matrix.cpp:270
matrix inverse(matrix a)
Compute inverse matrix.
Definition: matrix.cpp:847
std::complex< nr_double_t > nr_complex_t
Definition: complex.h:31
matrix adjoint(matrix a)
adjoint matrix
Definition: matrix.cpp:522
matrix ytos(matrix y, qucs::vector z0)
Admittance matrix to scattering parameters.
Definition: matrix.cpp:1133
matrix real(matrix a)
Real part matrix.
Definition: matrix.cpp:568
matrix abs(matrix a)
Computes magnitude of each matrix element.
Definition: matrix.cpp:531
int cols
Definition: matrix.h:207
nr_complex_t get(int, int)
Returns the matrix element at the given row and column.
Definition: matrix.cpp:194
size
Definition: parse_vcd.y:203
matrix ytoz(matrix y)
Convert admittance matrix to impedance matrix.
Definition: matrix.cpp:1380
int getSize(void) const
Definition: vector.cpp:192
matrix operator*(matrix a, nr_complex_t z)
Matrix scaling complex version.
Definition: matrix.cpp:298
nr_complex_t pow(const nr_complex_t z, const nr_double_t d)
Compute power function with real exponent.
Definition: complex.cpp:238
matrix stos(matrix s, qucs::vector zref, qucs::vector z0)
S params to S params.
Definition: matrix.cpp:890
nr_complex_t detLaplace(matrix a)
Compute determinant of the given matrix using Laplace expansion.
Definition: matrix.cpp:686
nr_complex_t * data
Definition: matrix.h:211
void exchangeRows(int, int)
The function swaps the given rows with each other.
Definition: matrix.cpp:1543
matrix twoport(matrix m, char in, char out)
Generic conversion matrix.
Definition: matrix.cpp:1594
const matrix & operator=(const matrix &)
Assignment operator.
Definition: matrix.cpp:164
nr_double_t rollet(matrix)
n
Definition: parse_citi.y:147
matrix stoh(matrix s, nr_complex_t z1, nr_complex_t z2)
Converts scattering parameters to hybrid matrix.
Definition: matrix.cpp:1269
h
Definition: parse_vcd.y:214
r
Definition: parse_mdl.y:515
nr_double_t b1(matrix)
matrix diagonal(qucs::vector diag)
Create a diagonal matrix from a vector.
Definition: matrix.cpp:624
matrix()
Create an empty matrix.
Definition: matrix.cpp:104
matrix inverseGaussJordan(matrix a)
Compute inverse matrix using Gauss-Jordan elimination.
Definition: matrix.cpp:798
matrix htos(matrix h, nr_complex_t z1, nr_complex_t z2)
Converts hybrid matrix to scattering parameters.
Definition: matrix.cpp:1307
i
Definition: parse_mdl.y:516
nr_complex_t sqr(const nr_complex_t z)
Square of complex number.
Definition: complex.cpp:673
matrix imag(matrix a)
Imaginary part matrix.
Definition: matrix.cpp:581
matrix operator-(matrix a, matrix b)
Matrix subtraction.
Definition: matrix.cpp:259
void exchangeCols(int, int)
The function swaps the given column with each other.
Definition: matrix.cpp:1561
nr_complex_t sqrt(const nr_complex_t z)
Compute principal value of square root.
Definition: complex.cpp:271
matrix stoy(matrix s, qucs::vector z0)
Scattering parameters to admittance matrix.
Definition: matrix.cpp:1082
void print(void)
matrix inverseLaplace(matrix a)
Compute inverse matrix using Laplace expansion.
Definition: matrix.cpp:779
matrix cztocs(matrix cz, matrix s)
Converts impedance noise correlation matrix to S-parameter noise correlation matrix.
Definition: matrix.cpp:1457
matrix operator+=(matrix)
Intrinsic matrix addition.
Definition: matrix.cpp:243
nr_double_t dB(const nr_complex_t z)
Magnitude in dB Compute .
Definition: complex.cpp:528
matrix ztos(matrix z, qucs::vector z0)
Convert impedance matrix scattering parameters.
Definition: matrix.cpp:1018
matrix operator/(matrix a, nr_complex_t z)
Matrix scaling division by complex version.
Definition: matrix.cpp:348
eqn::constant * c1
eqn::constant * c2
nr_complex_t detGauss(matrix a)
Compute determinant Gaussian algorithm.
Definition: matrix.cpp:717
matrix cstocz(matrix cs, matrix z)
Converts S-parameter noise correlation matrix to impedance noise correlation matrix.
Definition: matrix.cpp:1483
nr_complex_t det(matrix a)
Compute determinant of the given matrix.
Definition: matrix.cpp:762
Declaration sizeof(struct vcd_scope))
void set(int, int, nr_complex_t)
Sets the matrix element at the given row and column.
Definition: matrix.cpp:205
matrix cytocz(matrix cy, matrix z)
Converts admittance noise correlation matrix to impedance noise correlation matrix.
Definition: matrix.cpp:1531
matrix transpose(matrix a)
Matrix transposition.
Definition: matrix.cpp:492
Dense matrix class header file.
matrix operator+(matrix a, matrix b)
Matrix addition.
Definition: matrix.cpp:228
matrix cstocy(matrix cs, matrix y)
Converts S-parameter noise correlation matrix to admittance noise correlation matrix.
Definition: matrix.cpp:1430
Dense complex matrix class This class defines a matrix object with its methods, operators and operati...
Definition: matrix.h:92
nr_complex_t cofactor(matrix a, int u, int v)
Computes the complex cofactor of the given determinant.
Definition: matrix.cpp:657
matrix cytocs(matrix cy, matrix s)
Admittance noise correlation matrix to S-parameter noise correlation matrix.
Definition: matrix.cpp:1404
v
Definition: parse_zvr.y:141
matrix stoa(matrix s, nr_complex_t z1, nr_complex_t z2)
Converts chain matrix to scattering parameters.
Definition: matrix.cpp:1181
matrix stoz(matrix s, qucs::vector z0)
Scattering parameters to impedance matrix.
Definition: matrix.cpp:973
matrix cztocy(matrix cz, matrix y)
Converts impedance noise correlation matrix to admittance noise correlation matrix.
Definition: matrix.cpp:1507
nr_double_t norm(const nr_complex_t z)
Compute euclidian norm of complex number.
Definition: complex.cpp:283
int getCols(void)
Definition: matrix.h:103
matrix stog(matrix s, nr_complex_t z1, nr_complex_t z2)
Definition: matrix.cpp:1331
y
Definition: parse_mdl.y:499
matrix gtos(matrix g, nr_complex_t z1, nr_complex_t z2)
Definition: matrix.cpp:1355
matrix eye(int rs, int cs)
Create identity matrix with specified number of rows and columns.
Definition: matrix.cpp:603
friend matrix imag(matrix)
matrix conj(matrix a)
Conjugate complex matrix.
Definition: matrix.cpp:505
matrix atos(matrix a, nr_complex_t z1, nr_complex_t z2)
Converts chain matrix to scattering parameters.
Definition: matrix.cpp:1222
zref
Definition: parse_zvr.y:130
friend matrix real(matrix)
matrix ztoy(matrix z)
impedance matrix to admittance matrix.
Definition: matrix.cpp:1050
int rows
Definition: matrix.h:209
int getRows(void)
Definition: matrix.h:104
matrix arg(matrix a)
Computes the argument of each matrix element.
Definition: matrix.cpp:555
matrix operator-=(matrix)
Intrinsic matrix subtraction.
Definition: matrix.cpp:283