* matvec.cpp - matrix vector class implementation
*
* Copyright (C) 2004-2009 Stefan Jahn <stefan@lkcc.org>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $Id$
*
*/
* \file matvec.cpp
* \brief Vector of matrices class implementation
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmath>
#include "logging.h"
#include "object.h"
#include "complex.h"
#include "vector.h"
#include "matrix.h"
#include "matvec.h"
namespace qucs {
Constructor creates an unnamed instance of the matvec class.
*/
matvec::matvec () {
size = 0;
rows = cols = 0;
name = NULL;
data = NULL;
}
Constructor creates an unnamed instance of the matvec class with a
certain number of empty matrices.
\param[in] length number of matrices in the vector
\param[in] r number of rows of each matrix
\param[in] c number of columns of each matrix
*/
matvec::matvec (int length, int r, int c) {
size = length;
rows = r;
cols = c;
name = NULL;
if (size > 0) {
data = new matrix[size];
for (int i = 0; i < size; i++) data[i] = matrix (r, c);
} else {
data = NULL;
}
}
The copy constructor creates a new instance based on the given
matvec object.
*/
matvec::matvec (const matvec & m) {
size = m.size;
rows = m.rows;
cols = m.cols;
name = m.name ? strdup (m.name) : NULL;
data = NULL;
if (size > 0) {
data = new matrix[size];
for (int i = 0; i < size; i++) data[i] = m.data[i];
}
}
Destructor deletes a matvec object.
*/
matvec::~matvec () {
free (name);
delete[] data;
}
\param[in] n constant pointer to the name character array.
*/
void matvec::setName (const char * n) {
free (name);
name = n ? strdup (n) : NULL;
}
\return name of the matvec object
*/
char * matvec::getName (void) {
return name;
}
appropriate matrix indices. */
void matvec::set (qucs::vector v, int r, int c) {
assert (v.getSize () == size &&
r >= 0 && r < rows && c >= 0 && c < cols);
for (int i = 0; i < size; i++) data[i].set (r, c, v.get (i));
}
indices. If the matrix vector has a valid name 'A' the returned
vector gets the name 'A[r,c]'. */
qucs::vector matvec::get (int r, int c) {
assert (r >= 0 && r < rows && c >= 0 && c < cols);
qucs::vector res;
for (int i = 0; i < size; i++) res.add (data[i].get (r, c));
if (name != NULL) {
res.setName (createMatrixString (name, r, c));
}
return res;
}
'n[r,c]' scheme indicating a matrix (vector) entry. */
char * matvec::createMatrixString (const char * n, int r, int c) {
static char str[256];
sprintf (str, "%s[%d,%d]", n, r + 1, c + 1);
return str;
}
'n[r,c]' scheme indicating a matrix (vector) entry but with
different arguments. */
char * matvec::createMatrixString (char n, int r, int c) {
static char str[256];
sprintf (str, "%c[%d,%d]", n, r + 1, c + 1);
return str;
}
matches the 'n[r,c]' pattern it returns the name 'n' and saves the
row and column indices as well. The caller is responsible to
'free()' the returned string. If the vectors name does not match
the pattern the function returns NULL. */
char * matvec::isMatrixVector (const char * n, int& r, int& c) {
const char * p; int len;
char *pnew;
if (n == NULL) return NULL;
if ((p = strchr (n, '[')) != NULL) {
r = atoi (p + 1) - 1;
if ((p = strchr (p, ',')) != NULL) {
c = atoi (p + 1) - 1;
if ((p = strchr (p, ']')) != NULL) {
if (p[1] == '\0') {
if ((len = strchr (n, '[') - n) > 0) {
pnew = (char *) malloc (len + 1);
memcpy (pnew, n, len);
pnew[len] = '\0';
return pnew;
}
}
}
}
}
return NULL;
}
matrix entries specified by `name' and returns the matrix vector
dimensions. */
void matvec::getMatrixVectorSize (qucs::vector * data, char * name,
int& rs, int& cs, int& ss) {
qucs::vector * v;
char * n;
const char *vn;
int r, c, s;
rs = cs = ss = -1;
for (v = data; v != NULL; v = (qucs::vector *) v->getNext ()) {
vn = v->getName ();
if (strstr (vn, name) == vn) {
if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) {
if (rs < r) rs = r;
if (cs < c) cs = c;
s = v->getSize ();
if (ss < s) ss = s;
free (n);
}
}
}
}
matrix entries specified by `name' and returns a matrix vector
object. If there are no such matrices the function returns
NULL. */
matvec * matvec::getMatrixVector (qucs::vector * data, char * name) {
int rs, cs, ss;
getMatrixVectorSize (data, name, rs, cs, ss);
qucs::vector * v;
const char * vn;
char * n;
int r, c;
if (rs >= 0 && cs >= 0 && ss > 0) {
matvec * mv = new matvec (ss, rs + 1, cs + 1);
mv->setName (name);
for (v = data; v; v = (qucs::vector *) v->getNext ()) {
vn = v->getName ();
if (strstr (vn, name) == vn) {
if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) {
mv->set (*v, r, c);
free (n);
}
}
}
return mv;
}
return NULL;
}
specified position. */
void matvec::set (matrix m, int idx) {
assert (m.getRows () == rows && m.getCols () == cols &&
idx >= 0 && idx < size);
data[idx] = m;
}
the given position. */
matrix matvec::get (int idx) {
assert (idx >= 0 && idx < size);
matrix res (data[idx]);
return res;
}
matvec operator + (matvec a, matvec b) {
assert (a.getRows () == b.getRows () && a.getCols () == b.getCols () &&
a.getSize () == b.getSize ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + b.get (i), i);
return res;
}
matvec operator + (matvec a, matrix b) {
assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + b, i);
return res;
}
matvec operator + (matvec a, qucs::vector b) {
assert (a.getSize () == b.getSize ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + b.get (i), i);
return res;
}
matvec operator + (qucs::vector b, matvec a) {
return a + b;
}
matvec operator + (matrix a, matvec b) {
return b + a;
}
matvec operator + (matvec a, nr_complex_t z) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + z, i);
return res;
}
matvec operator + (nr_complex_t z, matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (z + a.get (i), i);
return res;
}
matvec operator + (matvec a, nr_double_t d) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) + d, i);
return res;
}
matvec operator + (nr_double_t d, matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (d + a.get (i), i);
return res;
}
matvec operator - (matvec a, nr_complex_t z) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - z, i);
return res;
}
matvec operator - (nr_complex_t z, matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (z - a.get (i), i);
return res;
}
matvec operator - (matvec a, nr_double_t d) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - d, i);
return res;
}
matvec operator - (nr_double_t d, matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (d - a.get (i), i);
return res;
}
matvec matvec::operator += (matvec a) {
assert (a.getRows () == rows && a.getCols () == cols &&
a.getSize () == size);
for (int i = 0; i < size; i++) data[i] = data[i] + a.get (i);
return *this;
}
matvec operator - (matvec a, matvec b) {
assert (a.getRows () == b.getRows () && a.getCols () == b.getCols () &&
a.getSize () == b.getSize ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - b.get (i), i);
return res;
}
matvec operator - (matvec a, matrix b) {
assert (a.getRows () == b.getRows () && a.getCols () == b.getCols ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) - b, i);
return res;
}
matvec operator - (matrix a, matvec b) {
return -b + a;
}
matvec operator - (matvec a, qucs::vector b) {
return -b + a;
}
matvec operator - (qucs::vector b, matvec a) {
return -a + b;
}
matvec matvec::operator - () {
matvec res (getSize (), getRows (), getCols ());
for (int i = 0; i < getSize (); i++) res.set (-data[i], i);
return res;
}
matvec matvec::operator -= (matvec a) {
assert (a.getRows () == rows && a.getCols () == cols &&
a.getSize () == size);
for (int i = 0; i < a.getSize (); i++) data[i] = data[i] - a.get (i);
return *this;
}
matvec operator * (matvec a, nr_complex_t z) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * z, i);
return res;
}
matvec operator * (nr_complex_t z, matvec a) {
return a * z;
}
matvec operator * (matvec a, nr_double_t d) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * d, i);
return res;
}
matvec operator * (nr_double_t d, matvec a) {
return a * d;
}
matvec operator * (matvec a, qucs::vector b) {
assert (a.getSize () == b.getSize ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * b.get (i), i);
return res;
}
matvec operator * (qucs::vector a, matvec b) {
return b * a;
}
matvec operator / (matvec a, nr_complex_t z) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) / z, i);
return res;
}
matvec operator / (matvec a, nr_double_t d) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) / d, i);
return res;
}
matvec operator / (matvec a, qucs::vector b) {
assert (a.getSize () == b.getSize ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) / b.get (i), i);
return res;
}
matvec operator * (matvec a, matvec b) {
assert (a.getCols () == b.getRows () && a.getSize () == b.getSize ());
matvec res (a.getSize (), a.getRows (), b.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * b.get (i), i);
return res;
}
matvec operator * (matvec a, matrix b) {
assert (a.getCols () == b.getRows ());
matvec res (a.getSize (), a.getRows (), b.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (a.get (i) * b, i);
return res;
}
matvec operator * (matrix a, matvec b) {
return b * a;
}
qucs::vector det (matvec a) {
qucs::vector res (a.getSize ());
for (int i = 0; i < a.getSize (); i++) res.set (det (a.get (i)), i);
return res;
}
matvec inverse (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (inverse (a.get (i)), i);
return res;
}
matvec sqr (matvec a) {
return a * a;
}
matvec pow (matvec a, int n) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (pow (a.get (i), n), i);
return res;
}
matvec pow (matvec a, qucs::vector v) {
assert (a.getSize () == v.getSize ());
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++)
res.set (pow (a.get (i), (int) real (v.get (i))), i);
return res;
}
matvec conj (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (conj (a.get (i)), i);
return res;
}
matvec abs (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (abs (a.get (i)), i);
return res;
}
matvec dB (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (dB (a.get (i)), i);
return res;
}
matvec arg (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (arg (a.get (i)), i);
return res;
}
matvec real (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (real (a.get (i)), i);
return res;
}
matvec imag (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (imag (a.get (i)), i);
return res;
}
also called the adjugate or transpose conjugate. */
matvec adjoint (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (adjoint (a.get (i)), i);
return res;
}
matvec transpose (matvec a) {
matvec res (a.getSize (), a.getCols (), a.getRows ());
for (int i = 0; i < a.getSize (); i++) res.set (transpose (a.get (i)), i);
return res;
}
to scattering parameters with the reference impedance 'z0'. */
matvec stos (matvec s, qucs::vector zref, qucs::vector z0) {
assert (s.getCols () == s.getRows () &&
s.getCols () == zref.getSize () && s.getCols () == z0.getSize ());
matvec res (s.getSize (), s.getCols (), s.getRows ());
for (int i = 0; i < s.getSize (); i++)
res.set (stos (s.get (i), zref, z0), i);
return res;
}
matvec stos (matvec s, nr_complex_t zref, nr_complex_t z0) {
int d = s.getRows ();
return stos (s, qucs::vector (d, zref), qucs::vector (d, z0));
}
matvec stos (matvec s, nr_double_t zref, nr_double_t z0) {
return stos (s, nr_complex_t (zref, 0), nr_complex_t (z0, 0));
}
matvec stos (matvec s, qucs::vector zref, nr_complex_t z0) {
return stos (s, zref, qucs::vector (zref.getSize (), z0));
}
matvec stos (matvec s, nr_complex_t zref, qucs::vector z0) {
return stos (s, qucs::vector (z0.getSize (), zref), z0);
}
matvec stoy (matvec s, qucs::vector z0) {
assert (s.getCols () == s.getRows () && s.getCols () == z0.getSize ());
matvec res (s.getSize (), s.getCols (), s.getRows ());
for (int i = 0; i < s.getSize (); i++) res.set (stoy (s.get (i), z0), i);
return res;
}
matvec stoy (matvec s, nr_complex_t z0) {
return stoy (s, qucs::vector (s.getCols (), z0));
}
matvec ytos (matvec y, qucs::vector z0) {
assert (y.getCols () == y.getRows () && y.getCols () == z0.getSize ());
matvec res (y.getSize (), y.getCols (), y.getRows ());
for (int i = 0; i < y.getSize (); i++) res.set (ytos (y.get (i), z0), i);
return res;
}
matvec ytos (matvec y, nr_complex_t z0) {
return ytos (y, qucs::vector (y.getCols (), z0));
}
matvec stoz (matvec s, qucs::vector z0) {
assert (s.getCols () == s.getRows () && s.getCols () == z0.getSize ());
matvec res (s.getSize (), s.getCols (), s.getRows ());
for (int i = 0; i < s.getSize (); i++) res.set (stoz (s.get (i), z0), i);
return res;
}
matvec stoz (matvec s, nr_complex_t z0) {
return stoz (s, qucs::vector (s.getCols (), z0));
}
matvec ztos (matvec z, qucs::vector z0) {
assert (z.getCols () == z.getRows () && z.getCols () == z0.getSize ());
matvec res (z.getSize (), z.getCols (), z.getRows ());
for (int i = 0; i < z.getSize (); i++) res.set (ztos (z.get (i), z0), i);
return res;
}
matvec ztos (matvec z, nr_complex_t z0) {
return ztos (z, qucs::vector (z.getCols (), z0));
}
matvec ztoy (matvec z) {
assert (z.getCols () == z.getRows ());
matvec res (z.getSize (), z.getCols (), z.getRows ());
for (int i = 0; i < z.getSize (); i++) res.set (ztoy (z.get (i)), i);
return res;
}
matvec ytoz (matvec y) {
assert (y.getCols () == y.getRows ());
matvec res (y.getSize (), y.getCols (), y.getRows ());
for (int i = 0; i < y.getSize (); i++) res.set (ytoz (y.get (i)), i);
return res;
}
forms Y, Z, H, G and A to any other. Also converts S<->(A, T, H, Y
and Z) matrix vectors. */
matvec twoport (matvec m, char in, char out) {
assert (m.getCols () >= 2 && m.getRows () >= 2);
matvec res (m.getSize (), 2, 2);
for (int i = 0; i < m.getSize (); i++)
res.set (twoport (m.get (i), in, out), i);
return res;
}
given S-parameter matrix vector. */
qucs::vector rollet (matvec m) {
assert (m.getCols () >= 2 && m.getRows () >= 2);
qucs::vector res (m.getSize ());
for (int i = 0; i < m.getSize (); i++) res.set (rollet (m.get (i)), i);
return res;
}
S-parameter matrix vector. */
qucs::vector b1 (matvec m) {
assert (m.getCols () >= 2 && m.getRows () >= 2);
qucs::vector res (m.getSize ());
for (int i = 0; i < m.getSize (); i++) res.set (b1 (m.get (i)), i);
return res;
}
matvec rad2deg (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (rad2deg (a.get (i)), i);
return res;
}
matvec deg2rad (matvec a) {
matvec res (a.getSize (), a.getRows (), a.getCols ());
for (int i = 0; i < a.getSize (); i++) res.set (deg2rad (a.get (i)), i);
return res;
}
}