LCOV - code coverage report
Current view: top level - src/math - matrix.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 162 656 24.7 %
Date: 2015-01-05 16:01:02 Functions: 27 86 31.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 194 1682 11.5 %

           Branch data     Line data    Source code
       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                 :            :  */
      24                 :            : /*!\file matrix.cpp
      25                 :            :    \brief Dense matrix class implementation
      26                 :            : 
      27                 :            :   References:
      28                 :            : 
      29                 :            :   [1] Power Waves and the Scattering Matrix
      30                 :            :       Kurokawa, K.
      31                 :            :       Microwave Theory and Techniques, IEEE Transactions on,
      32                 :            :       Vol.13, Iss.2, Mar 1965
      33                 :            :       Pages: 194- 202
      34                 :            : 
      35                 :            :   [2] A Rigorous Technique for Measuring the Scattering Matrix of
      36                 :            :       a Multiport Device with a 2-Port Network Analyzer
      37                 :            :       John C. TIPPET, Ross A. SPECIALE
      38                 :            :       Microwave Theory and Techniques, IEEE Transactions on,
      39                 :            :       Vol.82, Iss.5, May 1982
      40                 :            :       Pages: 661- 666
      41                 :            : 
      42                 :            :   [3] Comments on "A Rigorous Techique for Measuring the Scattering
      43                 :            :       Matrix of a Multiport Device with a Two-Port Network Analyzer"
      44                 :            :       Dropkin, H.
      45                 :            :       Microwave Theory and Techniques, IEEE Transactions on,
      46                 :            :       Vol. 83, Iss.1, Jan 1983
      47                 :            :       Pages: 79 - 81
      48                 :            : 
      49                 :            :   [4] Arbitrary Impedance
      50                 :            :       "Accurate Measurements In Almost Any
      51                 :            :       Impedance Environment"
      52                 :            :       in Scropion Application note
      53                 :            :       Anritsu
      54                 :            :       online(2007/07/30) http://www.eu.anritsu.com/files/11410-00284B.pdf
      55                 :            : 
      56                 :            :   [5] Conversions between S, Z, Y, H, ABCD, and T parameters
      57                 :            :       which are valid for complex source and load impedances
      58                 :            :       Frickey, D.A.
      59                 :            :       Microwave Theory and Techniques, IEEE Transactions on
      60                 :            :       Vol. 42, Iss. 2, Feb 1994
      61                 :            :       pages: 205 - 211
      62                 :            :       doi: 10.1109/22.275248
      63                 :            : 
      64                 :            :   [6] Comments on "Conversions between S, Z, Y, h, ABCD,
      65                 :            :       and T parameters which are valid for complex source and load impedances" [and reply]
      66                 :            :       Marks, R.B.; Williams, D.F.; Frickey, D.A.
      67                 :            :       Microwave Theory and Techniques, IEEE Transactions on,
      68                 :            :       Vol.43, Iss.4, Apr 1995
      69                 :            :       Pages: 914- 915
      70                 :            :       doi: 10.1109/22.375247
      71                 :            : 
      72                 :            :   [7] Wave Techniques for Noise Modeling and Measurement
      73                 :            :       S. W. Wedge and D. B. Rutledge,
      74                 :            :       IEEE Transactions on Microwave Theory and Techniques,
      75                 :            :       vol. 40, no. 11, Nov. 1992.
      76                 :            :       pages 2004-2012,
      77                 :            :       doi: 10.1109/22.168757
      78                 :            :       Author copy online (2007/07/31)
      79                 :            :       http://authors.library.caltech.edu/6226/01/WEDieeetmtt92.pdf
      80                 :            : 
      81                 :            : */
      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                 :            : 
     100                 :            : /*!\brief Create an empty matrix
     101                 :            : 
     102                 :            :    Constructor creates an unnamed instance of the matrix class.
     103                 :            : */
     104                 :      13273 : matrix::matrix () {
     105                 :      13273 :   rows = 0;
     106                 :      13273 :   cols = 0;
     107                 :      13273 :   data = NULL;
     108                 :      13273 : }
     109                 :            : 
     110                 :            : /*!\brief Creates a square matrix
     111                 :            : 
     112                 :            :     Constructor creates an unnamed instance of the matrix class with a
     113                 :            :     certain number of rows and columns.  Particularly creates a square matrix.
     114                 :            :     \param[in] s number of rows or colums of square matrix
     115                 :            :     \todo Why not s const?
     116                 :            : */
     117                 :       5950 : matrix::matrix (int s)  {
     118                 :       5950 :   rows = cols = s;
     119 [ +  - ][ +  + ]:     108950 :   data = (s > 0) ? new nr_complex_t[s * s] : NULL;
         [ #  # ][ #  # ]
     120                 :       5950 : }
     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                 :      15913 : matrix::matrix (int r, int c)  {
     132                 :      15913 :   rows = r;
     133                 :      15913 :   cols = c;
     134 [ +  - ][ +  - ]:     257152 :   data = (r > 0 && c > 0) ? new nr_complex_t[r * c] : NULL;
         [ +  + ][ #  # ]
         [ #  # ][ #  # ]
     135                 :      15913 : }
     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                 :      13130 : matrix::matrix (const matrix & m) {
     144                 :      13130 :   rows = m.rows;
     145                 :      13130 :   cols = m.cols;
     146                 :      13130 :   data = NULL;
     147                 :            : 
     148                 :            :   // copy matrix elements
     149 [ +  - ][ +  - ]:      13130 :   if (rows > 0 && cols > 0) {
         [ #  # ][ #  # ]
     150 [ +  + ][ #  # ]:     255730 :     data = new nr_complex_t[rows * cols];
     151                 :      13130 :     memcpy (data, m.data, sizeof (nr_complex_t) * rows * cols);
     152                 :            :   }
     153                 :      13130 : }
     154                 :            : 
     155                 :            : /*!\brief Assignment operator
     156                 :            : 
     157                 :            :   The assignment copy constructor creates a new instance based on the
     158                 :            :   given matrix object.
     159                 :            : 
     160                 :            :   \param[in] m object to copy
     161                 :            :   \return assigned object
     162                 :            :   \note m = m is safe
     163                 :            : */
     164                 :      13273 : const matrix& matrix::operator=(const matrix & m) {
     165         [ +  - ]:      13273 :   if (&m != this) {
     166                 :      13273 :     rows = m.rows;
     167                 :      13273 :     cols = m.cols;
     168         [ -  + ]:      13273 :     if (data) {
     169         [ #  # ]:          0 :       delete[] data;
     170                 :          0 :       data = NULL;
     171                 :            :     }
     172 [ +  - ][ +  - ]:      13273 :     if (rows > 0 && cols > 0) {
     173         [ +  + ]:     148912 :       data = new nr_complex_t[rows * cols];
     174                 :      13273 :       memcpy (data, m.data, sizeof (nr_complex_t) * rows * cols);
     175                 :            :     }
     176                 :            :   }
     177                 :      13273 :   return *this;
     178                 :            : }
     179                 :            : 
     180                 :            : /*!\bried Destructor
     181                 :            : 
     182                 :            :    Destructor deletes a matrix object.
     183                 :            : */
     184                 :      48266 : matrix::~matrix () {
     185 [ +  - ][ +  - ]:      48266 :   if (data) delete[] data;
         [ #  # ][ #  # ]
     186                 :      48266 : }
     187                 :            : 
     188                 :            : /*!\brief  Returns the matrix element at the given row and column.
     189                 :            :    \param[in] r row number
     190                 :            :    \param[in] c column number
     191                 :            :    \todo Why not inline and synonymous of ()
     192                 :            :    \todo c and r const
     193                 :            : */
     194                 :    1394550 : nr_complex_t matrix::get (int r, int c) {
     195                 :    1394550 :   return data[r * cols + c];
     196                 :            : }
     197                 :            : 
     198                 :            : /*!\brief Sets the matrix element at the given row and column.
     199                 :            :    \param[in] r row number
     200                 :            :    \param[in] c column number
     201                 :            :    \param[in] z complex number to assign
     202                 :            :    \todo Why not inline and synonymous of ()
     203                 :            :    \todo r c and z const
     204                 :            : */
     205                 :     248237 : void matrix::set (int r, int c, nr_complex_t z) {
     206                 :     248237 :   data[r * cols + c] = z;
     207                 :     248237 : }
     208                 :            : 
     209                 :            : #ifdef DEBUG
     210                 :            : /*!\brief Debug function: Prints the matrix object */
     211                 :          0 : void matrix::print (void) {
     212         [ #  # ]:          0 :   for (int r = 0; r < rows; r++) {
     213         [ #  # ]:          0 :     for (int c = 0; c < cols; c++) {
     214                 :            :       fprintf (stderr, "%+.2e,%+.2e ", (double) real (get (r, c)),
     215         [ #  # ]:          0 :                (double) imag (get (r, c)));
     216                 :            :     }
     217                 :          0 :     fprintf (stderr, "\n");
     218                 :            :   }
     219                 :          0 : }
     220                 :            : #endif /* DEBUG */
     221                 :            : 
     222                 :            : /*!\brief Matrix addition.
     223                 :            :    \param[a] first matrix
     224                 :            :    \param[b] second matrix
     225                 :            :    \note assert same size
     226                 :            :    \todo a and b are const
     227                 :            : */
     228                 :       1210 : matrix operator + (matrix a, matrix b) {
     229 [ +  - ][ -  + ]:       1210 :   assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
                 [ -  + ]
     230                 :            : 
     231                 :       1210 :   matrix res (a.getRows (), a.getCols ());
     232         [ +  + ]:       6110 :   for (int r = 0; r < a.getRows (); r++)
     233         [ +  + ]:      34700 :     for (int c = 0; c < a.getCols (); c++)
     234         [ +  - ]:      29800 :       res.set (r, c, a.get (r, c) + b.get (r, c));
     235                 :       1210 :   return res;
     236                 :            : }
     237                 :            : 
     238                 :            : /*!\brief Intrinsic matrix addition.
     239                 :            :    \param[in] a matrix to add
     240                 :            :    \note assert same size
     241                 :            :    \todo a is const
     242                 :            : */
     243                 :          0 : matrix matrix::operator += (matrix a) {
     244 [ #  # ][ #  # ]:          0 :   assert (a.getRows () == rows && a.getCols () == cols);
                 [ #  # ]
     245                 :            : 
     246                 :            :   int r, c, i;
     247         [ #  # ]:          0 :   for (i = 0, r = 0; r < a.getRows (); r++)
     248         [ #  # ]:          0 :     for (c = 0; c < a.getCols (); c++, i++)
     249                 :          0 :       data[i] += a.get (r, c);
     250                 :          0 :   return *this;
     251                 :            : }
     252                 :            : 
     253                 :            : /*!\brief Matrix subtraction.
     254                 :            :    \param[a] first matrix
     255                 :            :    \param[b] second matrix
     256                 :            :    \note assert same size
     257                 :            :    \todo a and b are const
     258                 :            : */
     259                 :       1070 : matrix operator - (matrix a, matrix b) {
     260 [ +  - ][ -  + ]:       1070 :   assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
                 [ -  + ]
     261                 :            : 
     262                 :       1070 :   matrix res (a.getRows (), a.getCols ());
     263         [ +  + ]:       4570 :   for (int r = 0; r < a.getRows (); r++)
     264         [ +  + ]:      19300 :     for (int c = 0; c < a.getCols (); c++)
     265         [ +  - ]:      15800 :       res.set (r, c, a.get (r, c) - b.get (r, c));
     266                 :       1070 :   return res;
     267                 :            : }
     268                 :            : 
     269                 :            : /*!\brief Unary minus. */
     270                 :          0 : matrix matrix::operator - () {
     271                 :          0 :   matrix res (getRows (), getCols ());
     272                 :            :   int r, c, i;
     273         [ #  # ]:          0 :   for (i = 0, r = 0; r < getRows (); r++)
     274         [ #  # ]:          0 :     for (c = 0; c < getCols (); c++, i++)
     275                 :          0 :       res.set (r, c, -data[i]);
     276                 :          0 :   return res;
     277                 :            : }
     278                 :            : 
     279                 :            : /*!\brief Intrinsic matrix subtraction.
     280                 :            :    \param[in] a matrix to substract
     281                 :            :    \note assert same size
     282                 :            : */
     283                 :          0 : matrix matrix::operator -= (matrix a) {
     284 [ #  # ][ #  # ]:          0 :   assert (a.getRows () == rows && a.getCols () == cols);
                 [ #  # ]
     285                 :            :   int r, c, i;
     286         [ #  # ]:          0 :   for (i = 0, r = 0; r < a.getRows (); r++)
     287         [ #  # ]:          0 :     for (c = 0; c < a.getCols (); c++, i++)
     288                 :          0 :       data[i] -= a.get (r, c);
     289                 :          0 :   return *this;
     290                 :            : }
     291                 :            : 
     292                 :            : /*!\brief Matrix scaling complex version
     293                 :            :    \param[in] a matrix to scale
     294                 :            :    \param[in] z scaling complex
     295                 :            :    \return Scaled matrix
     296                 :            :    \todo Why not a and z const
     297                 :            : */
     298                 :          0 : matrix operator * (matrix a, nr_complex_t z) {
     299                 :          0 :   matrix res (a.getRows (), a.getCols ());
     300         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     301         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     302         [ #  # ]:          0 :       res.set (r, c, a.get (r, c) * z);
     303                 :          0 :   return res;
     304                 :            : }
     305                 :            : 
     306                 :            : /*!\brief Matrix scaling complex version (different order)
     307                 :            :    \param[in] a matrix to scale
     308                 :            :    \param[in] z scaling complex
     309                 :            :    \return Scaled matrix
     310                 :            :    \todo Why not a and z const
     311                 :            :    \todo Why not inline
     312                 :            : */
     313                 :          0 : matrix operator * (nr_complex_t z, matrix a) {
     314         [ #  # ]:          0 :   return a * z;
     315                 :            : }
     316                 :            : 
     317                 :            : /*!\brief Matrix scaling complex version
     318                 :            :    \param[in] a matrix to scale
     319                 :            :    \param[in] d scaling real
     320                 :            :    \return Scaled matrix
     321                 :            :    \todo Why not d and a const
     322                 :            : */
     323                 :         70 : matrix operator * (matrix a, nr_double_t d) {
     324                 :         70 :   matrix res (a.getRows (), a.getCols ());
     325         [ +  + ]:        770 :   for (int r = 0; r < a.getRows (); r++)
     326         [ +  + ]:       7700 :     for (int c = 0; c < a.getCols (); c++)
     327                 :       7000 :       res.set (r, c, a.get (r, c) * d);
     328                 :         70 :   return res;
     329                 :            : }
     330                 :            : 
     331                 :            : /*!\brief Matrix scaling real version (different order)
     332                 :            :    \param[in] a matrix to scale
     333                 :            :    \param[in] d scaling real
     334                 :            :    \return Scaled matrix
     335                 :            :    \todo Why not inline?
     336                 :            :    \todo Why not d and a const
     337                 :            : */
     338                 :          0 : matrix operator * (nr_double_t d, matrix a) {
     339         [ #  # ]:          0 :   return a * d;
     340                 :            : }
     341                 :            : 
     342                 :            : /*!\brief Matrix scaling division by complex version
     343                 :            :    \param[in] a matrix to scale
     344                 :            :    \param[in] z scaling complex
     345                 :            :    \return Scaled matrix
     346                 :            :    \todo Why not a and z const
     347                 :            : */
     348                 :          0 : matrix operator / (matrix a, nr_complex_t z) {
     349                 :          0 :   matrix res (a.getRows (), a.getCols ());
     350         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     351         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     352         [ #  # ]:          0 :       res.set (r, c, a.get (r, c) / z);
     353                 :          0 :   return res;
     354                 :            : }
     355                 :            : 
     356                 :            : /*!\brief Matrix scaling division by real version
     357                 :            :    \param[in] a matrix to scale
     358                 :            :    \param[in] d scaling real
     359                 :            :    \return Scaled matrix
     360                 :            :    \todo Why not a and d const
     361                 :            : */
     362                 :         70 : matrix operator / (matrix a, nr_double_t d) {
     363                 :         70 :   matrix res (a.getRows (), a.getCols ());
     364         [ +  + ]:        770 :   for (int r = 0; r < a.getRows (); r++)
     365         [ +  + ]:       7700 :     for (int c = 0; c < a.getCols (); c++)
     366                 :       7000 :       res.set (r, c, a.get (r, c) / d);
     367                 :         70 :   return res;
     368                 :            : }
     369                 :            : 
     370                 :            : /*! Matrix multiplication.
     371                 :            : 
     372                 :            :     Dumb and not optimized matrix multiplication
     373                 :            :     \param[a] first matrix
     374                 :            :     \param[b] second matrix
     375                 :            :     \note assert compatibility
     376                 :            :     \todo a and b are const
     377                 :            : */
     378                 :       4290 : matrix operator * (matrix a, matrix b) {
     379         [ -  + ]:       4290 :   assert (a.getCols () == b.getRows ());
     380                 :            : 
     381                 :       4290 :   int r, c, i, n = a.getCols ();
     382                 :       4290 :   nr_complex_t z;
     383         [ +  - ]:       4290 :   matrix res (a.getRows (), b.getCols ());
     384         [ +  + ]:      20790 :   for (r = 0; r < a.getRows (); r++) {
     385         [ +  + ]:     104700 :     for (c = 0; c < b.getCols (); c++) {
     386 [ +  - ][ +  + ]:     720600 :       for (i = 0, z = 0; i < n; i++) z += a.get (r, i) * b.get (i, c);
     387                 :      88200 :       res.set (r, c, z);
     388                 :            :     }
     389                 :            :   }
     390                 :       4290 :   return res;
     391                 :            : }
     392                 :            : 
     393                 :            : /*!\brief Complex scalar addition.
     394                 :            :    \param[in] a matrix
     395                 :            :    \param[in] z complex to add
     396                 :            :    \todo Move near other +
     397                 :            :    \todo a and z are const
     398                 :            : */
     399                 :          0 : matrix operator + (matrix a, nr_complex_t z) {
     400                 :          0 :   matrix res (a.getRows (), a.getCols ());
     401         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     402         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     403         [ #  # ]:          0 :       res.set (r, c, a.get (r, c) + z);
     404                 :          0 :   return res;
     405                 :            : }
     406                 :            : 
     407                 :            : /*!\brief Complex scalar addition different order.
     408                 :            :    \param[in] a matrix
     409                 :            :    \param[in] z complex to add
     410                 :            :    \todo Move near other +
     411                 :            :    \todo a and z are const
     412                 :            :    \todo Why not inline
     413                 :            : */
     414                 :          0 : matrix operator + (nr_complex_t z, matrix a) {
     415         [ #  # ]:          0 :   return a + z;
     416                 :            : }
     417                 :            : 
     418                 :            : /*!\brief Real scalar addition.
     419                 :            :    \param[in] a matrix
     420                 :            :    \param[in] d real to add
     421                 :            :    \todo Move near other +
     422                 :            :    \todo a and d are const
     423                 :            : */
     424                 :          0 : matrix operator + (matrix a, nr_double_t d) {
     425                 :          0 :   matrix res (a.getRows (), a.getCols ());
     426         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     427         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     428                 :          0 :       res.set (r, c, a.get (r, c) + d);
     429                 :          0 :   return res;
     430                 :            : }
     431                 :            : 
     432                 :            : /*!\brief Real scalar addition different order.
     433                 :            :    \param[in] a matrix
     434                 :            :    \param[in] d real to add
     435                 :            :    \todo Move near other +
     436                 :            :    \todo a and d are const
     437                 :            :    \todo Why not inline
     438                 :            : */
     439                 :          0 : matrix operator + (nr_double_t d, matrix a) {
     440         [ #  # ]:          0 :   return a + d;
     441                 :            : }
     442                 :            : 
     443                 :            : /*!\brief Complex scalar substraction
     444                 :            :    \param[in] a matrix
     445                 :            :    \param[in] z complex to add
     446                 :            :    \todo Move near other +
     447                 :            :    \todo a and z are const
     448                 :            :    \todo Why not inline
     449                 :            : */
     450                 :          0 : matrix operator - (matrix a, nr_complex_t z) {
     451         [ #  # ]:          0 :   return -z + a;
     452                 :            : }
     453                 :            : 
     454                 :            : /*!\brief Complex scalar substraction different order
     455                 :            :    \param[in] a matrix
     456                 :            :    \param[in] z complex to add
     457                 :            :    \todo Move near other +
     458                 :            :    \todo a and z are const
     459                 :            :    \todo Why not inline
     460                 :            : */
     461                 :          0 : matrix operator - (nr_complex_t z, matrix a) {
     462         [ #  # ]:          0 :   return -a + z;
     463                 :            : }
     464                 :            : 
     465                 :            : /*!\brief Real scalar substraction
     466                 :            :    \param[in] a matrix
     467                 :            :    \param[in] z real to add
     468                 :            :    \todo Move near other +
     469                 :            :    \todo a and z are const
     470                 :            :    \todo Why not inline
     471                 :            : */
     472                 :          0 : matrix operator - (matrix a, nr_double_t d) {
     473         [ #  # ]:          0 :   return -d + a;
     474                 :            : }
     475                 :            : 
     476                 :            : /*!\brief Real scalar substraction different order
     477                 :            :    \param[in] a matrix
     478                 :            :    \param[in] z real to add
     479                 :            :    \todo Move near other +
     480                 :            :    \todo a and z are const
     481                 :            :    \todo Why not inline
     482                 :            : */
     483                 :          0 : matrix operator - (nr_double_t d, matrix a) {
     484         [ #  # ]:          0 :   return -a + d;
     485                 :            : }
     486                 :            : 
     487                 :            : /*!\brief Matrix transposition
     488                 :            :    \param[in] a Matrix to transpose
     489                 :            :    \todo add transpose in place
     490                 :            :    \todo a is const
     491                 :            : */
     492                 :         70 : matrix transpose (matrix a) {
     493                 :         70 :   matrix res (a.getCols (), a.getRows ());
     494         [ +  + ]:        770 :   for (int r = 0; r < a.getRows (); r++)
     495         [ +  + ]:       7700 :     for (int c = 0; c < a.getCols (); c++)
     496                 :       7000 :       res.set (c, r, a.get (r, c));
     497                 :         70 :   return res;
     498                 :            : }
     499                 :            : 
     500                 :            : /*!\brief Conjugate complex matrix.
     501                 :            :   \param[in] a Matrix to conjugate
     502                 :            :   \todo add conj in place
     503                 :            :   \todo a is const
     504                 :            : */
     505                 :         70 : matrix conj (matrix a) {
     506                 :         70 :   matrix res (a.getRows (), a.getCols ());
     507         [ +  + ]:        770 :   for (int r = 0; r < a.getRows (); r++)
     508         [ +  + ]:       7700 :     for (int c = 0; c < a.getCols (); c++)
     509                 :       7000 :       res.set (r, c, conj (a.get (r, c)));
     510                 :         70 :   return res;
     511                 :            : }
     512                 :            : 
     513                 :            : /*!\brief adjoint matrix
     514                 :            : 
     515                 :            :    The function returns the adjoint complex matrix.  This is also
     516                 :            :    called the adjugate or transpose conjugate.
     517                 :            :    \param[in] a Matrix to transpose
     518                 :            :    \todo add adjoint in place
     519                 :            :    \todo Do not lazy and avoid conj and transpose copy
     520                 :            :    \todo a is const
     521                 :            : */
     522                 :         70 : matrix adjoint (matrix a) {
     523 [ +  - ][ +  - ]:         70 :   return transpose (conj (a));
     524                 :            : }
     525                 :            : 
     526                 :            : /*!\brief Computes magnitude of each matrix element.
     527                 :            :    \param[in] a matrix
     528                 :            :    \todo add abs in place
     529                 :            :    \todo a is const
     530                 :            : */
     531                 :          0 : matrix abs (matrix a) {
     532                 :          0 :   matrix res (a.getRows (), a.getCols ());
     533         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     534         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     535                 :          0 :       res.set (r, c, abs (a.get (r, c)));
     536                 :          0 :   return res;
     537                 :            : }
     538                 :            : 
     539                 :            : /*!\brief Computes magnitude in dB of each matrix element.
     540                 :            :    \param[in] a matrix
     541                 :            : */
     542                 :          0 : matrix dB (matrix a) {
     543                 :          0 :   matrix res (a.getRows (), a.getCols ());
     544         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     545         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     546         [ #  # ]:          0 :       res.set (r, c, dB (a.get (r, c)));
     547                 :          0 :   return res;
     548                 :            : }
     549                 :            : 
     550                 :            : /*!\brief Computes the argument of each matrix element.
     551                 :            :    \param[in] a matrix
     552                 :            :    \todo add arg in place
     553                 :            :    \todo a is const
     554                 :            : */
     555                 :          0 : matrix arg (matrix a) {
     556                 :          0 :   matrix res (a.getRows (), a.getCols ());
     557         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     558         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     559                 :          0 :       res.set (r, c, arg (a.get (r, c)));
     560                 :          0 :   return res;
     561                 :            : }
     562                 :            : 
     563                 :            : /*!\brief Real part matrix.
     564                 :            :    \param[in] a matrix
     565                 :            :    \todo add real in place
     566                 :            :    \todo a is const
     567                 :            : */
     568                 :          0 : matrix real (matrix a) {
     569                 :          0 :   matrix res (a.getRows (), a.getCols ());
     570         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     571         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     572                 :          0 :       res.set (r, c, real (a.get (r, c)));
     573                 :          0 :   return res;
     574                 :            : }
     575                 :            : 
     576                 :            : /*!\brief Imaginary part matrix.
     577                 :            :    \param[in] a matrix
     578                 :            :    \todo add imag in place
     579                 :            :    \todo a is const
     580                 :            : */
     581                 :          0 : matrix imag (matrix a) {
     582                 :          0 :   matrix res (a.getRows (), a.getCols ());
     583         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     584         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     585                 :          0 :       res.set (r, c, imag (a.get (r, c)));
     586                 :          0 :   return res;
     587                 :            : }
     588                 :            : 
     589                 :            : /*!\brief Multiply a matrix by itself
     590                 :            :    \param[in] a matrix
     591                 :            : */
     592                 :          0 : matrix sqr (matrix a) {
     593 [ #  # ][ #  # ]:          0 :   return a * a;
     594                 :            : }
     595                 :            : 
     596                 :            : /*!\brief Create identity matrix with specified number of rows and columns.
     597                 :            :    \param[in] rs row number
     598                 :            :    \param[in] cs column number
     599                 :            :    \todo Avoid res.get*
     600                 :            :    \todo Use memset
     601                 :            :    \todo rs, cs are const
     602                 :            : */
     603                 :       3280 : matrix eye (int rs, int cs) {
     604                 :       3280 :   matrix res (rs, cs);
     605         [ +  + ]:      14480 :   for (int r = 0; r < res.getRows (); r++)
     606         [ +  + ]:      65600 :     for (int c = 0; c < res.getCols (); c++)
     607         [ +  + ]:      54400 :       if (r == c) res.set (r, c, 1);
     608                 :       3280 :   return res;
     609                 :            : }
     610                 :            : 
     611                 :            : /*!\brief Create a square identity matrix
     612                 :            :    \param[in] s row or column number of square matrix
     613                 :            :    \todo Do not by lazy and implement it
     614                 :            :    \todo s is const
     615                 :            : */
     616                 :       3280 : matrix eye (int s) {
     617                 :       3280 :   return eye (s, s);
     618                 :            : }
     619                 :            : 
     620                 :            : /*!\brief Create a diagonal matrix from a vector
     621                 :            :    \param[in] diag vector to write on the diagonal
     622                 :            :    \todo diag is const
     623                 :            : */
     624                 :       2140 : matrix diagonal (qucs::vector diag) {
     625                 :       2140 :   int size = diag.getSize ();
     626                 :       2140 :   matrix res (size);
     627         [ +  + ]:       9140 :   for (int i = 0; i < size; i++) res (i, i) = diag (i);
     628                 :       2140 :   return res;
     629                 :            : }
     630                 :            : 
     631                 :            : // Compute n-th power of the given matrix.
     632                 :          0 : matrix pow (matrix a, int n) {
     633                 :          0 :   matrix res;
     634         [ #  # ]:          0 :   if (n == 0) {
     635 [ #  # ][ #  # ]:          0 :     res = eye (a.getRows (), a.getCols ());
     636                 :            :   }
     637                 :            :   else {
     638 [ #  # ][ #  # ]:          0 :     res = a = n < 0 ? inverse (a) : a;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     639         [ #  # ]:          0 :     for (int i = 1; i < std::abs (n); i++)
     640 [ #  # ][ #  # ]:          0 :       res = res * a;
         [ #  # ][ #  # ]
     641                 :            :   }
     642                 :          0 :   return res;
     643                 :            : }
     644                 :            : 
     645                 :            : /*!\brief Computes the complex cofactor of the given determinant
     646                 :            : 
     647                 :            :    The cofactor is the determinant obtained by deleting the row and column
     648                 :            :    of a given element of a matrix or determinant.
     649                 :            :    The cofactor is preceded by a + or - sign depending of the sign
     650                 :            :    of \f$(-1)^(u+v)\f$
     651                 :            : 
     652                 :            :    \bug This algortihm is recursive! Stack overfull!
     653                 :            :    \todo ((u + v) & 1) is cryptic use (u + v)% 2
     654                 :            :    \todo #ifdef 0
     655                 :            :    \todo static?
     656                 :            : */
     657                 :          0 : nr_complex_t cofactor (matrix a, int u, int v) {
     658         [ #  # ]:          0 :   matrix res (a.getRows () - 1, a.getCols () - 1);
     659                 :            :   int r, c, ra, ca;
     660         [ #  # ]:          0 :   for (ra = r = 0; r < res.getRows (); r++, ra++) {
     661         [ #  # ]:          0 :     if (ra == u) ra++;
     662         [ #  # ]:          0 :     for (ca = c = 0; c < res.getCols (); c++, ca++) {
     663         [ #  # ]:          0 :       if (ca == v) ca++;
     664                 :          0 :       res.set (r, c, a.get (ra, ca));
     665                 :            :     }
     666                 :            :   }
     667 [ #  # ][ #  # ]:          0 :   nr_complex_t z = detLaplace (res);
     668         [ #  # ]:          0 :   return ((u + v) & 1) ? -z : z;
     669                 :            : }
     670                 :            : 
     671                 :            : /*!\brief Compute determinant of the given matrix using Laplace expansion.
     672                 :            : 
     673                 :            :    The Laplace expansion  of the determinant of
     674                 :            :    an n by n square matrix a expresses
     675                 :            :    the determinant of a as a sum of n determinants of (n-1) by  (n-1)
     676                 :            :    sub-matrices of a.  There are 2n such expressions, one for each row
     677                 :            :    and column of a.
     678                 :            : 
     679                 :            :    See Wikipedia http://en.wikipedia.org/wiki/Laplace_expansion
     680                 :            :    \param[in] a matrix
     681                 :            :    \bug This algortihm is recursive! Stack overfull!
     682                 :            :    \note assert square matrix
     683                 :            :    \todo #ifdef 0
     684                 :            :    \todo static ?
     685                 :            : */
     686                 :          0 : nr_complex_t detLaplace (matrix a) {
     687         [ #  # ]:          0 :   assert (a.getRows () == a.getCols ());
     688                 :          0 :   int s = a.getRows ();
     689                 :          0 :   nr_complex_t res = 0;
     690         [ #  # ]:          0 :   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                 :          0 :     int r = 0;
     694         [ #  # ]:          0 :     for (int i = 0; i < s; i++) {
     695 [ #  # ][ #  # ]:          0 :       res += a.get (r, i) * cofactor (a, r, i);
                 [ #  # ]
     696                 :            :     }
     697                 :          0 :     return res;
     698                 :            :   }
     699                 :            :   /* 1 by 1 matrix */
     700         [ #  # ]:          0 :   else if (s == 1) {
     701                 :          0 :     return a (0, 0);
     702                 :            :   }
     703                 :            :   /* 0 by 0 matrix */
     704                 :          0 :   return 1;
     705                 :            : }
     706                 :            : 
     707                 :            : /*!\brief Compute determinant Gaussian algorithm
     708                 :            : 
     709                 :            :    Compute determinant of the given matrix using the Gaussian
     710                 :            :    algorithm.  This means to triangulate the matrix and multiply all
     711                 :            :    the diagonal elements.
     712                 :            :    \param[in] a matrix
     713                 :            :    \note assert square matrix
     714                 :            :    \todo static ?
     715                 :            :    \todo a const?
     716                 :            :    */
     717                 :          0 : nr_complex_t detGauss (matrix a) {
     718         [ #  # ]:          0 :   assert (a.getRows () == a.getCols ());
     719                 :            :   nr_double_t MaxPivot;
     720                 :          0 :   nr_complex_t f, res;
     721                 :          0 :   matrix b;
     722                 :          0 :   int i, c, r, pivot, n = a.getCols ();
     723                 :            : 
     724                 :            :   // return special matrix cases
     725         [ #  # ]:          0 :   if (n == 0) return 1;
     726         [ #  # ]:          0 :   if (n == 1) return a (0, 0);
     727                 :            : 
     728                 :            :   // make copy of original matrix
     729 [ #  # ][ #  # ]:          0 :   b = matrix (a);
     730                 :            : 
     731                 :            :   // triangulate the matrix
     732         [ #  # ]:          0 :   for (res = 1, i = 0; i < n; i++) {
     733                 :            :     // find maximum column value for pivoting
     734         [ #  # ]:          0 :     for (MaxPivot = 0, pivot = r = i; r < n; r++) {
     735         [ #  # ]:          0 :       if (abs (b.get (r, i)) > MaxPivot) {
     736                 :          0 :         MaxPivot = abs (b.get (r, i));
     737                 :          0 :         pivot = r;
     738                 :            :       }
     739                 :            :     }
     740                 :            :     // exchange rows if necessary
     741         [ #  # ]:          0 :     assert (MaxPivot != 0);
     742 [ #  # ][ #  # ]:          0 :     if (i != pivot) { b.exchangeRows (i, pivot); res = -res; }
     743                 :            :     // compute new rows and columns
     744         [ #  # ]:          0 :     for (r = i + 1; r < n; r++) {
     745         [ #  # ]:          0 :       f = b.get (r, i) / b.get (i, i);
     746         [ #  # ]:          0 :       for (c = i + 1; c < n; c++) {
     747 [ #  # ][ #  # ]:          0 :         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         [ #  # ]:          0 :   for (i = 0; i < n; i++) res *= b.get (i, i);
     754                 :          0 :   return res;
     755                 :            : }
     756                 :            : 
     757                 :            : /*!\brief Compute determinant of the given matrix.
     758                 :            :    \param[in] a matrix
     759                 :            :    \return Complex determinant
     760                 :            :    \todo a const?
     761                 :            : */
     762                 :          0 : nr_complex_t det (matrix a) {
     763                 :            : #if 0
     764                 :            :   return detLaplace (a);
     765                 :            : #else
     766         [ #  # ]:          0 :   return detGauss (a);
     767                 :            : #endif
     768                 :            : }
     769                 :            : 
     770                 :            : /*!\brief Compute inverse matrix using Laplace expansion
     771                 :            : 
     772                 :            :   Compute inverse matrix of the given matrix using Laplace expansion.
     773                 :            :   \param[in] a matrix to invert
     774                 :            :   \todo Static?
     775                 :            :   \bug recursive! Stack overflow
     776                 :            :   \todo a const?
     777                 :            :   \todo #ifdef 0
     778                 :            : */
     779                 :          0 : matrix inverseLaplace (matrix a) {
     780         [ #  # ]:          0 :   matrix res (a.getRows (), a.getCols ());
     781 [ #  # ][ #  # ]:          0 :   nr_complex_t d = detLaplace (a);
     782         [ #  # ]:          0 :   assert (abs (d) != 0); // singular matrix
     783         [ #  # ]:          0 :   for (int r = 0; r < a.getRows (); r++)
     784         [ #  # ]:          0 :     for (int c = 0; c < a.getCols (); c++)
     785 [ #  # ][ #  # ]:          0 :       res.set (r, c, cofactor (a, c, r) / d);
                 [ #  # ]
     786                 :          0 :   return res;
     787                 :            : }
     788                 :            : 
     789                 :            : /*!\brief Compute inverse matrix using Gauss-Jordan elimination
     790                 :            : 
     791                 :            :    Compute inverse matrix of the given matrix by Gauss-Jordan
     792                 :            :    elimination.
     793                 :            :    \todo a const?
     794                 :            :    \todo static?
     795                 :            :    \note assert non singulat matix
     796                 :            :    \param[in] a matrix to invert
     797                 :            : */
     798                 :       2140 : matrix inverseGaussJordan (matrix a) {
     799                 :            :   nr_double_t MaxPivot;
     800                 :       2140 :   nr_complex_t f;
     801                 :       2140 :   matrix b, e;
     802                 :       2140 :   int i, c, r, pivot, n = a.getCols ();
     803                 :            : 
     804                 :            :   // create temporary matrix and the result matrix
     805 [ +  - ][ +  - ]:       2140 :   b = matrix (a);
     806 [ +  - ][ +  - ]:       2140 :   e = eye (n);
     807                 :            : 
     808                 :            :   // create the eye matrix in 'b' and the result in 'e'
     809         [ +  + ]:       9140 :   for (i = 0; i < n; i++) {
     810                 :            :     // find maximum column value for pivoting
     811         [ +  + ]:      26300 :     for (MaxPivot = 0, pivot = r = i; r < n; r++) {
     812         [ +  + ]:      19300 :       if (abs (b (r, i)) > MaxPivot) {
     813                 :       7700 :         MaxPivot = abs (b (r, i));
     814                 :       7700 :         pivot = r;
     815                 :            :       }
     816                 :            :     }
     817                 :            :     // exchange rows if necessary
     818         [ -  + ]:       7000 :     assert (MaxPivot != 0); // singular matrix
     819         [ +  + ]:       7000 :     if (i != pivot) {
     820         [ +  - ]:        500 :       b.exchangeRows (i, pivot);
     821         [ +  - ]:        500 :       e.exchangeRows (i, pivot);
     822                 :            :     }
     823                 :            : 
     824                 :            :     // compute current row
     825         [ +  + ]:      38600 :     for (f = b (i, i), c = 0; c < n; c++) {
     826                 :      31600 :       b (i, c) /= f;
     827                 :      31600 :       e (i, c) /= f;
     828                 :            :     }
     829                 :            : 
     830                 :            :     // compute new rows and columns
     831         [ +  + ]:      38600 :     for (r = 0; r < n; r++) {
     832         [ +  + ]:      31600 :       if (r != i) {
     833         [ +  + ]:     193800 :         for (f = b (r, i), c = 0; c < n; c++) {
     834         [ +  - ]:     169200 :           b (r, c) -= f * b (i, c);
     835         [ +  - ]:     169200 :           e (r, c) -= f * e (i, c);
     836                 :            :         }
     837                 :            :       }
     838                 :            :     }
     839                 :            :   }
     840                 :       2140 :   return e;
     841                 :            : }
     842                 :            : 
     843                 :            : /*!\brief Compute inverse matrix
     844                 :            :    \param[in] a matrix to invert
     845                 :            :    \todo a is const
     846                 :            : */
     847                 :       2140 : matrix inverse (matrix a) {
     848                 :            : #if 0
     849                 :            :   return inverseLaplace (a);
     850                 :            : #else
     851         [ +  - ]:       2140 :   return inverseGaussJordan (a);
     852                 :            : #endif
     853                 :            : }
     854                 :            : 
     855                 :            : /*!\brief S params to S params
     856                 :            : 
     857                 :            :   Convert scattering parameters with the reference impedance 'zref'
     858                 :            :   to scattering parameters with the reference impedance 'z0'.
     859                 :            : 
     860                 :            :   Detail are given in [1], under equation (32)
     861                 :            : 
     862                 :            :   New scatering matrix \f$S'\f$ is:
     863                 :            :   \f[
     864                 :            :   S'=A^{-1}(S-\Gamma^+)(I-\Gamma S)^{-1}A^+
     865                 :            :   \f]
     866                 :            :   Where x^+ is the adjoint (or complex tranposate) of x,
     867                 :            :   I the identity matrix and \f$A\f$ is diagonal the matrix such as:
     868                 :            :   \f$   \Gamma_i= r_i \f$ and \f$A\f$ the diagonal matrix such
     869                 :            :   as:
     870                 :            :   \f[
     871                 :            :   A_i =  \frac{(1-r_i^*)\sqrt{|1-r_ir_i^*|}}{|1-r_i|}
     872                 :            :   \f]
     873                 :            :   Where \f$x*\f$ is the complex conjugate of \f$x\f$
     874                 :            :   and \f$r_i\f$ is wave reflexion coefficient of \f$Z_i'\f$ with respect
     875                 :            :   to \f$Z_i^*\f$ (where \f$Z_i'\f$ is the new impedance and
     876                 :            :   \f$Z_i\f$ is the old impedance), ie:
     877                 :            :   \f[
     878                 :            :   r_i = \frac{Z_i'-Z_i}{Z_i'-Z_i^*}
     879                 :            :   \f]
     880                 :            : 
     881                 :            :   \param[in] s original S matrix
     882                 :            :   \param[in] zref original reference impedance
     883                 :            :   \param[in] z0 new reference impedance
     884                 :            :   \bug This formula is valid only for real z!
     885                 :            :   \todo Correct documentation about standing waves [1-4]
     886                 :            :   \todo Implement Speciale implementation [2-3] if applicable
     887                 :            :   \return Renormalized scattering matrix
     888                 :            :   \todo s, zref and z0 const
     889                 :            : */
     890                 :          0 : matrix stos (matrix s, qucs::vector zref, qucs::vector z0) {
     891                 :          0 :   int d = s.getRows ();
     892                 :          0 :   matrix e, r, a;
     893                 :            : 
     894 [ #  # ][ #  # ]:          0 :   assert (d == s.getCols () && d == z0.getSize () && d == zref.getSize ());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     895                 :            : 
     896 [ #  # ][ #  # ]:          0 :   e = eye (d);
     897 [ #  # ][ #  # ]:          0 :   r = diagonal ((z0 - zref) / (z0 + zref));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     898 [ #  # ][ #  # ]:          0 :   a = diagonal (sqrt (z0 / zref) / (z0 + zref));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     899 [ #  # ][ #  # ]:          0 :   return inverse (a) * (s - r) * inverse (e - r * s) * a;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     900                 :            : }
     901                 :            : 
     902                 :            : /*!\brief S renormalization with all part identic
     903                 :            :    \param[in] s original S matrix
     904                 :            :    \param[in] zref original reference impedance
     905                 :            :    \param[in] z0 new reference impedance
     906                 :            :    \todo Why not inline
     907                 :            :    \return Renormalized scattering matrix
     908                 :            :    \todo s, zref and z0 const
     909                 :            : */
     910                 :          0 : matrix stos (matrix s, nr_complex_t zref, nr_complex_t z0) {
     911                 :          0 :   int d = s.getRows ();
     912 [ #  # ][ #  # ]:          0 :   return stos (s, qucs::vector (d, zref), qucs::vector (d, z0));
         [ #  # ][ #  # ]
     913                 :            : }
     914                 :            : 
     915                 :            : /*!\brief S renormalization with all part identic and real
     916                 :            :   \param[in] s original S matrix
     917                 :            :   \param[in] zref original reference impedance
     918                 :            :   \param[in] z0 new reference impedance
     919                 :            :   \todo Why not inline
     920                 :            :   \return Renormalized scattering matrix
     921                 :            :   \todo s, zref and z0 const
     922                 :            : */
     923                 :          0 : matrix stos (matrix s, nr_double_t zref, nr_double_t z0) {
     924 [ #  # ][ #  # ]:          0 :   return stos (s, nr_complex_t (zref, 0), nr_complex_t (z0, 0));
     925                 :            : }
     926                 :            : 
     927                 :            : /*!\brief S renormalization (variation)
     928                 :            :    \param[in] s original S matrix
     929                 :            :    \param[in] zref original reference impedance
     930                 :            :    \param[in] z0 new reference impedance
     931                 :            :    \todo Why not inline
     932                 :            :    \return Renormalized scattering matrix
     933                 :            :    \todo s, zref and z0 const
     934                 :            : */
     935                 :          0 : matrix stos (matrix s, qucs::vector zref, nr_complex_t z0) {
     936 [ #  # ][ #  # ]:          0 :   return stos (s, zref, qucs::vector (zref.getSize (), z0));
         [ #  # ][ #  # ]
     937                 :            : }
     938                 :            : 
     939                 :            : /*!\brief S renormalization (variation)
     940                 :            :   \param[in] s original S matrix
     941                 :            :   \param[in] zref original reference impedance
     942                 :            :   \param[in] z0 new reference impedance
     943                 :            :   \todo Why not inline
     944                 :            :   \todo s, zref and z0 const
     945                 :            :   \return Renormalized scattering matrix
     946                 :            : */
     947                 :          0 : matrix stos (matrix s, nr_complex_t zref, qucs::vector z0) {
     948 [ #  # ][ #  # ]:          0 :   return stos (s, qucs::vector (z0.getSize (), zref), z0);
         [ #  # ][ #  # ]
                 [ #  # ]
     949                 :            : }
     950                 :            : 
     951                 :            : /*!\brief Scattering parameters to impedance matrix
     952                 :            : 
     953                 :            :   Convert scattering parameters to impedance matrix.
     954                 :            :   According to [1] eq (19):
     955                 :            :   \f[
     956                 :            :   Z=F^{-1} (I- S)^{-1} (SG + G^+) F
     957                 :            :   \f]
     958                 :            :   Where \f$S\f$ is the scattering matrix, \f$x^+\f$
     959                 :            :   is the adjoint of x, I the identity matrix. The matrix
     960                 :            :   F and G are diagonal matrix defined by:
     961                 :            :   \f{align*}
     962                 :            :   F_i&=\frac{1}{2\sqrt{\Re\text{e}\; Z_i}} \\
     963                 :            :   G_i&=Z_i
     964                 :            :   \f}
     965                 :            :   \param[in] s Scattering matrix
     966                 :            :   \param[in] z0 Normalisation impedance
     967                 :            :   \note We could safely drop the \f$1/2\f$ in \f$F\f$ because we compute
     968                 :            :         \f$FXF^{-1}\f$ and therefore \f$1/2\f$ will simplify.
     969                 :            :   \bug not correct if zref is complex
     970                 :            :   \todo s, z0 const
     971                 :            :   \return Impedance matrix
     972                 :            : */
     973                 :          0 : matrix stoz (matrix s, qucs::vector z0) {
     974                 :          0 :   int d = s.getRows ();
     975                 :          0 :   matrix e, zref, gref;
     976                 :            : 
     977 [ #  # ][ #  # ]:          0 :   assert (d == s.getCols () && d == z0.getSize ());
         [ #  # ][ #  # ]
     978                 :            : 
     979 [ #  # ][ #  # ]:          0 :   e = eye (d);
     980 [ #  # ][ #  # ]:          0 :   zref = diagonal (z0);
         [ #  # ][ #  # ]
     981 [ #  # ][ #  # ]:          0 :   gref = diagonal (sqrt (real (1 / z0)));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     982 [ #  # ][ #  # ]:          0 :   return inverse (gref) * inverse (e - s) * (s * zref + zref) * gref;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     983                 :            : }
     984                 :            : 
     985                 :            : /*!\brief Scattering parameters to impedance matrix identic case
     986                 :            :    \param[in] s Scattering matrix
     987                 :            :    \param[in] z0 Normalisation impedance
     988                 :            :    \return Impedance matrix
     989                 :            :    \todo Why not inline?
     990                 :            :    \todo s and z0 const?
     991                 :            : */
     992                 :          0 : matrix stoz (matrix s, nr_complex_t z0) {
     993 [ #  # ][ #  # ]:          0 :   return stoz (s, qucs::vector (s.getRows (), z0));
     994                 :            : }
     995                 :            : 
     996                 :            : /*!\brief Convert impedance matrix scattering parameters.
     997                 :            : 
     998                 :            :    Convert scattering parameters to impedance matrix.
     999                 :            :    According to [1] eq (18):
    1000                 :            :   \f[
    1001                 :            :   S=F(Z-G^+)(Z+G)^{-1} F^{-1}
    1002                 :            :   \f]
    1003                 :            :   Where \f$Z\f$ is the scattering matrix, \f$x^+\f$
    1004                 :            :   is the adjoint of x, I the identity matrix. The matrix
    1005                 :            :   F and G are diagonal matrix defined by:
    1006                 :            :   \f{align*}
    1007                 :            :   F_i&=\frac{1}{2\sqrt{\Re\text{e}\; Z_i}} \\
    1008                 :            :   G_i&=Z_i
    1009                 :            :   \f}
    1010                 :            :   \param[in] Z Impedance matrix
    1011                 :            :   \param[in] z0 Normalisation impedance
    1012                 :            :   \return Scattering matrix
    1013                 :            :   \note We could safely drop the \f$1/2\f$ in \f$F\f$ because we compute
    1014                 :            :         \f$FXF^{-1}\f$ and therefore \f$1/2\f$ will simplify.
    1015                 :            :   \bug not correct if zref is complex
    1016                 :            :   \todo z and z0 const?
    1017                 :            : */
    1018                 :        600 : matrix ztos (matrix z, qucs::vector z0) {
    1019                 :        600 :   int d = z.getRows ();
    1020                 :        600 :   matrix e, zref, gref;
    1021                 :            : 
    1022 [ +  - ][ +  - ]:        600 :   assert (d == z.getCols () && d == z0.getSize ());
         [ -  + ][ -  + ]
    1023                 :            : 
    1024 [ +  - ][ +  - ]:        600 :   e = eye (d);
    1025 [ +  - ][ +  - ]:        600 :   zref = diagonal (z0);
         [ +  - ][ +  - ]
    1026 [ +  - ][ +  - ]:        600 :   gref = diagonal (sqrt (real (1 / z0)));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1027 [ +  - ][ +  - ]:        600 :   return gref * (z - zref) * inverse (z + zref) * inverse (gref);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1028                 :            : }
    1029                 :            : 
    1030                 :            : /*!\brief Convert impedance matrix to scattering parameters identic case
    1031                 :            :    \param[in] Z Impedance matrix
    1032                 :            :    \param[in] z0 Normalisation impedance
    1033                 :            :    \return Scattering matrix
    1034                 :            :    \todo Why not inline
    1035                 :            :    \todo z and z0 const
    1036                 :            :  */
    1037                 :        600 : matrix ztos (matrix z, nr_complex_t z0) {
    1038 [ +  - ][ +  - ]:        600 :   return ztos (z, qucs::vector (z.getRows (), z0));
    1039                 :            : }
    1040                 :            : 
    1041                 :            : /*!\brief impedance matrix to admittance matrix.
    1042                 :            : 
    1043                 :            :    Convert impedance matrix to admittance matrix. By definition
    1044                 :            :    \f$Y=Z^{-1}\f$
    1045                 :            :    \param[in] z impedance matrix
    1046                 :            :    \return Admittance matrix
    1047                 :            :    \todo Why not inline
    1048                 :            :    \todo z const
    1049                 :            : */
    1050                 :          0 : matrix ztoy (matrix z) {
    1051         [ #  # ]:          0 :   assert (z.getRows () == z.getCols ());
    1052         [ #  # ]:          0 :   return inverse (z);
    1053                 :            : }
    1054                 :            : 
    1055                 :            : /*!\brief Scattering parameters to admittance matrix.
    1056                 :            : 
    1057                 :            :   Convert scattering parameters to admittance matrix.
    1058                 :            :   According to [1] eq (19):
    1059                 :            :   \f[
    1060                 :            :   Z=F^{-1} (I- S)^{-1} (SG + G^+) F
    1061                 :            :   \f]
    1062                 :            :   Where \f$S\f$ is the scattering matrix, \f$x^+\f$
    1063                 :            :   is the adjoint of x, I the identity matrix. The matrix
    1064                 :            :   F and G are diagonal matrix defined by:
    1065                 :            :   \f{align*}
    1066                 :            :   F_i&=\frac{1}{2\sqrt{\Re\text{e}\; Z_i}} \\
    1067                 :            :   G_i&=Z_i
    1068                 :            :   \f}
    1069                 :            :   Using the well know formula \f$(AB)^{-1}=B^{1}A^{1}\f$,
    1070                 :            :   we derivate:
    1071                 :            :   \f[
    1072                 :            :   Y=F^{-1} (SG+G^+)^{-1} (I-S) F
    1073                 :            :   \f]
    1074                 :            :   \param[in] s Scattering matrix
    1075                 :            :   \param[in] z0 Normalisation impedance
    1076                 :            :   \note We could safely drop the \f$1/2\f$ in \f$F\f$ because we compute
    1077                 :            :         \f$FXF^{-1}\f$ and therefore \f$1/2\f$ will simplify.
    1078                 :            :   \bug not correct if zref is complex
    1079                 :            :   \todo s and z0 const
    1080                 :            :   \return Admittance matrix
    1081                 :            : */
    1082                 :          0 : matrix stoy (matrix s, qucs::vector z0) {
    1083                 :          0 :   int d = s.getRows ();
    1084                 :          0 :   matrix e, zref, gref;
    1085                 :            : 
    1086 [ #  # ][ #  # ]:          0 :   assert (d == s.getCols () && d == z0.getSize ());
         [ #  # ][ #  # ]
    1087                 :            : 
    1088 [ #  # ][ #  # ]:          0 :   e = eye (d);
    1089 [ #  # ][ #  # ]:          0 :   zref = diagonal (z0);
         [ #  # ][ #  # ]
    1090 [ #  # ][ #  # ]:          0 :   gref = diagonal (sqrt (real (1 / z0)));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1091 [ #  # ][ #  # ]:          0 :   return inverse (gref) * inverse (s * zref + zref) * (e - s) * gref;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1092                 :            : }
    1093                 :            : 
    1094                 :            : /*!\brief Convert scattering pto adminttance parameters identic case
    1095                 :            :    \param[in] S Scattering matrix
    1096                 :            :    \param[in] z0 Normalisation impedance
    1097                 :            :    \return Admittance matrix
    1098                 :            :    \todo Why not inline
    1099                 :            :    \todo s and z0 const
    1100                 :            :  */
    1101                 :          0 : matrix stoy (matrix s, nr_complex_t z0) {
    1102 [ #  # ][ #  # ]:          0 :   return stoy (s, qucs::vector (s.getRows (), z0));
    1103                 :            : }
    1104                 :            : 
    1105                 :            : /*!\brief Admittance matrix to scattering parameters
    1106                 :            : 
    1107                 :            :    Convert admittance matrix to scattering parameters.
    1108                 :            :    Using the same methodology as [1] eq (16-19), but writing
    1109                 :            :    (16) as \f$i=Yv\f$, ie
    1110                 :            :    \f[
    1111                 :            :    S=F(I-G^+Y)(I-GY)^{-1}F^{-1}
    1112                 :            :    \f]
    1113                 :            :    Where \f$S\f$ is the scattering matrix, \f$x^+\f$
    1114                 :            :    is the adjoint of x, I the identity matrix. The matrix
    1115                 :            :    F and G are diagonal matrix defined by:
    1116                 :            :    \f{align*}
    1117                 :            :    F_i&=\frac{1}{2\sqrt{\Re\text{e}\; Z_i}} \\
    1118                 :            :    G_i&=Z_i
    1119                 :            :    \f}
    1120                 :            :    Using the well know formula \f$(AB)^{-1}=B^{1}A^{1}\f$,
    1121                 :            :    we derivate:
    1122                 :            :    \f[
    1123                 :            :    Y=F^{-1} (SG+G^+)^{-1} (I-S) F
    1124                 :            :    \f]
    1125                 :            :    \param[in] y admittance matrix
    1126                 :            :    \param[in] z0 Normalisation impedance
    1127                 :            :    \note We could safely drop the \f$1/2\f$ in \f$F\f$ because we compute
    1128                 :            :          \f$FXF^{-1}\f$ and therefore \f$1/2\f$ will simplify.
    1129                 :            :    \bug not correct if zref is complex
    1130                 :            :    \todo why not y and z0 const
    1131                 :            :    \return Scattering matrix
    1132                 :            : */
    1133                 :        470 : matrix ytos (matrix y, qucs::vector z0) {
    1134                 :        470 :   int d = y.getRows ();
    1135                 :        470 :   matrix e, zref, gref;
    1136                 :            : 
    1137 [ +  - ][ +  - ]:        470 :   assert (d == y.getCols () && d == z0.getSize ());
         [ -  + ][ -  + ]
    1138                 :            : 
    1139 [ +  - ][ +  - ]:        470 :   e = eye (d);
    1140 [ +  - ][ +  - ]:        470 :   zref = diagonal (z0);
         [ +  - ][ +  - ]
    1141 [ +  - ][ +  - ]:        470 :   gref = diagonal (sqrt (real (1 / z0)));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1142 [ +  - ][ +  - ]:        470 :   return gref * (e - zref * y) * inverse (e + zref * y) * inverse (gref);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1143                 :            : }
    1144                 :            : /*!\brief Convert Admittance matrix to scattering parameters identic case
    1145                 :            :    \param[in] y Admittance matrix
    1146                 :            :    \param[in] z0 Normalisation impedance
    1147                 :            :    \return Scattering matrix
    1148                 :            :    \todo Why not inline
    1149                 :            :    \todo y and z0 const
    1150                 :            :  */
    1151                 :        470 : matrix ytos (matrix y, nr_complex_t z0) {
    1152 [ +  - ][ +  - ]:        470 :   return ytos (y, qucs::vector (y.getRows (), z0));
    1153                 :            : }
    1154                 :            : /*!\brief Converts chain matrix to scattering parameters.
    1155                 :            : 
    1156                 :            :     Converts scattering parameters to chain matrix.
    1157                 :            :     Formulae are given by [5] tab 1. and are remembered here:
    1158                 :            : 
    1159                 :            :     \f{align*}
    1160                 :            :     A&=\frac{(Z_{01}^*+S_{11}Z_{01})(1-S_{22})
    1161                 :            :                  +S_{12}S_{21}Z_{01}}{\Delta} \\
    1162                 :            :     B&=\frac{(Z_{01}^*+S_{11}Z_{01})(Z_{02}^*+S_{22}Z_{02})
    1163                 :            :                  -S_{12}S_{21}Z_{01}Z_{02}}{\Delta} \\
    1164                 :            :     C&=\frac{(1-S_{11})(1-S_{22})
    1165                 :            :                  -S_{12}S_{21}}{\Delta} \\
    1166                 :            :     D&=\frac{(1-S_{11})(Z_{02}^*+S_{22}Z_{02})
    1167                 :            :                  +S_{12}S_{21}Z_{02}}{\Delta}
    1168                 :            :     \f}
    1169                 :            :     Where:
    1170                 :            :     \f[
    1171                 :            :     \Delta = 2 S_{21}\sqrt{\Re\text{e}\;Z_{01}\Re\text{e}\;Z_{02}}
    1172                 :            :     \f]
    1173                 :            :     \bug Do not need fabs
    1174                 :            :     \param[in] s Scattering matrix
    1175                 :            :     \param[in] z1 impedance at input 1
    1176                 :            :     \param[in] z2 impedance at input 2
    1177                 :            :     \return Chain matrix
    1178                 :            :     \note Assert 2 by 2 matrix
    1179                 :            :     \todo Why not s,z1,z2 const
    1180                 :            : */
    1181                 :          0 : matrix stoa (matrix s, nr_complex_t z1, nr_complex_t z2) {
    1182 [ #  # ][ #  # ]:          0 :   nr_complex_t d = s (0, 0) * s (1, 1) - s (0, 1) * s (1, 0);
                 [ #  # ]
    1183         [ #  # ]:          0 :   nr_complex_t n = 2.0 * s (1, 0) * sqrt (fabs (real (z1) * real (z2)));
    1184         [ #  # ]:          0 :   matrix a (2);
    1185                 :            : 
    1186 [ #  # ][ #  # ]:          0 :   assert (s.getRows () >= 2 && s.getCols () >= 2);
                 [ #  # ]
    1187                 :            : 
    1188         [ #  # ]:          0 :   a.set (0, 0, (conj (z1) + z1 * s (0, 0) -
    1189         [ #  # ]:          0 :                 conj (z1) * s (1, 1) - z1 * d) / n);
           [ #  #  #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1190 [ #  # ][ #  # ]:          0 :   a.set (0, 1, (conj (z1) * conj (z2) + z1 * conj (z2) * s (0, 0) +
                 [ #  # ]
    1191 [ #  # ][ #  # ]:          0 :                 conj (z1) * z2 * s (1, 1) + z1 * z2 * d) / n);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1192 [ #  # ][ #  # ]:          0 :   a.set (1, 0, (1.0 - s (0, 0) - s (1, 1) + d) / n);
                 [ #  # ]
    1193         [ #  # ]:          0 :   a.set (1, 1, (conj (z2) - conj (z2) * s (0, 0) +
    1194         [ #  # ]:          0 :                 z2 * s (1, 1) - z2 * d) / n);
           [ #  #  #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1195                 :          0 :   return a;
    1196                 :            : }
    1197                 :            : 
    1198                 :            : 
    1199                 :            : /*!\brief Converts chain matrix to scattering parameters.
    1200                 :            : 
    1201                 :            :     Converts chain matrix to scattering parameters
    1202                 :            :     Formulae are given by [5] and are remembered here:
    1203                 :            :     \f{align*}
    1204                 :            :     S_{11}&=\frac{AZ_{02}+B-CZ_{01}^*Z_{02}-DZ_{01}^*}{\Delta} \\
    1205                 :            :     S_{12}&=\frac{2(AD-BC)
    1206                 :            :                   (\Re\text{e}\;Z_{01}\Re\text{e}\;Z_{02})^{1/2}}
    1207                 :            :                 {\Delta}\\
    1208                 :            :     S_{21}&=\frac{2(\Re\text{e}\;Z_{01}\Re\text{e}\;Z_{02})^{1/2}}{\Delta}\\
    1209                 :            :     S_{22}&=\frac{-AZ_{02}^*+B-CZ_{01}^*Z_{02}+DZ_{01}}{\Delta}
    1210                 :            :     \f}
    1211                 :            :     Where:
    1212                 :            :     \f[
    1213                 :            :     \Delta =AZ_{02}+B+CZ_{01}Z_{02}-DZ_{01}
    1214                 :            :     \f]
    1215                 :            :     \param[in] a Chain matrix
    1216                 :            :     \param[in] z1 impedance at input 1
    1217                 :            :     \param[in] z2 impedance at input 2
    1218                 :            :     \return Scattering matrix
    1219                 :            :     \bug Do not use fabs
    1220                 :            :     \todo a, z1, z2 const
    1221                 :            : */
    1222                 :          0 : matrix atos (matrix a, nr_complex_t z1, nr_complex_t z2) {
    1223         [ #  # ]:          0 :   nr_complex_t d = 2.0 * sqrt (fabs (real (z1) * real (z2)));
    1224         [ #  # ]:          0 :   nr_complex_t n = a (0, 0) * z2 + a (0, 1) +
    1225 [ #  # ][ #  # ]:          0 :     a (1, 0) * z1 * z2 + a (1, 1) * z1;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1226         [ #  # ]:          0 :   matrix s (2);
    1227                 :            : 
    1228 [ #  # ][ #  # ]:          0 :   assert (a.getRows () >= 2 && a.getCols () >= 2);
                 [ #  # ]
    1229                 :            : 
    1230         [ #  # ]:          0 :   s.set (0, 0, (a (0, 0) * z2 + a (0, 1)
    1231 [ #  # ][ #  # ]:          0 :                 - a (1, 0) * conj (z1) * z2 - a (1, 1) * conj (z1)) / n);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1232                 :          0 :   s.set (0, 1, (a (0, 0) * a (1, 1) -
    1233   [ #  #  #  # ]:          0 :                 a (0, 1) * a (1, 0)) * d / n);
         [ #  # ][ #  # ]
                 [ #  # ]
    1234         [ #  # ]:          0 :   s.set (1, 0, d / n);
    1235 [ #  # ][ #  # ]:          0 :   s.set (1, 1, (a (1, 1) * z1 - a (0, 0) * conj (z2) +
    1236 [ #  # ][ #  # ]:          0 :                 a (0, 1) - a (1, 0) * z1 * conj (z2)) / n);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1237                 :          0 :   return s;
    1238                 :            : }
    1239                 :            : 
    1240                 :            : /*!\brief Converts scattering parameters to hybrid matrix.
    1241                 :            : 
    1242                 :            :     Converts chain matrix to scattering parameters
    1243                 :            :     Formulae are given by [5] and are remembered here:
    1244                 :            :     \f{align*}
    1245                 :            :     h_{11}&=\frac{(Z_{01}^*+S_{11}Z_{01})
    1246                 :            :                   (Z_{02}^*+S_{22}Z_{02})
    1247                 :            :                   -S_{12}S_{21}Z_{01}Z_{02}}{\Delta}\\
    1248                 :            :     h_{12}&=\frac{2S_{12}
    1249                 :            :                   (\Re\text{e}\;Z_{01} \Re\text{e}\;Z_{02})^\frac{1}{2}}
    1250                 :            :                  {\Delta} \\
    1251                 :            :     h_{21}&=\frac{-2S_{21}
    1252                 :            :                   (\Re\text{e}\;Z_{01} \Re\text{e}\;Z_{02})^\frac{1}{2}}
    1253                 :            :                  {\Delta} \\
    1254                 :            : 
    1255                 :            :     h_{22}&=\frac{(1-S_{11})(1-S_{22})-S_{12}S_{21}}{\Delta}
    1256                 :            :     \f}
    1257                 :            :     Where \f$\Delta\f$ is:
    1258                 :            :     \f[
    1259                 :            :     \Delta=(1-S_{11})(Z_{02}^*+S_{22}Z_{02})+S_{12}S_{21}Z_{02}
    1260                 :            :     \f]
    1261                 :            :     \bug{Programmed formulae are valid only for Z real}
    1262                 :            :     \param[in] s Scattering matrix
    1263                 :            :     \param[in] z1 impedance at input 1
    1264                 :            :     \param[in] z2 impedance at input 2
    1265                 :            :     \return hybrid matrix
    1266                 :            :     \note Assert 2 by 2 matrix
    1267                 :            :     \todo Why not s,z1,z2 const
    1268                 :            :  */
    1269                 :          0 : matrix stoh (matrix s, nr_complex_t z1, nr_complex_t z2) {
    1270         [ #  # ]:          0 :   nr_complex_t n = s (0, 1) * s (1, 0);
    1271 [ #  # ][ #  # ]:          0 :   nr_complex_t d = (1.0 - s (0, 0)) * (1.0 + s (1, 1)) + n;
    1272         [ #  # ]:          0 :   matrix h (2);
    1273                 :            : 
    1274 [ #  # ][ #  # ]:          0 :   assert (s.getRows () >= 2 && s.getCols () >= 2);
                 [ #  # ]
    1275                 :            : 
    1276 [ #  # ][ #  # ]:          0 :   h.set (0, 0, ((1.0 + s (0, 0)) * (1.0 + s (1, 1)) - n) * z1 / d);
         [ #  # ][ #  # ]
    1277         [ #  # ]:          0 :   h.set (0, 1, +2.0 * s (0, 1) / d);
    1278         [ #  # ]:          0 :   h.set (1, 0, -2.0 * s (1, 0) / d);
    1279 [ #  # ][ #  # ]:          0 :   h.set (1, 1, ((1.0 - s (0, 0)) * (1.0 - s (1, 1)) - n) / z2 / d);
         [ #  # ][ #  # ]
    1280                 :          0 :   return h;
    1281                 :            : }
    1282                 :            : 
    1283                 :            : /*!\brief Converts hybrid matrix to scattering parameters.
    1284                 :            : 
    1285                 :            :     Formulae are given by [5] and are remembered here:
    1286                 :            :     \f{align*}
    1287                 :            :     S_{11}&=\frac{(h_{11}-Z_{01}^*)(1+h_{22}Z_{02})-h_{12}h_{21}Z_{02}}
    1288                 :            :                  {\Delta}\\
    1289                 :            :     S_{12}&=\frac{-2h_{12}(\Re\text{e}\;Z_{01}\Re\text{e}\;Z_{02})^\frac{1}{2}}
    1290                 :            :                  {\Delta}\\
    1291                 :            :     S_{21}&=\frac{-2h_{21}(\Re\text{e}\;Z_{01}\Re\text{e}\;Z_{02})^\frac{1}{2}}
    1292                 :            :                  {\Delta}\\
    1293                 :            :     S_{22}&=\frac{(h_{11}+Z_{01})(1-h_{22}Z_{02}^*)-h_{12}h_{21}Z_{02}^*}
    1294                 :            :                  {\Delta}
    1295                 :            :    \f}
    1296                 :            :    Where \f$\Delta\f$ is:
    1297                 :            :    \f[
    1298                 :            :    \Delta=(Z_{01}+h_{11})(1+h_{22}Z_{02})-h_{12}h_{21}Z_{02}
    1299                 :            :    \f]
    1300                 :            :    \param[in] h hybrid matrix
    1301                 :            :    \param[in] z1 impedance at input 1
    1302                 :            :    \param[in] z2 impedance at input 2
    1303                 :            :    \return scattering matrix
    1304                 :            :    \note Assert 2 by 2 matrix
    1305                 :            :    \todo Why not h,z1,z2 const
    1306                 :            : */
    1307                 :          0 : matrix htos (matrix h, nr_complex_t z1, nr_complex_t z2) {
    1308         [ #  # ]:          0 :   nr_complex_t n = h (0, 1) * h (1, 0);
    1309 [ #  # ][ #  # ]:          0 :   nr_complex_t d = (1.0 + h (0, 0) / z1) * (1.0 + z2 * h (1, 1)) - n;
         [ #  # ][ #  # ]
    1310         [ #  # ]:          0 :   matrix s (2);
    1311                 :            : 
    1312 [ #  # ][ #  # ]:          0 :   assert (h.getRows () >= 2 && h.getCols () >= 2);
                 [ #  # ]
    1313                 :            : 
    1314 [ #  # ][ #  # ]:          0 :   s.set (0, 0, ((h (0, 0) / z1 - 1.0) * (1.0 + z2 * h (1, 1)) - n) / d);
         [ #  # ][ #  # ]
                 [ #  # ]
    1315         [ #  # ]:          0 :   s.set (0, 1, +2.0 * h (0, 1) / d);
    1316         [ #  # ]:          0 :   s.set (1, 0, -2.0 * h (1, 0) / d);
    1317 [ #  # ][ #  # ]:          0 :   s.set (1, 1, ((1.0 + h (0, 0) / z1) * (1.0 - z2 * h (1, 1)) + n) / d);
         [ #  # ][ #  # ]
                 [ #  # ]
    1318                 :          0 :   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                 :          0 : matrix stog (matrix s, nr_complex_t z1, nr_complex_t z2) {
    1332         [ #  # ]:          0 :   nr_complex_t n = s (0, 1) * s (1, 0);
    1333 [ #  # ][ #  # ]:          0 :   nr_complex_t d = (1.0 + s (0, 0)) * (1.0 - s (1, 1)) + n;
    1334         [ #  # ]:          0 :   matrix g (2);
    1335                 :            : 
    1336 [ #  # ][ #  # ]:          0 :   assert (s.getRows () >= 2 && s.getCols () >= 2);
                 [ #  # ]
    1337                 :            : 
    1338 [ #  # ][ #  # ]:          0 :   g.set (0, 0, ((1.0 - s (0, 0)) * (1.0 - s (1, 1)) - n) / z1 / d);
         [ #  # ][ #  # ]
    1339         [ #  # ]:          0 :   g.set (0, 1, -2.0 * s (0, 1) / d);
    1340         [ #  # ]:          0 :   g.set (1, 0, +2.0 * s (1, 0) / d);
    1341 [ #  # ][ #  # ]:          0 :   g.set (1, 1, ((1.0 + s (0, 0)) * (1.0 + s (1, 1)) - n) * z2 / d);
         [ #  # ][ #  # ]
    1342                 :          0 :   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                 :          0 : matrix gtos (matrix g, nr_complex_t z1, nr_complex_t z2) {
    1356         [ #  # ]:          0 :   nr_complex_t n = g (0, 1) * g (1, 0);
    1357 [ #  # ][ #  # ]:          0 :   nr_complex_t d = (1.0 + g (0, 0) * z1) * (1.0 + g (1, 1) / z2) - n;
         [ #  # ][ #  # ]
    1358         [ #  # ]:          0 :   matrix s (2);
    1359                 :            : 
    1360 [ #  # ][ #  # ]:          0 :   assert (g.getRows () >= 2 && g.getCols () >= 2);
                 [ #  # ]
    1361                 :            : 
    1362 [ #  # ][ #  # ]:          0 :   s.set (0, 0, ((1.0 - g (0, 0) * z1) * (1.0 + g (1, 1) / z2) + n) / d);
         [ #  # ][ #  # ]
                 [ #  # ]
    1363         [ #  # ]:          0 :   s.set (0, 1, -2.0 * g (0, 1) / d);
    1364         [ #  # ]:          0 :   s.set (1, 0, +2.0 * g (1, 0) / d);
    1365 [ #  # ][ #  # ]:          0 :   s.set (1, 1, ((g (0, 0) * z1 + 1.0) * (g (1, 1) / z2 - 1.0) - n) / d);
         [ #  # ][ #  # ]
                 [ #  # ]
    1366                 :          0 :   return s;
    1367                 :            : }
    1368                 :            : 
    1369                 :            : /*!\brief Convert admittance matrix to impedance matrix.
    1370                 :            : 
    1371                 :            :   Convert \f$Y\f$ matrix to \f$Z\f$ matrix using well known relation
    1372                 :            :   \f$Z=Y^{-1}\f$
    1373                 :            :   \param[in] y admittance matrix
    1374                 :            :   \return Impedance matrix
    1375                 :            :   \note Check if y matrix is a square matrix
    1376                 :            :   \todo Why not inline
    1377                 :            :   \todo y const
    1378                 :            :   \todo move near ztoy()
    1379                 :            : */
    1380                 :          0 : matrix ytoz (matrix y) {
    1381         [ #  # ]:          0 :   assert (y.getRows () == y.getCols ());
    1382         [ #  # ]:          0 :   return inverse (y);
    1383                 :            : }
    1384                 :            : 
    1385                 :            : /*!\brief Admittance noise correlation matrix to S-parameter noise
    1386                 :            :    correlation matrix
    1387                 :            : 
    1388                 :            :    Converts admittance noise correlation matrix to S-parameter noise
    1389                 :            :    correlation matrix. According to [7] fig 2:
    1390                 :            :    \f[
    1391                 :            :    C_s=\frac{1}{4}(I+S)C_y(I+S)^+
    1392                 :            :    \f]
    1393                 :            :    Where \f$C_s\f$ is the scattering noise correlation matrix,
    1394                 :            :    \f$C_y\f$ the admittance noise correlation matrix, \f$I\f$
    1395                 :            :     the identity matrix and \f$S\f$ the scattering matrix
    1396                 :            :     of device. \f$x^+\f$ is the adjoint of \f$x\f$
    1397                 :            :    \warning cy matrix and s matrix are assumed to be normalized
    1398                 :            :    \param[in] cy Admittance noise correlation
    1399                 :            :    \param[in] s S parameter matrix of device
    1400                 :            :    \return S-parameter noise correlation matrix
    1401                 :            :    \note Assert compatiblity of matrix
    1402                 :            :    \todo cy s const
    1403                 :            : */
    1404                 :         70 : matrix cytocs (matrix cy, matrix s) {
    1405         [ +  - ]:         70 :   matrix e = eye (s.getRows ());
    1406                 :            : 
    1407 [ +  - ][ +  - ]:         70 :   assert (cy.getRows () == cy.getCols () && s.getRows () == s.getCols () &&
                 [ -  + ]
    1408         [ -  + ]:         70 :           cy.getRows () == s.getRows ());
    1409                 :            : 
    1410 [ +  - ][ +  - ]:         70 :   return (e + s) * cy * adjoint (e + s) / 4;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1411                 :            : }
    1412                 :            : 
    1413                 :            : /*!\brief Converts S-parameter noise correlation matrix to admittance noise
    1414                 :            :     correlation matrix.
    1415                 :            : 
    1416                 :            :     According to [7] fig 2:
    1417                 :            :     \f[
    1418                 :            :     C_y=(I+Y)C_s(I+Y)^+
    1419                 :            :     \f]
    1420                 :            :     Where \f$C_s\f$ is the scattering noise correlation matrix,
    1421                 :            :     \f$C_y\f$ the admittance noise correlation matrix, \f$I\f$
    1422                 :            :     the identity matrix and \f$S\f$ the scattering matrix
    1423                 :            :     of device. \f$x^+\f$ is the adjoint of \f$x\f$
    1424                 :            :     \warning cs matrix and y matrix are assumed to be normalized
    1425                 :            :     \param[in]  cs S parameter noise correlation
    1426                 :            :     \param[in] y Admittance matrix of device
    1427                 :            :     \return admittance noise correlation matrix
    1428                 :            :     \todo cs, y const
    1429                 :            : */
    1430                 :          0 : matrix cstocy (matrix cs, matrix y) {
    1431         [ #  # ]:          0 :   matrix e = eye (y.getRows ());
    1432                 :            : 
    1433 [ #  # ][ #  # ]:          0 :   assert (cs.getRows () == cs.getCols () && y.getRows () == y.getCols () &&
                 [ #  # ]
    1434         [ #  # ]:          0 :           cs.getRows () == y.getRows ());
    1435                 :            : 
    1436 [ #  # ][ #  # ]:          0 :   return (e + y) * cs * adjoint (e + y);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1437                 :            : }
    1438                 :            : 
    1439                 :            : /*!\brief Converts impedance noise correlation matrix to S-parameter noise
    1440                 :            :    correlation matrix.
    1441                 :            : 
    1442                 :            :    According to [7] fig 2:
    1443                 :            :    \f[
    1444                 :            :    C_s=\frac{1}{4}(I-S)C_z(I-S)
    1445                 :            :    \f]
    1446                 :            :    Where \f$C_s\f$ is the scattering noise correlation matrix,
    1447                 :            :    \f$C_z\f$ the impedance noise correlation matrix, \f$I\f$
    1448                 :            :     the identity matrix and \f$S\f$ the scattering matrix
    1449                 :            :     of device. \f$x^+\f$ is the adjoint of \f$x\f$
    1450                 :            :    \warning Cz matrix and s matrix are assumed to be normalized
    1451                 :            :    \param[in] cz Impedance noise correlation
    1452                 :            :    \param[in] s S parameter matrix of device
    1453                 :            :    \return S-parameter noise correlation matrix
    1454                 :            :    \note Assert compatiblity of matrix
    1455                 :            :    \todo cz, s const
    1456                 :            : */
    1457                 :          0 : matrix cztocs (matrix cz, matrix s) {
    1458         [ #  # ]:          0 :   matrix e = eye (s.getRows ());
    1459                 :            : 
    1460 [ #  # ][ #  # ]:          0 :   assert (cz.getRows () == cz.getCols () && s.getRows () == s.getCols () &&
                 [ #  # ]
    1461         [ #  # ]:          0 :           cz.getRows () == s.getRows ());
    1462                 :            : 
    1463 [ #  # ][ #  # ]:          0 :   return (e - s) * cz * adjoint (e - s) / 4;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1464                 :            : }
    1465                 :            : 
    1466                 :            : /*!\brief Converts S-parameter noise correlation matrix to impedance noise
    1467                 :            :     correlation matrix.
    1468                 :            : 
    1469                 :            :     According to [7] fig 2:
    1470                 :            :     \f[
    1471                 :            :     C_z=(I+Z)C_s(I+Z)^+
    1472                 :            :     \f]
    1473                 :            :     Where \f$C_s\f$ is the scattering noise correlation matrix,
    1474                 :            :     \f$C_z\f$ the impedance noise correlation matrix, \f$I\f$
    1475                 :            :     the identity matrix and \f$S\f$ the scattering matrix
    1476                 :            :     of device. \f$x^+\f$ is the adjoint of \f$x\f$
    1477                 :            :     \warning cs matrix and y matrix are assumed to be normalized
    1478                 :            :     \param[in]  cs S parameter noise correlation
    1479                 :            :     \param[in] z Impedance matrix of device
    1480                 :            :     \return Impedance noise correlation matrix
    1481                 :            :     \todo cs, z const
    1482                 :            : */
    1483                 :          0 : matrix cstocz (matrix cs, matrix z) {
    1484 [ #  # ][ #  # ]:          0 :   assert (cs.getRows () == cs.getCols () && z.getRows () == z.getCols () &&
                 [ #  # ]
    1485         [ #  # ]:          0 :           cs.getRows () == z.getRows ());
    1486         [ #  # ]:          0 :   matrix e = eye (z.getRows ());
    1487 [ #  # ][ #  # ]:          0 :   return (e + z) * cs * adjoint (e + z);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1488                 :            : }
    1489                 :            : 
    1490                 :            : /*!\brief Converts impedance noise correlation matrix to admittance noise
    1491                 :            :     correlation matrix.
    1492                 :            : 
    1493                 :            :     According to [7] fig 2:
    1494                 :            :     \f[
    1495                 :            :     C_y=YC_zY^+
    1496                 :            :     \f]
    1497                 :            :     Where \f$C_z\f$ is the impedance correlation matrix,
    1498                 :            :     \f$I\f$ the identity matrix and \f$C_y\f$ the admittance noise
    1499                 :            :     correlation matrix.
    1500                 :            :     \f$x^+\f$ is the adjoint of \f$x\f$
    1501                 :            :     \warning cz matrix and y matrix are assumed to be normalized
    1502                 :            :     \param[in]  cz impedance noise correlation
    1503                 :            :     \param[in]  y Admittance matrix of device
    1504                 :            :     \return admittance noise correlation matrix
    1505                 :            :     \todo cs, y const
    1506                 :            : */
    1507                 :          0 : matrix cztocy (matrix cz, matrix y) {
    1508 [ #  # ][ #  # ]:          0 :   assert (cz.getRows () == cz.getCols () && y.getRows () == y.getCols () &&
                 [ #  # ]
    1509         [ #  # ]:          0 :           cz.getRows () == y.getRows ());
    1510                 :            : 
    1511 [ #  # ][ #  # ]:          0 :   return y * cz * adjoint (y);
         [ #  # ][ #  # ]
                 [ #  # ]
    1512                 :            : }
    1513                 :            : 
    1514                 :            : /*!\brief Converts admittance noise correlation matrix to impedance noise
    1515                 :            :     correlation matrix.
    1516                 :            : 
    1517                 :            :     According to [7] fig 2:
    1518                 :            :     \f[
    1519                 :            :     C_z=ZC_yZ^+
    1520                 :            :     \f]
    1521                 :            :     Where \f$C_z\f$ is the impedance correlation matrix,
    1522                 :            :     \f$I\f$ the identity matrix and \f$C_y\f$ the admittance noise
    1523                 :            :     correlation matrix.
    1524                 :            :     \f$x^+\f$ is the adjoint of \f$x\f$
    1525                 :            :     \warning cy matrix and z matrix are assumed to be normalized
    1526                 :            :     \param[in]  cy Admittance noise correlation
    1527                 :            :     \param[in]  z Impedance matrix of device
    1528                 :            :     \return Impedance noise correlation matrix
    1529                 :            :     \todo cs, z const
    1530                 :            : */
    1531                 :          0 : matrix cytocz (matrix cy, matrix z) {
    1532 [ #  # ][ #  # ]:          0 :   assert (cy.getRows () == cy.getCols () && z.getRows () == z.getCols () &&
                 [ #  # ]
    1533         [ #  # ]:          0 :           cy.getRows () == z.getRows ());
    1534 [ #  # ][ #  # ]:          0 :   return z * cy * adjoint (z);
         [ #  # ][ #  # ]
                 [ #  # ]
    1535                 :            : }
    1536                 :            : 
    1537                 :            : /*!\brief The function swaps the given rows with each other.
    1538                 :            :   \param[in] r1 source row
    1539                 :            :   \param[in] r2 destination row
    1540                 :            :   \note assert not out of bound r1 and r2
    1541                 :            :   \todo r1 and r2 const
    1542                 :            : */
    1543                 :       1000 : void matrix::exchangeRows (int r1, int r2) {
    1544         [ +  + ]:       3800 :   nr_complex_t * s = new nr_complex_t[cols];
    1545                 :       1000 :   int len = sizeof (nr_complex_t) * cols;
    1546                 :            : 
    1547 [ +  - ][ +  - ]:       1000 :   assert (r1 >= 0 && r2 >= 0 && r1 < rows && r2 < rows);
         [ +  - ][ -  + ]
                 [ -  + ]
    1548                 :            : 
    1549                 :       1000 :   memcpy (s, &data[r1 * cols], len);
    1550                 :       1000 :   memcpy (&data[r1 * cols], &data[r2 * cols], len);
    1551                 :       1000 :   memcpy (&data[r2 * cols], s, len);
    1552         [ +  - ]:       1000 :   delete[] s;
    1553                 :       1000 : }
    1554                 :            : 
    1555                 :            : /*!\brief The function swaps the given column with each other.
    1556                 :            :   \param[in] c1 source column
    1557                 :            :   \param[in] c2 destination column
    1558                 :            :   \note assert not out of bound r1 and r2
    1559                 :            :   \todo c1 and c2 const
    1560                 :            : */
    1561                 :          0 : void matrix::exchangeCols (int c1, int c2) {
    1562                 :          0 :   nr_complex_t s;
    1563                 :            : 
    1564 [ #  # ][ #  # ]:          0 :   assert (c1 >= 0 && c2 >= 0 && c1 < cols && c2 < cols);
         [ #  # ][ #  # ]
                 [ #  # ]
    1565                 :            : 
    1566         [ #  # ]:          0 :   for (int r = 0; r < rows * cols; r += cols) {
    1567                 :          0 :     s = data[r + c1];
    1568                 :          0 :     data[r + c1] = data[r + c2];
    1569                 :          0 :     data[r + c2] = s;
    1570                 :            :   }
    1571                 :          0 : }
    1572                 :            : 
    1573                 :            : /*!\brief Generic conversion matrix
    1574                 :            : 
    1575                 :            :   This function converts 2x2 matrices from any of the matrix forms Y,
    1576                 :            :   Z, H, G and A to any other.  Also converts S<->(A, T, H, Y and Z)
    1577                 :            :   matrices.
    1578                 :            :   Convertion assumed:
    1579                 :            : 
    1580                 :            :   Y->Y, Y->Z, Y->H, Y->G, Y->A, Y->S,
    1581                 :            :   Z->Y, Z->Z, Z->H, Z->G, Z->A, Z->S,
    1582                 :            :   H->Y, H->Z, H->H, H->G, H->A, H->S,
    1583                 :            :   G->Y, G->Z, G->H, G->G, G->A, G->S,
    1584                 :            :   A->Y, A->Z, A->H, A->G, A->A, A->S,
    1585                 :            :   S->Y, S->Z, S->H, S->G, S->A, S->S,
    1586                 :            :   S->T,T->T,T->S
    1587                 :            :   \note assert 2x2 matrix
    1588                 :            :   \param[in] m base matrix
    1589                 :            :   \param[in] in matrix
    1590                 :            :   \param[in] out matrix
    1591                 :            :   \return matrix given by format out
    1592                 :            :   \todo m, in, out const
    1593                 :            : */
    1594                 :          0 : matrix twoport (matrix m, char in, char out) {
    1595 [ #  # ][ #  # ]:          0 :   assert (m.getRows () >= 2 && m.getCols () >= 2);
                 [ #  # ]
    1596                 :          0 :   nr_complex_t d;
    1597         [ #  # ]:          0 :   matrix res (2);
    1598                 :            : 
    1599   [ #  #  #  #  :          0 :   switch (in) {
             #  #  #  # ]
    1600                 :            :   case 'Y':
    1601   [ #  #  #  #  :          0 :     switch (out) {
                #  #  # ]
    1602                 :            :     case 'Y': // Y to Y
    1603         [ #  # ]:          0 :       res = m;
    1604                 :          0 :       break;
    1605                 :            :     case 'Z': // Y to Z
    1606 [ #  # ][ #  # ]:          0 :       d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
                 [ #  # ]
    1607         [ #  # ]:          0 :       res.set (0, 0, m (1, 1) / d);
    1608         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1609         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1610         [ #  # ]:          0 :       res.set (1, 1, m (0, 0) / d);
    1611                 :          0 :       break;
    1612                 :            :     case 'H': // Y to H
    1613                 :          0 :       d = m (0, 0);
    1614                 :          0 :       res.set (0, 0, 1.0 / d);
    1615         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1616         [ #  # ]:          0 :       res.set (1, 0, m (1, 0) / d);
    1617 [ #  # ][ #  # ]:          0 :       res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1618                 :          0 :       break;
    1619                 :            :     case 'G': // Y to G
    1620                 :          0 :       d = m (1, 1);
    1621 [ #  # ][ #  # ]:          0 :       res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1622         [ #  # ]:          0 :       res.set (0, 1, m (0, 1) / d);
    1623         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1624                 :          0 :       res.set (1, 1, 1.0 / d);
    1625                 :          0 :       break;
    1626                 :            :     case 'A': // Y to A
    1627                 :          0 :       d = m (1, 0);
    1628         [ #  # ]:          0 :       res.set (0, 0, -m (1, 1) / d);
    1629                 :          0 :       res.set (0, 1, -1.0 / d);
    1630 [ #  # ][ #  # ]:          0 :       res.set (1, 0, m (0, 1) - m (1, 1) * m (0, 0) / d);
                 [ #  # ]
    1631         [ #  # ]:          0 :       res.set (1, 1, -m (0, 0) / d);
    1632                 :          0 :       break;
    1633                 :            :     case 'S': // Y to S
    1634 [ #  # ][ #  # ]:          0 :       res = ytos (m);
                 [ #  # ]
    1635                 :          0 :       break;
    1636                 :            :     }
    1637                 :          0 :     break;
    1638                 :            :   case 'Z':
    1639   [ #  #  #  #  :          0 :     switch (out) {
                #  #  # ]
    1640                 :            :     case 'Y': // Z to Y
    1641 [ #  # ][ #  # ]:          0 :       d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
                 [ #  # ]
    1642         [ #  # ]:          0 :       res.set (0, 0, m (1, 1) / d);
    1643         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1644         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1645         [ #  # ]:          0 :       res.set (1, 1, m (0, 0) / d);
    1646                 :          0 :       break;
    1647                 :            :     case 'Z': // Z to Z
    1648         [ #  # ]:          0 :       res = m;
    1649                 :          0 :       break;
    1650                 :            :     case 'H': // Z to H
    1651                 :          0 :       d = m (1, 1);
    1652 [ #  # ][ #  # ]:          0 :       res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1653         [ #  # ]:          0 :       res.set (0, 1, m (0, 1) / d);
    1654         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1655                 :          0 :       res.set (1, 1, 1.0 / d);
    1656                 :          0 :       break;
    1657                 :            :     case 'G': // Z to G
    1658                 :          0 :       d = m (0, 0);
    1659                 :          0 :       res.set (0, 0, 1.0 / d);
    1660         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1661         [ #  # ]:          0 :       res.set (1, 0, m (1, 0) / d);
    1662 [ #  # ][ #  # ]:          0 :       res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1663                 :          0 :       break;
    1664                 :            :     case 'A': // Z to A
    1665                 :          0 :       d = m (1, 0);
    1666         [ #  # ]:          0 :       res.set (0, 0, m (0, 0) / d);
    1667 [ #  # ][ #  # ]:          0 :       res.set (0, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
                 [ #  # ]
    1668                 :          0 :       res.set (1, 0, 1.0 / d);
    1669         [ #  # ]:          0 :       res.set (1, 1, m (1, 1) / d);
    1670                 :          0 :       break;
    1671                 :            :     case 'S': // Z to S
    1672 [ #  # ][ #  # ]:          0 :       res = ztos (m);
                 [ #  # ]
    1673                 :          0 :       break;
    1674                 :            :     }
    1675                 :          0 :     break;
    1676                 :            :   case 'H':
    1677   [ #  #  #  #  :          0 :     switch (out) {
                #  #  # ]
    1678                 :            :     case 'Y': // H to Y
    1679                 :          0 :       d = m (0, 0);
    1680                 :          0 :       res.set (0, 0, 1.0 / d);
    1681         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1682         [ #  # ]:          0 :       res.set (1, 0, m (1, 0) / d);
    1683 [ #  # ][ #  # ]:          0 :       res.set (1, 1, m (1, 1) - m (0, 1) * m.get(2, 1) / d);
                 [ #  # ]
    1684                 :          0 :       break;
    1685                 :            :     case 'Z': // H to Z
    1686                 :          0 :       d = m (1, 1);
    1687 [ #  # ][ #  # ]:          0 :       res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1688         [ #  # ]:          0 :       res.set (0, 1, m (0, 1) / d);
    1689         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1690                 :          0 :       res.set (1, 1, 1.0 / d);
    1691                 :          0 :       break;
    1692                 :            :     case 'H': // H to H
    1693         [ #  # ]:          0 :       res = m;
    1694                 :          0 :       break;
    1695                 :            :     case 'G': // H to G
    1696 [ #  # ][ #  # ]:          0 :       d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
                 [ #  # ]
    1697         [ #  # ]:          0 :       res.set (0, 0, m (1, 1) / d);
    1698         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1699         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1700         [ #  # ]:          0 :       res.set (1, 1, m (0, 0) / d);
    1701                 :          0 :       break;
    1702                 :            :     case 'A': // H to A
    1703                 :          0 :       d = m (1, 0);
    1704 [ #  # ][ #  # ]:          0 :       res.set (0, 0, m (0, 1) - m (0, 0) * m (1, 1) / d);
                 [ #  # ]
    1705         [ #  # ]:          0 :       res.set (0, 1, -m (0, 0) / d);
    1706         [ #  # ]:          0 :       res.set (1, 0, -m (1, 1) / d);
    1707                 :          0 :       res.set (1, 1, -1.0 / d);
    1708                 :          0 :       break;
    1709                 :            :     case 'S': // H to S
    1710 [ #  # ][ #  # ]:          0 :       res = htos (m);
                 [ #  # ]
    1711                 :          0 :       break;
    1712                 :            :     }
    1713                 :          0 :     break;
    1714                 :            :   case 'G':
    1715   [ #  #  #  #  :          0 :     switch (out) {
                #  #  # ]
    1716                 :            :     case 'Y': // G to Y
    1717                 :          0 :       d = m (1, 1);
    1718 [ #  # ][ #  # ]:          0 :       res.set (0, 0, m (0, 0) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1719         [ #  # ]:          0 :       res.set (0, 1, m (0, 1) / d);
    1720         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1721                 :          0 :       res.set (1, 1, 1.0 / d);
    1722                 :          0 :       break;
    1723                 :            :     case 'Z': // G to Z
    1724                 :          0 :       d = m (0, 0);
    1725                 :          0 :       res.set (0, 0, 1.0 / d);
    1726         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1727         [ #  # ]:          0 :       res.set (1, 0, m (1, 0) / d);
    1728 [ #  # ][ #  # ]:          0 :       res.set (1, 1, m (1, 1) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1729                 :          0 :       break;
    1730                 :            :     case 'H': // G to H
    1731 [ #  # ][ #  # ]:          0 :       d = m (0, 0) * m (1, 1) - m (0, 1) * m (1, 0);
                 [ #  # ]
    1732         [ #  # ]:          0 :       res.set (0, 0, m (1, 1) / d);
    1733         [ #  # ]:          0 :       res.set (0, 1, -m (0, 1) / d);
    1734         [ #  # ]:          0 :       res.set (1, 0, -m (1, 0) / d);
    1735         [ #  # ]:          0 :       res.set (1, 1, m (0, 0) / d);
    1736                 :          0 :       break;
    1737                 :            :     case 'G': // G to G
    1738         [ #  # ]:          0 :       res = m;
    1739                 :          0 :       break;
    1740                 :            :     case 'A': // G to A
    1741                 :          0 :       d = m (1, 0);
    1742                 :          0 :       res.set (0, 0, 1.0 / d);
    1743         [ #  # ]:          0 :       res.set (0, 1, m (1, 1) / d);
    1744         [ #  # ]:          0 :       res.set (1, 0, m (0, 0) / d);
    1745 [ #  # ][ #  # ]:          0 :       res.set (1, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
                 [ #  # ]
    1746                 :          0 :       break;
    1747                 :            :     case 'S': // G to S
    1748 [ #  # ][ #  # ]:          0 :       res = gtos (m);
                 [ #  # ]
    1749                 :          0 :       break;
    1750                 :            :     }
    1751                 :          0 :     break;
    1752                 :            :   case 'A':
    1753   [ #  #  #  #  :          0 :     switch (out) {
                #  #  # ]
    1754                 :            :     case 'Y': // A to Y
    1755                 :          0 :       d = m (0, 1);
    1756         [ #  # ]:          0 :       res.set (0, 0, m (1, 1) / d);
    1757 [ #  # ][ #  # ]:          0 :       res.set (0, 1, m (1, 0) - m (0, 0) * m (1, 1) / d);
                 [ #  # ]
    1758                 :          0 :       res.set (1, 0, -1.0 / d);
    1759         [ #  # ]:          0 :       res.set (1, 1, m (0, 0) / d);
    1760                 :          0 :       break;
    1761                 :            :     case 'Z': // A to Z
    1762                 :          0 :       d = m (1, 0);
    1763         [ #  # ]:          0 :       res.set (0, 0, m (0, 0) / d);
    1764 [ #  # ][ #  # ]:          0 :       res.set (0, 1, m (0, 0) * m (1, 1) / d - m (0, 1));
                 [ #  # ]
    1765                 :          0 :       res.set (1, 0, 1.0 / d);
    1766         [ #  # ]:          0 :       res.set (1, 1, m (1, 1) / d);
    1767                 :          0 :       break;
    1768                 :            :     case 'H': // A to H
    1769                 :          0 :       d = m (1, 1);
    1770         [ #  # ]:          0 :       res.set (0, 0, m (0, 1) / d);
    1771 [ #  # ][ #  # ]:          0 :       res.set (0, 1, m (0, 0) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1772                 :          0 :       res.set (1, 0, -1.0 / d);
    1773         [ #  # ]:          0 :       res.set (1, 1, m (1, 0) / d);
    1774                 :          0 :       break;
    1775                 :            :     case 'G': // A to G
    1776                 :          0 :       d = m (0, 0);
    1777         [ #  # ]:          0 :       res.set (0, 0, m (1, 0) / d);
    1778 [ #  # ][ #  # ]:          0 :       res.set (0, 1, m (1, 0) * m (0, 1) / d - m (1, 1));
                 [ #  # ]
    1779                 :          0 :       res.set (1, 0, 1.0 / d);
    1780         [ #  # ]:          0 :       res.set (1, 1, m (0, 1) / d);
    1781                 :          0 :       break;
    1782                 :            :     case 'A': // A to A
    1783         [ #  # ]:          0 :       res = m;
    1784                 :          0 :       break;
    1785                 :            :     case 'S': // A to S
    1786 [ #  # ][ #  # ]:          0 :       res = atos (m);
                 [ #  # ]
    1787                 :          0 :       break;
    1788                 :            :     }
    1789                 :          0 :     break;
    1790                 :            :   case 'S':
    1791   [ #  #  #  #  :          0 :     switch (out) {
             #  #  #  # ]
    1792                 :            :     case 'S': // S to S
    1793         [ #  # ]:          0 :       res = m;
    1794                 :          0 :       break;
    1795                 :            :     case 'T': // S to T
    1796                 :          0 :       d = m (1, 0);
    1797 [ #  # ][ #  # ]:          0 :       res.set (0, 0, m (0, 1) - m (0, 0) * m (1, 1) / d);
                 [ #  # ]
    1798         [ #  # ]:          0 :       res.set (0, 1, m (0, 0) / d);
    1799         [ #  # ]:          0 :       res.set (1, 0, -m (1, 1) / d);
    1800                 :          0 :       res.set (0, 1, 1.0 / d);
    1801                 :          0 :       break;
    1802                 :            :     case 'A': // S to A
    1803 [ #  # ][ #  # ]:          0 :       res = stoa (m);
                 [ #  # ]
    1804                 :          0 :       break;
    1805                 :            :     case 'H': // S to H
    1806 [ #  # ][ #  # ]:          0 :       res = stoh (m);
                 [ #  # ]
    1807                 :          0 :       break;
    1808                 :            :     case 'G': // S to G
    1809 [ #  # ][ #  # ]:          0 :       res = stog (m);
                 [ #  # ]
    1810                 :          0 :       break;
    1811                 :            :     case 'Y': // S to Y
    1812 [ #  # ][ #  # ]:          0 :       res = stoy (m);
                 [ #  # ]
    1813                 :          0 :       break;
    1814                 :            :     case 'Z': // S to Z
    1815 [ #  # ][ #  # ]:          0 :       res = stoz (m);
                 [ #  # ]
    1816                 :          0 :       break;
    1817                 :            :     }
    1818                 :          0 :     break;
    1819                 :            :   case 'T':
    1820      [ #  #  # ]:          0 :     switch (out) {
    1821                 :            :     case 'S': // T to S
    1822                 :          0 :       d = m (1, 1);
    1823         [ #  # ]:          0 :       res.set (0, 0, m (0, 1) / d);
    1824 [ #  # ][ #  # ]:          0 :       res.set (0, 1, m (0, 0) - m (0, 1) * m (1, 0) / d);
                 [ #  # ]
    1825                 :          0 :       res.set (1, 0, 1.0 / d);
    1826         [ #  # ]:          0 :       res.set (0, 1, -m (1, 0) / d);
    1827                 :          0 :       break;
    1828                 :            :     case 'T': // T to T
    1829         [ #  # ]:          0 :       res = m;
    1830                 :          0 :       break;
    1831                 :            :     }
    1832                 :          0 :     break;
    1833                 :            :   }
    1834                 :          0 :   return res;
    1835                 :            : }
    1836                 :            : 
    1837                 :            : /*!\brief Compute the Rollet stabilty factor
    1838                 :            : 
    1839                 :            :    The function returns the Rollet stability factor (\f$K\f) of the given
    1840                 :            :    S-parameter matrix:
    1841                 :            :    \[
    1842                 :            :    K=\frac{1-|S_{11}|^2-|S_{22}|^2+|\delta|^2}{2|S_{12}S_{21}|}
    1843                 :            :    \]
    1844                 :            :    Where:
    1845                 :            :    \[
    1846                 :            :    \Delta=S_{11}S_{22}-S_{12}S_{21}
    1847                 :            :    \]
    1848                 :            :    \param[in] m S parameter matrix
    1849                 :            :    \return Rollet factor
    1850                 :            :    \note Assert 2x2 matrix
    1851                 :            :    \todo m const?
    1852                 :            :    \todo Rewrite with abs and expand det. It is cleaner.
    1853                 :            : */
    1854                 :          0 : nr_double_t rollet (matrix m) {
    1855 [ #  # ][ #  # ]:          0 :   assert (m.getRows () >= 2 && m.getCols () >= 2);
                 [ #  # ]
    1856                 :            :   nr_double_t res;
    1857 [ #  # ][ #  # ]:          0 :   res = (1 - norm (m (0, 0)) - norm (m (1, 1)) + norm (det (m))) /
    1858         [ #  # ]:          0 :     2 / abs (m (0, 1) * m (1, 0));
    1859                 :          0 :   return res;
    1860                 :            : }
    1861                 :            : 
    1862                 :            : /* Computes stability measure B1 of the given S-parameter matrix. */
    1863                 :          0 : nr_double_t b1 (matrix m) {
    1864 [ #  # ][ #  # ]:          0 :   assert (m.getRows () >= 2 && m.getCols () >= 2);
                 [ #  # ]
    1865                 :            :   nr_double_t res;
    1866 [ #  # ][ #  # ]:          0 :   res = 1 + norm (m (0, 0)) - norm (m (1, 1)) - norm (det (m));
    1867                 :          0 :   return res;
    1868                 :            : }
    1869                 :            : 
    1870                 :            : } // namespace qucs

Generated by: LCOV version 1.11