My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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: matrix.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
82 #if HAVE_CONFIG_H
83 # include <config.h>
84 #endif
85 
86 #include <assert.h>
87 #include <stdio.h>
88 #include <stdlib.h>
89 #include <string.h>
90 #include <math.h>
91 
92 #include "logging.h"
93 #include "object.h"
94 #include "complex.h"
95 #include "vector.h"
96 #include "matrix.h"
97 
103  rows = 0;
104  cols = 0;
105  data = NULL;
106 }
107 
116  rows = cols = s;
117  data = (s > 0) ? new nr_complex_t[s * s] : NULL;
118 }
119 
120 /* \brief Creates a matrix
121 
122  Constructor creates an unnamed instance of the matrix class with a
123  certain number of rows and columns.
124  \param[in] r number of rows
125  \param[in] c number of column
126  \todo Why not r and c constant
127  \todo Assert r >= 0 and c >= 0
128 */
129 matrix::matrix (int r, int c) {
130  rows = r;
131  cols = c;
132  data = (r > 0 && c > 0) ? new nr_complex_t[r * c] : NULL;
133 }
134 
135 /* \brief copy constructor
136 
137  The copy constructor creates a new instance based on the given
138  matrix object.
139  \todo Add assert tests
140 */
141 matrix::matrix (const matrix & m) {
142  rows = m.rows;
143  cols = m.cols;
144  data = NULL;
145 
146  // copy matrix elements
147  if (rows > 0 && cols > 0) {
148  data = new nr_complex_t[rows * cols];
149  memcpy (data, m.data, sizeof (nr_complex_t) * rows * cols);
150  }
151 }
152 
162 const matrix& matrix::operator=(const matrix & m) {
163  if (&m != this) {
164  rows = m.rows;
165  cols = m.cols;
166  if (data) {
167  delete[] data;
168  data = NULL;
169  }
170  if (rows > 0 && cols > 0) {
171  data = new nr_complex_t[rows * cols];
172  memcpy (data, m.data, sizeof (nr_complex_t) * rows * cols);
173  }
174  }
175  return *this;
176 }
177 
183  if (data) delete[] data;
184 }
185 
192 nr_complex_t matrix::get (int r, int c) {
193  return data[r * cols + c];
194 }
195 
203 void matrix::set (int r, int c, nr_complex_t z) {
204  data[r * cols + c] = z;
205 }
206 
207 #ifdef DEBUG
208 
209 void matrix::print (void) {
210  for (int r = 0; r < rows; r++) {
211  for (int c = 0; c < cols; c++) {
212  fprintf (stderr, "%+.2e,%+.2e ", (double) real (get (r, c)),
213  (double) imag (get (r, c)));
214  }
215  fprintf (stderr, "\n");
216  }
217 }
218 #endif /* DEBUG */
219 
227  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
228 
229  matrix res (a.getRows (), a.getCols ());
230  for (int r = 0; r < a.getRows (); r++)
231  for (int c = 0; c < a.getCols (); c++)
232  res.set (r, c, a.get (r, c) + b.get (r, c));
233  return res;
234 }
235 
242  assert (a.getRows () == rows && a.getCols () == cols);
243 
244  int r, c, i;
245  for (i = 0, r = 0; r < a.getRows (); r++)
246  for (c = 0; c < a.getCols (); c++, i++)
247  data[i] += a.get (r, c);
248  return *this;
249 }
250 
258  assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
259 
260  matrix res (a.getRows (), a.getCols ());
261  for (int r = 0; r < a.getRows (); r++)
262  for (int c = 0; c < a.getCols (); c++)
263  res.set (r, c, a.get (r, c) - b.get (r, c));
264  return res;
265 }
266 
269  matrix res (getRows (), getCols ());
270  int r, c, i;
271  for (i = 0, r = 0; r < getRows (); r++)
272  for (c = 0; c < getCols (); c++, i++)
273  res.set (r, c, -data[i]);
274  return res;
275 }
276 
282  assert (a.getRows () == rows && a.getCols () == cols);
283  int r, c, i;
284  for (i = 0, r = 0; r < a.getRows (); r++)
285  for (c = 0; c < a.getCols (); c++, i++)
286  data[i] -= a.get (r, c);
287  return *this;
288 }
289 
297  matrix res (a.getRows (), a.getCols ());
298  for (int r = 0; r < a.getRows (); r++)
299  for (int c = 0; c < a.getCols (); c++)
300  res.set (r, c, a.get (r, c) * z);
301  return res;
302 }
303 
312  return a * z;
313 }
314 
321 matrix operator * (matrix a, nr_double_t d) {
322  matrix res (a.getRows (), a.getCols ());
323  for (int r = 0; r < a.getRows (); r++)
324  for (int c = 0; c < a.getCols (); c++)
325  res.set (r, c, a.get (r, c) * d);
326  return res;
327 }
328 
336 matrix operator * (nr_double_t d, matrix a) {
337  return a * d;
338 }
339 
347  matrix res (a.getRows (), a.getCols ());
348  for (int r = 0; r < a.getRows (); r++)
349  for (int c = 0; c < a.getCols (); c++)
350  res.set (r, c, a.get (r, c) / z);
351  return res;
352 }
353 
360 matrix operator / (matrix a, nr_double_t d) {
361  matrix res (a.getRows (), a.getCols ());
362  for (int r = 0; r < a.getRows (); r++)
363  for (int c = 0; c < a.getCols (); c++)
364  res.set (r, c, a.get (r, c) / d);
365  return res;
366 }
367 
377  assert (a.getCols () == b.getRows ());
378 
379  int r, c, i, n = a.getCols ();
380  nr_complex_t z;
381  matrix res (a.getRows (), b.getCols ());
382  for (r = 0; r < a.getRows (); r++) {
383  for (c = 0; c < b.getCols (); c++) {
384  for (i = 0, z = 0; i < n; i++) z += a.get (r, i) * b.get (i, c);
385  res.set (r, c, z);
386  }
387  }
388  return res;
389 }
390 
398  matrix res (a.getRows (), a.getCols ());
399  for (int r = 0; r < a.getRows (); r++)
400  for (int c = 0; c < a.getCols (); c++)
401  res.set (r, c, a.get (r, c) + z);
402  return res;
403 }
404 
413  return a + z;
414 }
415 
422 matrix operator + (matrix a, nr_double_t d) {
423  matrix res (a.getRows (), a.getCols ());
424  for (int r = 0; r < a.getRows (); r++)
425  for (int c = 0; c < a.getCols (); c++)
426  res.set (r, c, a.get (r, c) + d);
427  return res;
428 }
429 
437 matrix operator + (nr_double_t d, matrix a) {
438  return a + d;
439 }
440 
449  return -z + a;
450 }
451 
460  return -a + z;
461 }
462 
470 matrix operator - (matrix a, nr_double_t d) {
471  return -d + a;
472 }
473 
481 matrix operator - (nr_double_t d, matrix a) {
482  return -a + d;
483 }
484 
491  matrix res (a.getCols (), a.getRows ());
492  for (int r = 0; r < a.getRows (); r++)
493  for (int c = 0; c < a.getCols (); c++)
494  res.set (c, r, a.get (r, c));
495  return res;
496 }
497 
504  matrix res (a.getRows (), a.getCols ());
505  for (int r = 0; r < a.getRows (); r++)
506  for (int c = 0; c < a.getCols (); c++)
507  res.set (r, c, conj (a.get (r, c)));
508  return res;
509 }
510 
521  return transpose (conj (a));
522 }
523 
530  matrix res (a.getRows (), a.getCols ());
531  for (int r = 0; r < a.getRows (); r++)
532  for (int c = 0; c < a.getCols (); c++)
533  res.set (r, c, abs (a.get (r, c)));
534  return res;
535 }
536 
541  matrix res (a.getRows (), a.getCols ());
542  for (int r = 0; r < a.getRows (); r++)
543  for (int c = 0; c < a.getCols (); c++)
544  res.set (r, c, dB (a.get (r, c)));
545  return res;
546 }
547 
554  matrix res (a.getRows (), a.getCols ());
555  for (int r = 0; r < a.getRows (); r++)
556  for (int c = 0; c < a.getCols (); c++)
557  res.set (r, c, arg (a.get (r, c)));
558  return res;
559 }
560 
567  matrix res (a.getRows (), a.getCols ());
568  for (int r = 0; r < a.getRows (); r++)
569  for (int c = 0; c < a.getCols (); c++)
570  res.set (r, c, real (a.get (r, c)));
571  return res;
572 }
573 
580  matrix res (a.getRows (), a.getCols ());
581  for (int r = 0; r < a.getRows (); r++)
582  for (int c = 0; c < a.getCols (); c++)
583  res.set (r, c, imag (a.get (r, c)));
584  return res;
585 }
586 
594 matrix eye (int rs, int cs) {
595  matrix res (rs, cs);
596  for (int r = 0; r < res.getRows (); r++)
597  for (int c = 0; c < res.getCols (); c++)
598  if (r == c) res.set (r, c, 1);
599  return res;
600 }
601 
607 matrix eye (int s) {
608  return eye (s, s);
609 }
610 
616  int size = diag.getSize ();
617  matrix res (size);
618  for (int i = 0; i < size; i++) res (i, i) = diag (i);
619  return res;
620 }
621 
622 // Compute n-th power of the given matrix.
623 matrix pow (matrix a, int n) {
624  matrix res;
625  if (n == 0) {
626  res = eye (a.getRows (), a.getCols ());
627  }
628  else {
629  res = a = n < 0 ? inverse (a) : a;
630  for (int i = 1; i < abs (n); i++)
631  res = res * a;
632  }
633  return res;
634 }
635 
648 nr_complex_t cofactor (matrix a, int u, int v) {
649  matrix res (a.getRows () - 1, a.getCols () - 1);
650  int r, c, ra, ca;
651  for (ra = r = 0; r < res.getRows (); r++, ra++) {
652  if (ra == u) ra++;
653  for (ca = c = 0; c < res.getCols (); c++, ca++) {
654  if (ca == v) ca++;
655  res.set (r, c, a.get (ra, ca));
656  }
657  }
658  nr_complex_t z = detLaplace (res);
659  return ((u + v) & 1) ? -z : z;
660 }
661 
678  assert (a.getRows () == a.getCols ());
679  int s = a.getRows ();
680  nr_complex_t res = 0;
681  if (s > 1) {
682  /* always use the first row for sub-determinant, but you should
683  use the row or column with most zeros in it */
684  int r = 0;
685  for (int i = 0; i < s; i++) {
686  res += a.get (r, i) * cofactor (a, r, i);
687  }
688  return res;
689  }
690  /* 1 by 1 matrix */
691  else if (s == 1) {
692  return a (0, 0);
693  }
694  /* 0 by 0 matrix */
695  return 1;
696 }
697 
709  assert (a.getRows () == a.getCols ());
710  nr_double_t MaxPivot;
711  nr_complex_t f, res;
712  matrix b;
713  int i, c, r, pivot, n = a.getCols ();
714 
715  // return special matrix cases
716  if (n == 0) return 1;
717  if (n == 1) return a (0, 0);
718 
719  // make copy of original matrix
720  b = matrix (a);
721 
722  // triangulate the matrix
723  for (res = 1, i = 0; i < n; i++) {
724  // find maximum column value for pivoting
725  for (MaxPivot = 0, pivot = r = i; r < n; r++) {
726  if (abs (b.get (r, i)) > MaxPivot) {
727  MaxPivot = abs (b.get (r, i));
728  pivot = r;
729  }
730  }
731  // exchange rows if necessary
732  assert (MaxPivot != 0);
733  if (i != pivot) { b.exchangeRows (i, pivot); res = -res; }
734  // compute new rows and columns
735  for (r = i + 1; r < n; r++) {
736  f = b.get (r, i) / b.get (i, i);
737  for (c = i + 1; c < n; c++) {
738  b.set (r, c, b.get (r, c) - f * b.get (i, c));
739  }
740  }
741  }
742 
743  // now compute determinant by multiplying diagonal
744  for (i = 0; i < n; i++) res *= b.get (i, i);
745  return res;
746 }
747 
754 #if 0
755  return detLaplace (a);
756 #else
757  return detGauss (a);
758 #endif
759 }
760 
771  matrix res (a.getRows (), a.getCols ());
772  nr_complex_t d = detLaplace (a);
773  assert (abs (d) != 0); // singular matrix
774  for (int r = 0; r < a.getRows (); r++)
775  for (int c = 0; c < a.getCols (); c++)
776  res.set (r, c, cofactor (a, c, r) / d);
777  return res;
778 }
779 
790  nr_double_t MaxPivot;
791  nr_complex_t f;
792  matrix b, e;
793  int i, c, r, pivot, n = a.getCols ();
794 
795  // create temporary matrix and the result matrix
796  b = matrix (a);
797  e = eye (n);
798 
799  // create the eye matrix in 'b' and the result in 'e'
800  for (i = 0; i < n; i++) {
801  // find maximum column value for pivoting
802  for (MaxPivot = 0, pivot = r = i; r < n; r++) {
803  if (abs (b (r, i)) > MaxPivot) {
804  MaxPivot = abs (b (r, i));
805  pivot = r;
806  }
807  }
808  // exchange rows if necessary
809  assert (MaxPivot != 0); // singular matrix
810  if (i != pivot) {
811  b.exchangeRows (i, pivot);
812  e.exchangeRows (i, pivot);
813  }
814 
815  // compute current row
816  for (f = b (i, i), c = 0; c < n; c++) {
817  b (i, c) /= f;
818  e (i, c) /= f;
819  }
820 
821  // compute new rows and columns
822  for (r = 0; r < n; r++) {
823  if (r != i) {
824  for (f = b (r, i), c = 0; c < n; c++) {
825  b (r, c) -= f * b (i, c);
826  e (r, c) -= f * e (i, c);
827  }
828  }
829  }
830  }
831  return e;
832 }
833 
839 #if 0
840  return inverseLaplace (a);
841 #else
842  return inverseGaussJordan (a);
843 #endif
844 }
845 
882  int d = s.getRows ();
883  matrix e, r, a;
884 
885  assert (d == s.getCols () && d == z0.getSize () && d == zref.getSize ());
886 
887  e = eye (d);
888  r = diagonal ((z0 - zref) / (z0 + zref));
889  a = diagonal (sqrt (z0 / zref) / (z0 + zref));
890  return inverse (a) * (s - r) * inverse (e - r * s) * a;
891 }
892 
902  int d = s.getRows ();
903  return stos (s, vector (d, zref), vector (d, z0));
904 }
905 
914 matrix stos (matrix s, nr_double_t zref, nr_double_t z0) {
915  return stos (s, rect (zref, 0), rect (z0, 0));
916 }
917 
927  return stos (s, zref, vector (zref.getSize (), z0));
928 }
929 
939  return stos (s, vector (z0.getSize (), zref), z0);
940 }
941 
965  int d = s.getRows ();
966  matrix e, zref, gref;
967 
968  assert (d == s.getCols () && d == z0.getSize ());
969 
970  e = eye (d);
971  zref = diagonal (z0);
972  gref = diagonal (sqrt (real (1 / z0)));
973  return inverse (gref) * inverse (e - s) * (s * zref + zref) * gref;
974 }
975 
984  return stoz (s, vector (s.getRows (), z0));
985 }
986 
1010  int d = z.getRows ();
1011  matrix e, zref, gref;
1012 
1013  assert (d == z.getCols () && d == z0.getSize ());
1014 
1015  e = eye (d);
1016  zref = diagonal (z0);
1017  gref = diagonal (sqrt (real (1 / z0)));
1018  return gref * (z - zref) * inverse (z + zref) * inverse (gref);
1019 }
1020 
1029  return ztos (z, vector (z.getRows (), z0));
1030 }
1031 
1042  assert (z.getRows () == z.getCols ());
1043  return inverse (z);
1044 }
1045 
1074  int d = s.getRows ();
1075  matrix e, zref, gref;
1076 
1077  assert (d == s.getCols () && d == z0.getSize ());
1078 
1079  e = eye (d);
1080  zref = diagonal (z0);
1081  gref = diagonal (sqrt (real (1 / z0)));
1082  return inverse (gref) * inverse (s * zref + zref) * (e - s) * gref;
1083 }
1084 
1093  return stoy (s, vector (s.getRows (), z0));
1094 }
1095 
1125  int d = y.getRows ();
1126  matrix e, zref, gref;
1127 
1128  assert (d == y.getCols () && d == z0.getSize ());
1129 
1130  e = eye (d);
1131  zref = diagonal (z0);
1132  gref = diagonal (sqrt (real (1 / z0)));
1133  return gref * (e - zref * y) * inverse (e + zref * y) * inverse (gref);
1134 }
1143  return ytos (y, vector (y.getRows (), z0));
1144 }
1173  nr_complex_t d = s (0, 0) * s (1, 1) - s (0, 1) * s (1, 0);
1174  nr_complex_t n = 2.0 * s (1, 0) * sqrt (fabs (real (z1) * real (z2)));
1175  matrix a (2);
1176 
1177  assert (s.getRows () >= 2 && s.getCols () >= 2);
1178 
1179  a.set (0, 0, (conj (z1) + z1 * s (0, 0) -
1180  conj (z1) * s (1, 1) - z1 * d) / n);
1181  a.set (0, 1, (conj (z1) * conj (z2) + z1 * conj (z2) * s (0, 0) +
1182  conj (z1) * z2 * s (1, 1) + z1 * z2 * d) / n);
1183  a.set (1, 0, (1.0 - s (0, 0) - s (1, 1) + d) / n);
1184  a.set (1, 1, (conj (z2) - conj (z2) * s (0, 0) +
1185  z2 * s (1, 1) - z2 * d) / n);
1186  return a;
1187 }
1188 
1189 
1214  nr_complex_t d = 2.0 * sqrt (fabs (real (z1) * real (z2)));
1215  nr_complex_t n = a (0, 0) * z2 + a (0, 1) +
1216  a (1, 0) * z1 * z2 + a (1, 1) * z1;
1217  matrix s (2);
1218 
1219  assert (a.getRows () >= 2 && a.getCols () >= 2);
1220 
1221  s.set (0, 0, (a (0, 0) * z2 + a (0, 1)
1222  - a (1, 0) * conj (z1) * z2 - a (1, 1) * conj (z1)) / n);
1223  s.set (0, 1, (a (0, 0) * a (1, 1) -
1224  a (0, 1) * a (1, 0)) * d / n);
1225  s.set (1, 0, d / n);
1226  s.set (1, 1, (a (1, 1) * z1 - a (0, 0) * conj (z2) +
1227  a (0, 1) - a (1, 0) * z1 * conj (z2)) / n);
1228  return s;
1229 }
1230 
1261  nr_complex_t n = s (0, 1) * s (1, 0);
1262  nr_complex_t d = (1.0 - s (0, 0)) * (1.0 + s (1, 1)) + n;
1263  matrix h (2);
1264 
1265  assert (s.getRows () >= 2 && s.getCols () >= 2);
1266 
1267  h.set (0, 0, ((1.0 + s (0, 0)) * (1.0 + s (1, 1)) - n) * z1 / d);
1268  h.set (0, 1, +2.0 * s (0, 1) / d);
1269  h.set (1, 0, -2.0 * s (1, 0) / d);
1270  h.set (1, 1, ((1.0 - s (0, 0)) * (1.0 - s (1, 1)) - n) / z2 / d);
1271  return h;
1272 }
1273 
1299  nr_complex_t n = h (0, 1) * h (1, 0);
1300  nr_complex_t d = (1.0 + h (0, 0) / z1) * (1.0 + z2 * h (1, 1)) - n;
1301  matrix s (2);
1302 
1303  assert (h.getRows () >= 2 && h.getCols () >= 2);
1304 
1305  s.set (0, 0, ((h (0, 0) / z1 - 1.0) * (1.0 + z2 * h (1, 1)) - n) / d);
1306  s.set (0, 1, +2.0 * h (0, 1) / d);
1307  s.set (1, 0, -2.0 * h (1, 0) / d);
1308  s.set (1, 1, ((1.0 + h (0, 0) / z1) * (1.0 - z2 * h (1, 1)) + n) / d);
1309  return s;
1310 }
1311 
1312 /*\brief Converts scattering parameters to second hybrid matrix.
1313  \bug{Programmed formulae are valid only for Z real}
1314  \bug{Not documented and references}
1315  \param[in] s Scattering matrix
1316  \param[in] z1 impedance at input 1
1317  \param[in] z2 impedance at input 2
1318  \return second hybrid matrix
1319  \note Assert 2 by 2 matrix
1320  \todo Why not s,z1,z2 const
1321 */
1323  nr_complex_t n = s (0, 1) * s (1, 0);
1324  nr_complex_t d = (1.0 + s (0, 0)) * (1.0 - s (1, 1)) + n;
1325  matrix g (2);
1326 
1327  assert (s.getRows () >= 2 && s.getCols () >= 2);
1328 
1329  g.set (0, 0, ((1.0 - s (0, 0)) * (1.0 - s (1, 1)) - n) / z1 / d);
1330  g.set (0, 1, -2.0 * s (0, 1) / d);
1331  g.set (1, 0, +2.0 * s (1, 0) / d);
1332  g.set (1, 1, ((1.0 + s (0, 0)) * (1.0 + s (1, 1)) - n) * z2 / d);
1333  return g;
1334 }
1335 
1336 /*\brief Converts second hybrid matrix to scattering parameters.
1337  \bug{Programmed formulae are valid only for Z real}
1338  \bug{Not documented and references}
1339  \param[in] g second hybrid matrix
1340  \param[in] z1 impedance at input 1
1341  \param[in] z2 impedance at input 2
1342  \return scattering matrix
1343  \note Assert 2 by 2 matrix
1344  \todo Why not g,z1,z2 const
1345 */
1347  nr_complex_t n = g (0, 1) * g (1, 0);
1348  nr_complex_t d = (1.0 + g (0, 0) * z1) * (1.0 + g (1, 1) / z2) - n;
1349  matrix s (2);
1350 
1351  assert (g.getRows () >= 2 && g.getCols () >= 2);
1352 
1353  s.set (0, 0, ((1.0 - g (0, 0) * z1) * (1.0 + g (1, 1) / z2) + n) / d);
1354  s.set (0, 1, -2.0 * g (0, 1) / d);
1355  s.set (1, 0, +2.0 * g (1, 0) / d);
1356  s.set (1, 1, ((g (0, 0) * z1 + 1.0) * (g (1, 1) / z2 - 1.0) - n) / d);
1357  return s;
1358 }
1359 
1372  assert (y.getRows () == y.getCols ());
1373  return inverse (y);
1374 }
1375 
1396  matrix e = eye (s.getRows ());
1397 
1398  assert (cy.getRows () == cy.getCols () && s.getRows () == s.getCols () &&
1399  cy.getRows () == s.getRows ());
1400 
1401  return (e + s) * cy * adjoint (e + s) / 4;
1402 }
1403 
1422  matrix e = eye (y.getRows ());
1423 
1424  assert (cs.getRows () == cs.getCols () && y.getRows () == y.getCols () &&
1425  cs.getRows () == y.getRows ());
1426 
1427  return (e + y) * cs * adjoint (e + y);
1428 }
1429 
1449  matrix e = eye (s.getRows ());
1450 
1451  assert (cz.getRows () == cz.getCols () && s.getRows () == s.getCols () &&
1452  cz.getRows () == s.getRows ());
1453 
1454  return (e - s) * cz * adjoint (e - s) / 4;
1455 }
1456 
1475  assert (cs.getRows () == cs.getCols () && z.getRows () == z.getCols () &&
1476  cs.getRows () == z.getRows ());
1477  matrix e = eye (z.getRows ());
1478  return (e + z) * cs * adjoint (e + z);
1479 }
1480 
1499  assert (cz.getRows () == cz.getCols () && y.getRows () == y.getCols () &&
1500  cz.getRows () == y.getRows ());
1501 
1502  return y * cz * adjoint (y);
1503 }
1504 
1523  assert (cy.getRows () == cy.getCols () && z.getRows () == z.getCols () &&
1524  cy.getRows () == z.getRows ());
1525  return z * cy * adjoint (z);
1526 }
1527 
1534 void matrix::exchangeRows (int r1, int r2) {
1535  nr_complex_t * s = new nr_complex_t[cols];
1536  int len = sizeof (nr_complex_t) * cols;
1537 
1538  assert (r1 >= 0 && r2 >= 0 && r1 < rows && r2 < rows);
1539 
1540  memcpy (s, &data[r1 * cols], len);
1541  memcpy (&data[r1 * cols], &data[r2 * cols], len);
1542  memcpy (&data[r2 * cols], s, len);
1543  delete[] s;
1544 }
1545 
1552 void matrix::exchangeCols (int c1, int c2) {
1553  nr_complex_t s;
1554 
1555  assert (c1 >= 0 && c2 >= 0 && c1 < cols && c2 < cols);
1556 
1557  for (int r = 0; r < rows * cols; r += cols) {
1558  s = data[r + c1];
1559  data[r + c1] = data[r + c2];
1560  data[r + c2] = s;
1561  }
1562 }
1563 
1585 matrix twoport (matrix m, char in, char out) {
1586  assert (m.getRows () >= 2 && m.getCols () >= 2);
1587  nr_complex_t d;
1588  matrix res (2);
1589 
1590  switch (in) {
1591  case 'Y':
1592  switch (out) {
1593  case 'Y': // Y to Y
1594  res = m;
1595  break;
1596  case 'Z': // Y to Z
1597  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1598  res.set (0, 0, m (1, 1) / d);
1599  res.set (0, 1, -m (0, 1) / d);
1600  res.set (1, 0, -m (1, 0) / d);
1601  res.set (1, 1, m (0, 0) / d);
1602  break;
1603  case 'H': // Y to H
1604  d = m (0, 0);
1605  res.set (0, 0, 1.0 / d);
1606  res.set (0, 1, -m (0, 1) / d);
1607  res.set (1, 0, m (1, 0) / d);
1608  res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
1609  break;
1610  case 'G': // Y to G
1611  d = m (1, 1);
1612  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1613  res.set (0, 1, m (0, 1) / d);
1614  res.set (1, 0, -m (1, 0) / d);
1615  res.set (1, 1, 1.0 / d);
1616  break;
1617  case 'A': // Y to A
1618  d = m (1, 0);
1619  res.set (0, 0, -m (1, 1) / d);
1620  res.set (0, 1, -1.0 / d);
1621  res.set (1, 0, m (0, 1) - m (1, 1) * m (0, 0) / d);
1622  res.set (1, 1, -m (0, 0) / d);
1623  break;
1624  case 'S': // Y to S
1625  res = ytos (m);
1626  break;
1627  }
1628  break;
1629  case 'Z':
1630  switch (out) {
1631  case 'Y': // Z to Y
1632  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1633  res.set (0, 0, m (1, 1) / d);
1634  res.set (0, 1, -m (0, 1) / d);
1635  res.set (1, 0, -m (1, 0) / d);
1636  res.set (1, 1, m (0, 0) / d);
1637  break;
1638  case 'Z': // Z to Z
1639  res = m;
1640  break;
1641  case 'H': // Z to H
1642  d = m (1, 1);
1643  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1644  res.set (0, 1, m (0, 1) / d);
1645  res.set (1, 0, -m (1, 0) / d);
1646  res.set (1, 1, 1.0 / d);
1647  break;
1648  case 'G': // Z to G
1649  d = m (0, 0);
1650  res.set (0, 0, 1.0 / d);
1651  res.set (0, 1, -m (0, 1) / d);
1652  res.set (1, 0, m (1, 0) / d);
1653  res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
1654  break;
1655  case 'A': // Z to A
1656  d = m (1, 0);
1657  res.set (0, 0, m (0, 0) / d);
1658  res.set (0, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
1659  res.set (1, 0, 1.0 / d);
1660  res.set (1, 1, m (1, 1) / d);
1661  break;
1662  case 'S': // Z to S
1663  res = ztos (m);
1664  break;
1665  }
1666  break;
1667  case 'H':
1668  switch (out) {
1669  case 'Y': // H to Y
1670  d = m (0, 0);
1671  res.set (0, 0, 1.0 / d);
1672  res.set (0, 1, -m (0, 1) / d);
1673  res.set (1, 0, m (1, 0) / d);
1674  res.set (1, 1, m (1, 1) - m (0, 1) * m.get(2, 1) / d);
1675  break;
1676  case 'Z': // H to Z
1677  d = m (1, 1);
1678  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1679  res.set (0, 1, m (0, 1) / d);
1680  res.set (1, 0, -m (1, 0) / d);
1681  res.set (1, 1, 1.0 / d);
1682  break;
1683  case 'H': // H to H
1684  res = m;
1685  break;
1686  case 'G': // H to G
1687  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1688  res.set (0, 0, m (1, 1) / d);
1689  res.set (0, 1, -m (0, 1) / d);
1690  res.set (1, 0, -m (1, 0) / d);
1691  res.set (1, 1, m (0, 0) / d);
1692  break;
1693  case 'A': // H to A
1694  d = m (1, 0);
1695  res.set (0, 0, m (0, 1) - m (0, 0) * m (1, 1) / d);
1696  res.set (0, 1, -m (0, 0) / d);
1697  res.set (1, 0, -m (1, 1) / d);
1698  res.set (1, 1, -1.0 / d);
1699  break;
1700  case 'S': // H to S
1701  res = htos (m);
1702  break;
1703  }
1704  break;
1705  case 'G':
1706  switch (out) {
1707  case 'Y': // G to Y
1708  d = m (1, 1);
1709  res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
1710  res.set (0, 1, m (0, 1) / d);
1711  res.set (1, 0, -m (1, 0) / d);
1712  res.set (1, 1, 1.0 / d);
1713  break;
1714  case 'Z': // G to Z
1715  d = m (0, 0);
1716  res.set (0, 0, 1.0 / d);
1717  res.set (0, 1, -m (0, 1) / d);
1718  res.set (1, 0, m (1, 0) / d);
1719  res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
1720  break;
1721  case 'H': // G to H
1722  d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
1723  res.set (0, 0, m (1, 1) / d);
1724  res.set (0, 1, -m (0, 1) / d);
1725  res.set (1, 0, -m (1, 0) / d);
1726  res.set (1, 1, m (0, 0) / d);
1727  break;
1728  case 'G': // G to G
1729  res = m;
1730  break;
1731  case 'A': // G to A
1732  d = m (1, 0);
1733  res.set (0, 0, 1.0 / d);
1734  res.set (0, 1, m (1, 1) / d);
1735  res.set (1, 0, m (0, 0) / d);
1736  res.set (1, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
1737  break;
1738  case 'S': // G to S
1739  res = gtos (m);
1740  break;
1741  }
1742  break;
1743  case 'A':
1744  switch (out) {
1745  case 'Y': // A to Y
1746  d = m (0, 1);
1747  res.set (0, 0, m (1, 1) / d);
1748  res.set (0, 1, m (1, 0) - m (0, 0) * m (1, 1) / d);
1749  res.set (1, 0, -1.0 / d);
1750  res.set (1, 1, m (0, 0) / d);
1751  break;
1752  case 'Z': // A to Z
1753  d = m (1, 0);
1754  res.set (0, 0, m (0, 0) / d);
1755  res.set (0, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
1756  res.set (1, 0, 1.0 / d);
1757  res.set (1, 1, m (1, 1) / d);
1758  break;
1759  case 'H': // A to H
1760  d = m (1, 1);
1761  res.set (0, 0, m (0, 1) / d);
1762  res.set (0, 1, m (0, 0) - m (0, 1) * m (1, 0) / d);
1763  res.set (1, 0, -1.0 / d);
1764  res.set (1, 1, m (1, 0) / d);
1765  break;
1766  case 'G': // A to G
1767  d = m (0, 0);
1768  res.set (0, 0, m (1, 0) / d);
1769  res.set (0, 1, m (1, 0) * m (0, 1) / d - m (1, 1));
1770  res.set (1, 0, 1.0 / d);
1771  res.set (1, 1, m (0, 1) / d);
1772  break;
1773  case 'A': // A to A
1774  res = m;
1775  break;
1776  case 'S': // A to S
1777  res = atos (m);
1778  break;
1779  }
1780  break;
1781  case 'S':
1782  switch (out) {
1783  case 'S': // S to S
1784  res = m;
1785  break;
1786  case 'T': // S to T
1787  d = m (1, 0);
1788  res.set (0, 0, m (0, 1) - m (0, 0) * m (1, 1) / d);
1789  res.set (0, 1, m (0, 0) / d);
1790  res.set (1, 0, -m (1, 1) / d);
1791  res.set (0, 1, 1.0 / d);
1792  break;
1793  case 'A': // S to A
1794  res = stoa (m);
1795  break;
1796  case 'H': // S to H
1797  res = stoh (m);
1798  break;
1799  case 'G': // S to G
1800  res = stog (m);
1801  break;
1802  case 'Y': // S to Y
1803  res = stoy (m);
1804  break;
1805  case 'Z': // S to Z
1806  res = stoz (m);
1807  break;
1808  }
1809  break;
1810  case 'T':
1811  switch (out) {
1812  case 'S': // T to S
1813  d = m (1, 1);
1814  res.set (0, 0, m (0, 1) / d);
1815  res.set (0, 1, m (0, 0) - m (0, 1) * m (1, 0) / d);
1816  res.set (1, 0, 1.0 / d);
1817  res.set (0, 1, -m (1, 0) / d);
1818  break;
1819  case 'T': // T to T
1820  res = m;
1821  break;
1822  }
1823  break;
1824  }
1825  return res;
1826 }
1827 
1845 nr_double_t rollet (matrix m) {
1846  assert (m.getRows () >= 2 && m.getCols () >= 2);
1847  nr_double_t res;
1848  res = (1 - norm (m (0, 0)) - norm (m (1, 1)) + norm (det (m))) /
1849  2 / abs (m (0, 1) * m (1, 0));
1850  return res;
1851 }
1852 
1853 /* Computes stability measure B1 of the given S-parameter matrix. */
1854 nr_double_t b1 (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  return res;
1859 }