/* * vector.cpp - vector class implementation * * Copyright (C) 2003, 2004, 2005, 2006, 2007 Stefan Jahn * Copyright (C) 2006, 2007 Gunther Kraut * * 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$ * */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include "real.h" #include "complex.h" #include "object.h" #include "logging.h" #include "strlist.h" #include "vector.h" #include "consts.h" namespace qucs { // Constructor creates an unnamed instance of the vector class. vector::vector () : object () { capacity = size = 0; data = NULL; dependencies = NULL; origin = NULL; requested = 0; next = prev = nullptr; } /* Constructor creates an unnamed instance of the vector class with a given initial size. */ vector::vector (int s) : object () { assert (s >= 0); capacity = size = s; data = s > 0 ? (nr_complex_t *) calloc (capacity, sizeof (nr_complex_t)) : NULL; dependencies = NULL; origin = NULL; requested = 0; next = prev = nullptr; } /* Constructor creates an unnamed instance of the vector class with a given initial size and content. */ vector::vector (int s, nr_complex_t val) : object () { assert (s >= 0); capacity = size = s; data = s > 0 ? (nr_complex_t *) calloc (capacity, sizeof (nr_complex_t)) : NULL; for (int i = 0; i < s; i++) data[i] = val; dependencies = NULL; origin = NULL; requested = 0; next = prev = nullptr; } // Constructor creates an named instance of the vector class. vector::vector (const std::string &n) : object (n) { capacity = size = 0; data = NULL; dependencies = NULL; origin = NULL; requested = 0; next = prev = nullptr; } /* This constructor creates a named instance of the vector class with a given initial size. */ vector::vector (const std::string &n, int s) : object (n) { assert (s >= 0); capacity = size = s; data = s > 0 ? (nr_complex_t *) calloc (capacity, sizeof (nr_complex_t)) : NULL; dependencies = NULL; origin = NULL; requested = 0; next = prev = nullptr; } /* The copy constructor creates a new instance based on the given vector object. */ vector::vector (const vector & v) : object (v) { size = v.size; capacity = v.capacity; data = (nr_complex_t *) malloc (sizeof (nr_complex_t) * capacity); memcpy (data, v.data, sizeof (nr_complex_t) * size); dependencies = v.dependencies ? new strlist (*v.dependencies) : NULL; origin = v.origin ? strdup (v.origin) : NULL; requested = v.requested; next = v.next; prev = v.prev; } /* The assignment copy constructor creates a new instance based on the given vector object. It copies the data only and leaves any other properties untouched. */ const vector& vector::operator=(const vector & v) { if (&v != this) { size = v.size; capacity = v.capacity; if (data) { free (data); data = NULL; } if (capacity > 0) { data = (nr_complex_t *) malloc (sizeof (nr_complex_t) * capacity); if (size > 0) memcpy (data, v.data, sizeof (nr_complex_t) * size); } } return *this; } // Destructor deletes a vector object. vector::~vector () { free (data); delete dependencies; free (origin); } // Returns data dependencies. strlist * vector::getDependencies (void) { return dependencies; } // Sets the data dependencies. void vector::setDependencies (strlist * s) { delete dependencies; dependencies = s; } /* The function appends a new complex data item to the end of the vector and ensures that the vector can hold the increasing number of data items. */ void vector::add (nr_complex_t c) { if (data == NULL) { size = 0; capacity = 64; data = (nr_complex_t *) malloc (sizeof (nr_complex_t) * capacity); } else if (size >= capacity) { capacity *= 2; data = (nr_complex_t *) realloc (data, sizeof (nr_complex_t) * capacity); } data[size++] = c; } /* This function appends the given vector to the vector. */ void vector::add (vector * v) { if (v != NULL) { if (data == NULL) { size = 0; capacity = v->getSize (); data = (nr_complex_t *) malloc (sizeof (nr_complex_t) * capacity); } else if (size + v->getSize () > capacity) { capacity += v->getSize (); data = (nr_complex_t *) realloc (data, sizeof (nr_complex_t) * capacity); } for (int i = 0; i < v->getSize (); i++) data[size++] = v->get (i); } } // Returns the complex data item at the given position. nr_complex_t vector::get (int i) { return data[i]; } void vector::set (nr_double_t d, int i) { data[i] = nr_complex_t (d); } void vector::set (const nr_complex_t z, int i) { data[i] = nr_complex_t (z); } // The function returns the current size of the vector. int vector::getSize (void) const { return size; } int vector::checkSizes (vector v1, vector v2) { if (v1.getSize () != v2.getSize ()) { logprint (LOG_ERROR, "vector '%s' and '%s' have different sizes\n", v1.getName (), v2.getName ()); return 0; } return 1; } // searches the maximum value of the vector elements. // complex numbers in the 1. and 4. quadrant are counted as "abs(c)". // complex numbers in the 2. and 3. quadrant are counted as "-abs(c)". nr_double_t vector::maximum (void) { nr_complex_t c; nr_double_t d, max_D = -std::numeric_limits::max(); for (int i = 0; i < getSize (); i++) { c = data[i]; d = fabs (arg (c)) < pi_over_2 ? abs (c) : -abs (c); if (d > max_D) max_D = d; } return max_D; } // searches the minimum value of the vector elements. // complex numbers in the 1. and 4. quadrant are counted as "abs(c)". // complex numbers in the 2. and 3. quadrant are counted as "-abs(c)". nr_double_t vector::minimum (void) { nr_complex_t c; nr_double_t d, min_D = +std::numeric_limits::max(); for (int i = 0; i < getSize (); i++) { c = data[i]; d = fabs (arg (c)) < pi_over_2 ? abs (c) : -abs (c); if (d < min_D) min_D = d; } return min_D; } /* Unwraps a phase vector in radians. Adds +/- 2*Pi if consecutive values jump about |Pi|. */ vector unwrap (vector v, nr_double_t tol, nr_double_t step) { vector result (v.getSize ()); nr_double_t add = 0; result (0) = v (0); for (int i = 1; i < v.getSize (); i++) { nr_double_t diff = real (v (i) - v (i-1)); if (diff > +tol) { add -= step; } else if (diff < -tol) { add += step; } result (i) = v (i) + add; } return result; } nr_complex_t sum (vector v) { nr_complex_t result (0.0); for (int i = 0; i < v.getSize (); i++) result += v.get (i); return result; } nr_complex_t prod (vector v) { nr_complex_t result (1.0); for (int i = 0; i < v.getSize (); i++) result *= v.get (i); return result; } nr_complex_t avg (vector v) { nr_complex_t result (0.0); for (int i = 0; i < v.getSize (); i++) result += v.get (i); return result / (nr_double_t) v.getSize (); } vector signum (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (signum (v.get (i)), i); return result; } vector sign (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (sign (v.get (i)), i); return result; } vector xhypot (vector v, const nr_complex_t z) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (xhypot (v.get(i), z), i); return result; } vector xhypot (vector v, const nr_double_t d) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (xhypot (v.get(i), d), i); return result; } vector xhypot (const nr_complex_t z, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (xhypot (z, v.get (i)), i); return result; } vector xhypot (const nr_double_t d, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (xhypot (d, v.get (i)), i); return result; } vector xhypot (vector v1, vector v2) { int j, i, n, len, len1 = v1.getSize (), len2 = v2.getSize (); if (len1 >= len2) { assert (len1 % len2 == 0); len = len1; } else { assert (len2 % len1 == 0); len = len2; } vector res (len); for (j = i = n = 0; n < len; n++) { res (n) = xhypot (v1 (i), v2 (j)); if (++i >= len1) i = 0; if (++j >= len2) j = 0; } return res; } vector sinc (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (sinc (v.get (i)), i); return result; } vector abs (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (abs (v.get (i)), i); return result; } vector norm (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (norm (v.get (i)), i); return result; } vector arg (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (arg (v.get (i)), i); return result; } vector real (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (real (v.get (i)), i); return result; } vector imag (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (imag (v.get (i)), i); return result; } vector conj (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (conj (v.get (i)), i); return result; } vector dB (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (10.0 * std::log10 (norm (v.get (i))), i); return result; } vector sqrt (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (sqrt (v.get (i)), i); return result; } vector exp (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (exp (v.get (i)), i); return result; } vector limexp (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (limexp (v.get (i)), i); return result; } vector log (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (log (v.get (i)), i); return result; } vector log10 (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (log10 (v.get (i)), i); return result; } vector log2 (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (log2 (v.get (i)), i); return result; } vector pow (vector v, const nr_complex_t z) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (pow (v.get(i), z), i); return result; } vector pow (vector v, const nr_double_t d) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (pow (v.get(i), d), i); return result; } vector pow (const nr_complex_t z, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (pow (z, v.get (i)), i); return result; } vector pow (const nr_double_t d, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (pow (d, v.get (i)), i); return result; } vector pow (vector v1, vector v2) { int j, i, n, len, len1 = v1.getSize (), len2 = v2.getSize (); if (len1 >= len2) { assert (len1 % len2 == 0); len = len1; } else { assert (len2 % len1 == 0); len = len2; } vector res (len); for (j = i = n = 0; n < len; n++) { res (n) = pow (v1 (i), v2 (j)); if (++i >= len1) i = 0; if (++j >= len2) j = 0; } return res; } vector sin (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (sin (v.get (i)), i); return result; } vector asin (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (asin (v.get (i)), i); return result; } vector acos (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (acos (v.get (i)), i); return result; } vector cos (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (cos (v.get (i)), i); return result; } vector tan (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (tan (v.get (i)), i); return result; } vector atan (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (atan (v.get (i)), i); return result; } vector cot (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (cot (v.get (i)), i); return result; } vector acot (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (acot (v.get (i)), i); return result; } vector sinh (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (sinh (v.get (i)), i); return result; } vector asinh (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (asinh (v.get (i)), i); return result; } vector cosh (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (cosh (v.get (i)), i); return result; } vector sech (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (sech (v.get (i)), i); return result; } vector cosech (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (cosech (v.get (i)), i); return result; } vector acosh (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (acosh (v.get (i)), i); return result; } vector asech (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (asech (v.get (i)), i); return result; } vector tanh (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (tanh (v.get (i)), i); return result; } vector atanh (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (atanh (v.get (i)), i); return result; } vector coth (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (coth (v.get (i)), i); return result; } vector acoth (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (acoth (v.get (i)), i); return result; } // converts impedance to reflexion coefficient vector ztor (vector v, nr_complex_t zref) { vector result (v); for (int i = 0; i < v.getSize (); i++) result (i) = ztor (v (i), zref); return result; } // converts admittance to reflexion coefficient vector ytor (vector v, nr_complex_t zref) { vector result (v); for (int i = 0; i < v.getSize (); i++) result (i) = ytor (v (i), zref); return result; } // converts reflexion coefficient to impedance vector rtoz (vector v, nr_complex_t zref) { vector result (v); for (int i = 0; i < v.getSize (); i++) result (i) = rtoz (v (i), zref); return result; } // converts reflexion coefficient to admittance vector rtoy (vector v, nr_complex_t zref) { vector result (v); for (int i = 0; i < v.getSize (); i++) result (i) = rtoy (v (i), zref); return result; } // differentiates 'var' with respect to 'dep' exactly 'n' times vector diff (vector var, vector dep, int n) { int k, xi, yi, exchange = 0; vector x, y; // exchange dependent and independent variable if necessary if (var.getSize () < dep.getSize ()) { x = vector (var); y = vector (dep); exchange++; } else { x = vector (dep); y = vector (var); } assert (y.getSize () % x.getSize () == 0 && x.getSize () >= 2); vector result (y); nr_complex_t c; for (k = 0; k < n; k++) { // differentiate n times for (yi = xi = 0; yi < y.getSize (); yi++, xi++) { if (xi == x.getSize ()) xi = 0; // roll through independent vector if (xi == 0) { c = (y.get (yi + 1) - y.get (yi)) / (x.get (xi + 1) - x.get (xi)); } else if (xi == x.getSize () - 1) { c = (y.get (yi) - y.get (yi - 1)) / (x.get (xi) - x.get (xi - 1)); } else { c = ((y.get (yi) - y.get (yi - 1)) / (x.get (xi) - x.get (xi - 1)) + (y.get (yi + 1) - y.get (yi)) / (x.get (xi + 1) - x.get (xi))) / 2.0; } result.set (exchange ? 1.0 / c : c, yi); } y = result; } return result; } vector vector::operator=(const nr_complex_t c) { for (int i = 0; i < size; i++) data[i] = c; return *this; } vector vector::operator=(const nr_double_t d) { for (int i = 0; i < size; i++) data[i] = d; return *this; } vector vector::operator+=(vector v) { int i, n, len = v.getSize (); assert (size % len == 0); for (i = n = 0; i < size; i++) { data[i] += v (n); if (++n >= len) n = 0; } return *this; } vector vector::operator+=(const nr_complex_t c) { for (int i = 0; i < size; i++) data[i] += c; return *this; } vector vector::operator+=(const nr_double_t d) { for (int i = 0; i < size; i++) data[i] += d; return *this; } vector operator+(vector v1, vector v2) { int len1 = v1.getSize (), len2 = v2.getSize (); vector result; if (len1 >= len2) { result = v1; result += v2; } else { result = v2; result += v1; } return result; } vector operator+(vector v, const nr_complex_t c) { vector result (v); result += c; return result; } vector operator+(const nr_complex_t c, vector v) { return v + c; } vector operator+(vector v, const nr_double_t d) { vector result (v); result += d; return result; } vector operator+(const nr_double_t d, vector v) { return v + d; } vector vector::operator-() { vector result (size); for (int i = 0; i < size; i++) result (i) = -data[i]; return result; } vector vector::operator-=(vector v) { int i, n, len = v.getSize (); assert (size % len == 0); for (i = n = 0; i < size; i++) { data[i] -= v (n); if (++n >= len) n = 0; } return *this; } vector vector::operator-=(const nr_complex_t c) { for (int i = 0; i < size; i++) data[i] -= c; return *this; } vector vector::operator-=(const nr_double_t d) { for (int i = 0; i < size; i++) data[i] -= d; return *this; } vector operator-(vector v1, vector v2) { int len1 = v1.getSize (), len2 = v2.getSize (); vector result; if (len1 >= len2) { result = v1; result -= v2; } else { result = -v2; result += v1; } return result; } vector operator-(vector v, const nr_complex_t c) { vector result (v); result -= c; return result; } vector operator-(vector v, const nr_double_t d) { vector result (v); result -= d; return result; } vector operator-(const nr_complex_t c, vector v) { vector result (-v); result += c; return result; } vector operator-(const nr_double_t d, vector v) { vector result (-v); result += d; return result; } vector vector::operator*=(vector v) { int i, n, len = v.getSize (); assert (size % len == 0); for (i = n = 0; i < size; i++) { data[i] *= v (n); if (++n >= len) n = 0; } return *this; } vector vector::operator*=(const nr_complex_t c) { for (int i = 0; i < size; i++) data[i] *= c; return *this; } vector vector::operator*=(const nr_double_t d) { for (int i = 0; i < size; i++) data[i] *= d; return *this; } vector operator*(vector v1, vector v2) { int len1 = v1.getSize (), len2 = v2.getSize (); vector result; if (len1 >= len2) { result = v1; result *= v2; } else { result = v2; result *= v1; } return result; } vector operator*(vector v, const nr_complex_t c) { vector result (v); result *= c; return result; } vector operator*(vector v, const nr_double_t d) { vector result (v); result *= d; return result; } vector operator*(const nr_complex_t c, vector v) { return v * c; } vector operator*(const nr_double_t d, vector v) { return v * d; } vector vector::operator/=(vector v) { int i, n, len = v.getSize (); assert (size % len == 0); for (i = n = 0; i < size; i++) { data[i] /= v (n); if (++n >= len) n = 0; } return *this; } vector vector::operator/=(const nr_complex_t c) { for (int i = 0; i < size; i++) data[i] /= c; return *this; } vector vector::operator/=(const nr_double_t d) { for (int i = 0; i < size; i++) data[i] /= d; return *this; } vector operator/(vector v1, vector v2) { int len1 = v1.getSize (), len2 = v2.getSize (); vector result; if (len1 >= len2) { assert (len1 % len2 == 0); result = v1; result /= v2; } else { assert (len2 % len1 == 0); result = 1 / v2; result *= v1; } return result; } vector operator/(vector v, const nr_complex_t c) { vector result (v); result /= c; return result; } vector operator/(vector v, const nr_double_t d) { vector result (v); result /= d; return result; } vector operator/(const nr_complex_t c, vector v) { vector result (v); result = c; result /= v; return result; } vector operator/(const nr_double_t d, vector v) { vector result (v); result = d; result /= v; return result; } vector operator%(vector v, const nr_complex_t z) { int len = v.getSize (); vector result (len); for (int i = 0; i < len; i++) result (i) = v (i) % z; return result; } vector operator%(vector v, const nr_double_t d) { int len = v.getSize (); vector result (len); for (int i = 0; i < len; i++) result (i) = v (i) % d; return result; } vector operator%(const nr_complex_t z, vector v) { int len = v.getSize (); vector result (len); for (int i = 0; i < len; i++) result (i) = z % v (i); return result; } vector operator%(const nr_double_t d, vector v) { int len = v.getSize (); vector result (len); for (int i = 0; i < len; i++) result (i) = d % v (i); return result; } vector operator%(vector v1, vector v2) { int j, i, n, len, len1 = v1.getSize (), len2 = v2.getSize (); if (len1 >= len2) { assert (len1 % len2 == 0); len = len1; } else { assert (len2 % len1 == 0); len = len2; } vector res (len); for (j = i = n = 0; n < len; n++) { res (n) = v1 (i) % v2 (j); if (++i >= len1) i = 0; if (++j >= len2) j = 0; } return res; } /* This function reverses the order of the data list. */ void vector::reverse (void) { nr_complex_t * buffer = (nr_complex_t *) malloc (sizeof (nr_complex_t) * size); for (int i = 0; i < size; i++) buffer[i] = data[size - 1 - i]; free (data); data = buffer; capacity = size; } // Sets the origin (the analysis) of the vector. void vector::setOrigin (const char * n) { free (origin); origin = n ? strdup (n) : NULL; } // Returns the origin (the analysis) of the vector. char * vector::getOrigin (void) { return origin; } /* The function returns the number of entries with the given value deviating no more than the given epsilon. */ int vector::contains (nr_complex_t val, nr_double_t eps) { int count = 0; for (int i = 0; i < size; i++) { if (abs (data[i] - val) <= eps) count++; } return count; } // Sorts the vector either in ascending or descending order. void vector::sort (bool ascending) { nr_complex_t t; for (int i = 0; i < size; i++) { for (int n = 0; n < size - 1; n++) { if (ascending ? data[n] > data[n+1] : data[n] < data[n+1]) { t = data[n]; data[n] = data[n+1]; data[n+1] = t; } } } } /* The function creates a linear stepped vector of values starting at the given start value, ending with the given stop value and containing points elements. */ vector linspace (nr_double_t start, nr_double_t stop, int points) { vector result (points); nr_double_t val, step = (stop - start) / (points - 1); for (int i = 0; i < points; i++) { val = start + (i * step); if (i != 0 && fabs (val) < fabs (step) / 4 && fabs (val) < std::numeric_limits::epsilon()) val = 0.0; result.set (val, i); } return result; } /* The function creates a logarithmic stepped vector of values starting at the given start value, ending with the given stop value and containing points elements. */ vector logspace (nr_double_t start, nr_double_t stop, int points) { assert (start * stop > 0); vector result (points); nr_double_t step, first, last, d; // ensure the last value being larger than the first if (fabs (start) > fabs (stop)) { first = fabs (stop); last = fabs (start); } else { first = fabs (start); last = fabs (stop); } // check direction and sign of values d = fabs (start) > fabs (stop) ? -1 : 1; // compute logarithmic step size step = (::log (last) - ::log (first)) / (points - 1); for (int i = 0, j = points - 1; i < points; i++, j--) { if (d > 0) result.set (start * ::exp (step * i), i); else result.set (stop * ::exp (step * i), j); } return result; } vector cumsum (vector v) { vector result (v); nr_complex_t val (0.0); for (int i = 0; i < v.getSize (); i++) { val += v.get (i); result.set (val, i); } return result; } vector cumavg (vector v) { vector result (v); nr_complex_t val (0.0); for (int i = 0; i < v.getSize (); i++) { val = (val * (nr_double_t) i + v.get (i)) / (i + 1.0); result.set (val, i); } return result; } vector cumprod (vector v) { vector result (v); nr_complex_t val (1.0); for (int i = 0; i < v.getSize (); i++) { val *= v.get (i); result.set (val, i); } return result; } vector ceil (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (ceil (v.get (i)), i); return result; } vector fix (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (fix (v.get (i)), i); return result; } vector floor (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (floor (v.get (i)), i); return result; } vector round (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (round (v.get (i)), i); return result; } vector sqr (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (sqr (v.get (i)), i); return result; } vector step (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (step (v.get (i)), i); return result; } static nr_double_t integrate_n (vector v) { /* using trapezoidal rule */ nr_double_t result = 0.0; for (int i = 1; i < v.getSize () - 1; i++) result += norm (v.get (i)); result += 0.5 * norm (v.get (0)); result += 0.5 * norm (v.get (v.getSize () - 1)); return result; } nr_double_t vector::rms (void) { nr_double_t result = std::sqrt (integrate_n (*this) / getSize ()); return result; } nr_double_t vector::variance (void) { nr_double_t result = 0.0; nr_complex_t average = avg (*this); for (int i = 0; i < getSize (); i++) result += norm (get (i) - average); if (getSize () > 1) return result / (getSize () - 1); return 0.0; } nr_double_t vector::stddev (void) { return std::sqrt (variance ()); } vector erf (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (erf (v.get (i)), i); return result; } vector erfc (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (erfc (v.get (i)), i); return result; } vector erfinv (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (erfinv (v.get (i)), i); return result; } vector erfcinv (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (erfcinv (v.get (i)), i); return result; } vector rad2deg (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (rad2deg (v.get (i)), i); return result; } vector deg2rad (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (deg2rad (v.get (i)), i); return result; } vector i0 (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (i0 (v.get (i)), i); return result; } vector jn (const int n, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (jn (n, v.get (i)), i); return result; } vector yn (const int n, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (yn (n, v.get (i)), i); return result; } vector polar (const nr_complex_t a, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (qucs::polar (a, v.get (i)), i); return result; } vector polar (vector v, const nr_complex_t p) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (qucs::polar (v.get (i), p), i); return result; } vector polar (vector a, vector p) { int j, i, n, len, len1 = a.getSize (), len2 = p.getSize (); if (len1 >= len2) { assert (len1 % len2 == 0); len = len1; } else { assert (len2 % len1 == 0); len = len2; } vector res (len); for (j = i = n = 0; n < len; n++) { res (n) = qucs::polar (a (i), p (j)); if (++i >= len1) i = 0; if (++j >= len2) j = 0; } return res; } vector atan2 (const nr_double_t y, vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (atan2 (y, v.get (i)), i); return result; } vector atan2 (vector v, const nr_double_t x) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (atan2 (v.get (i), x) , i); return result; } vector atan2 (vector y, vector x) { int j, i, n, len, len1 = y.getSize (), len2 = x.getSize (); if (len1 >= len2) { assert (len1 % len2 == 0); len = len1; } else { assert (len2 % len1 == 0); len = len2; } vector res (len); for (j = i = n = 0; n < len; n++) { res (n) = atan2 (y (i), x (j)); if (++i >= len1) i = 0; if (++j >= len2) j = 0; } return res; } vector w2dbm (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (10.0 * log10 (v.get (i) / 0.001), i); return result; } vector dbm2w (vector v) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (0.001 * pow (10.0 , v.get (i) / 10.0), i); return result; } nr_double_t integrate (vector v, const nr_double_t h) { nr_double_t s = real (v.get (0) ) / 2; for (int i = 1; i < v.getSize () - 1; i++) s += real (v.get (i)); return (s + real (v.get (v.getSize () - 1) ) / 2) * h; } nr_complex_t integrate (vector v, const nr_complex_t h) { nr_complex_t s; s = v.get (0) / 2.0; for (int i = 1; i < v.getSize () - 1; i++) s += v.get (i); return (s + v.get (v.getSize () - 1) / 2.0) * h; } vector dbm (vector v, const nr_complex_t z) { vector result (v); for (int i = 0; i < v.getSize (); i++) result.set (10.0 * log10 (norm (v.get (i)) / conj (z) / 0.001), i); return result; } vector runavg (const nr_complex_t x, const int n) { vector result (n); for (int i = 0; i < n; i++) result.set (x, i); return result; } vector runavg (vector v, const int n) { nr_complex_t s (0.0), y; int len = v.getSize () - n + 1, i; vector result (len); for (i = 0; i < n; i++) s += v.get (i); y = s / (nr_double_t) n; // first running average value result.set (y, 0); for (i = 0; i < len - 1; i++) { y += (v.get (i + n) - v.get (i)) / (nr_double_t) n; result.set (y, i + 1); } return result; } // smooth a vector over an aperture a // done extending the vector endpoints and using a two-sided moving average // moving average length is always odd vector smooth(vector v, nr_double_t a) { int len = v.getSize (), i; int t2 = floor(len/2 * a / 100); // moving average is over 2*t2+1 elements // auxiliary vector, extend original vector at beginning and end int extvlen = len + 2 * t2; vector extv(extvlen), result (len); // fill auxiliary vector for (i = 0; i < extvlen; i++) { if (i < t2) { extv.set (v(0), i); } else if (i >= (len + t2)) { extv.set (v(len-1), i); } else { extv.set (v(i - t2), i); } } return runavg(extv, 2*t2+1); } //Ths function calculates the group delay from the svec=S[i,j] and frequency vectors vector groupdelay(vector svec, vector freq) { return -diff(unwrap(arg(svec)), (2*pi)*(freq)); } #ifdef DEBUG // Debug function: Prints the vector object. void vector::print (void) { for (int r = 0; r < size; r++) { fprintf (stderr, "%+.2e%+.2ei\n", (double) real (get (r)), (double) imag (get (r))); } } #endif /* DEBUG */ } // namespace qucs