LCOV - code coverage report
Current view: top level - src - interpolator.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 0 190 0.0 %
Date: 2015-01-05 16:01:02 Functions: 0 17 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 214 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * interpolator.cpp - interpolator class implementation
       3                 :            :  *
       4                 :            :  * Copyright (C) 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                 :            : 
      25                 :            : #if HAVE_CONFIG_H
      26                 :            : # include <config.h>
      27                 :            : #endif
      28                 :            : 
      29                 :            : #include <stdio.h>
      30                 :            : #include <stdlib.h>
      31                 :            : #include <string.h>
      32                 :            : #include <assert.h>
      33                 :            : 
      34                 :            : #include "poly.h"
      35                 :            : #include "spline.h"
      36                 :            : #include "object.h"
      37                 :            : #include "vector.h"
      38                 :            : #include "interpolator.h"
      39                 :            : 
      40                 :            : namespace qucs {
      41                 :            : 
      42                 :            : // Constructor creates an instance of the interpolator class.
      43                 :          0 : interpolator::interpolator () {
      44                 :          0 :   rsp = isp = NULL;
      45                 :          0 :   rx = ry = NULL;
      46                 :          0 :   cy = NULL;
      47                 :          0 :   repeat = dataType = interpolType = length = 0;
      48                 :          0 :   duration = 0.0;
      49                 :          0 : }
      50                 :            : 
      51                 :            : 
      52                 :            : // Destructor deletes an instance of the interpolator class.
      53                 :          0 : interpolator::~interpolator () {
      54 [ #  # ][ #  # ]:          0 :   if (rsp) delete rsp;
         [ #  # ][ #  # ]
      55 [ #  # ][ #  # ]:          0 :   if (isp) delete isp;
         [ #  # ][ #  # ]
      56 [ #  # ][ #  # ]:          0 :   if (rx) free (rx);
      57 [ #  # ][ #  # ]:          0 :   if (ry) free (ry);
      58 [ #  # ][ #  # ]:          0 :   if (cy) free (cy);
      59                 :          0 : }
      60                 :            : 
      61                 :            : // Cleans up vector storage.
      62                 :          0 : void interpolator::cleanup (void) {
      63         [ #  # ]:          0 :   if (rx) { free (rx); rx = NULL; }
      64         [ #  # ]:          0 :   if (ry) { free (ry); ry = NULL; }
      65         [ #  # ]:          0 :   if (cy) { free (cy); cy = NULL; }
      66                 :          0 : }
      67                 :            : 
      68                 :            : // Pass real interpolation datapoints as pointers.
      69                 :          0 : void interpolator::vectors (nr_double_t * y, nr_double_t * x, int len) {
      70                 :          0 :   int len1 = len;
      71                 :          0 :   int len2 = 2 + len * sizeof (nr_double_t);
      72         [ #  # ]:          0 :   if (len > 0) {
      73                 :          0 :     ry = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
      74                 :          0 :     memcpy (ry, y, len1 * sizeof (nr_double_t));
      75                 :            :   }
      76         [ #  # ]:          0 :   if (len > 0) {
      77                 :          0 :     rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
      78                 :          0 :     memcpy (rx, x, len1 * sizeof (nr_double_t));
      79                 :            :   }
      80                 :            : 
      81                 :          0 :   dataType = (DATA_REAL & DATA_MASK_TYPE);
      82                 :          0 :   length = len;
      83                 :          0 : }
      84                 :            : 
      85                 :            : // Pass real interpolation datapoints as vectors.
      86                 :          0 : void interpolator::rvectors (vector * y, vector * x) {
      87                 :          0 :   int len  = y->getSize ();
      88                 :          0 :   int len1 = len;
      89                 :          0 :   int len2 = 2 + len * sizeof (nr_double_t);
      90                 :          0 :   cleanup ();
      91         [ #  # ]:          0 :   if (len > 0) {
      92                 :          0 :     ry = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
      93         [ #  # ]:          0 :     for (int i = 0; i < len1; i++) ry[i] = real (y->get (i));
      94                 :            :   }
      95         [ #  # ]:          0 :   if (len > 0) {
      96                 :          0 :     rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
      97         [ #  # ]:          0 :     for (int i = 0; i < len1; i++) rx[i] = real (x->get (i));
      98                 :            :   }
      99                 :            : 
     100                 :          0 :   dataType = (DATA_REAL & DATA_MASK_TYPE);
     101                 :          0 :   length = len;
     102                 :          0 : }
     103                 :            : 
     104                 :            : // Pass complex interpolation datapoints as pointers.
     105                 :          0 : void interpolator::vectors (nr_complex_t * y, nr_double_t * x, int len) {
     106                 :          0 :   int len1 = len;
     107                 :          0 :   int len2 = 2 + len;
     108                 :          0 :   cleanup ();
     109         [ #  # ]:          0 :   if (len > 0) {
     110                 :          0 :     cy = (nr_complex_t *) malloc (len2 * sizeof (nr_complex_t));
     111                 :          0 :     memcpy (cy, y, len1 * sizeof (nr_complex_t));
     112                 :            :   }
     113         [ #  # ]:          0 :   if (len > 0) {
     114                 :          0 :     rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
     115                 :          0 :     memcpy (rx, x, len1 * sizeof (nr_double_t));
     116                 :            :   }
     117                 :            : 
     118                 :          0 :   dataType = (DATA_COMPLEX & DATA_MASK_TYPE);
     119                 :          0 :   length = len;
     120                 :          0 : }
     121                 :            : 
     122                 :            : // Pass complex interpolation datapoints as vectors.
     123                 :          0 : void interpolator::cvectors (vector * y, vector * x) {
     124                 :          0 :   int len  = y->getSize ();
     125                 :          0 :   int len1 = len;
     126                 :          0 :   int len2 = 2 + len;
     127                 :          0 :   cleanup ();
     128         [ #  # ]:          0 :   if (len > 0) {
     129                 :          0 :     cy = (nr_complex_t *) malloc (len2 * sizeof (nr_complex_t));
     130         [ #  # ]:          0 :     for (int i = 0; i < len1; i++) cy[i] = y->get (i);
     131                 :            :   }
     132         [ #  # ]:          0 :   if (len > 0) {
     133                 :          0 :     rx = (nr_double_t *) malloc (len2 * sizeof (nr_double_t));
     134         [ #  # ]:          0 :     for (int i = 0; i < len1; i++) rx[i] = real (x->get (i));
     135                 :            :   }
     136                 :            : 
     137                 :          0 :   dataType = (DATA_COMPLEX & DATA_MASK_TYPE);
     138                 :          0 :   length = len;
     139                 :          0 : }
     140                 :            : 
     141                 :            : // Prepares interpolator instance, e.g. setups spline object.
     142                 :          0 : void interpolator::prepare (int interpol, int repitition, int domain) {
     143                 :          0 :   interpolType = interpol;
     144                 :          0 :   dataType |= (domain & DATA_MASK_DOMAIN);
     145                 :          0 :   repeat = repitition;
     146                 :            : 
     147                 :            :   // preparations for cyclic interpolations
     148         [ #  # ]:          0 :   if (repeat & REPEAT_YES) {
     149                 :          0 :     duration = rx[length - 1] - rx[0];
     150                 :            :     // set first value to the end of the value vector
     151         [ #  # ]:          0 :     if (cy) cy[length - 1] = cy[0];
     152         [ #  # ]:          0 :     if (ry) ry[length - 1] = ry[0];
     153                 :            :   }
     154                 :            : 
     155                 :            :   // preparations for polar complex data
     156 [ #  # ][ #  # ]:          0 :   if (cy != NULL && (domain & DATA_POLAR) && length > 1) {
                 [ #  # ]
     157                 :            :     // unwrap phase of complex data vector
     158         [ #  # ]:          0 :     vector ang = vector (length);
     159         [ #  # ]:          0 :     for (int i = 0; i < length; i++) ang (i) = arg (cy[i]);
     160 [ #  # ][ #  # ]:          0 :     ang = unwrap (ang);
         [ #  # ][ #  # ]
                 [ #  # ]
     161                 :            :     // store complex data
     162         [ #  # ]:          0 :     for (int i = 0; i < length; i++) {
     163                 :          0 :       cy[i] = nr_complex_t (abs (cy[i]), real (ang (i)));
     164         [ #  # ]:          0 :     }
     165                 :            :   }
     166                 :            : 
     167                 :            :   // preparations spline interpolations
     168         [ #  # ]:          0 :   if (interpolType & INTERPOL_CUBIC) {
     169                 :            : 
     170                 :            :     // prepare complex vector interpolation using splines
     171         [ #  # ]:          0 :     if (cy != NULL) {
     172                 :            :       // create splines if necessary
     173 [ #  # ][ #  # ]:          0 :       if (rsp) delete rsp;
                 [ #  # ]
     174 [ #  # ][ #  # ]:          0 :       if (isp) delete isp;
                 [ #  # ]
     175 [ #  # ][ #  # ]:          0 :       rsp = new spline (SPLINE_BC_NATURAL);
     176 [ #  # ][ #  # ]:          0 :       isp = new spline (SPLINE_BC_NATURAL);
     177         [ #  # ]:          0 :       if (repeat & REPEAT_YES) {
     178                 :          0 :         rsp->setBoundary (SPLINE_BC_PERIODIC);
     179                 :          0 :         isp->setBoundary (SPLINE_BC_PERIODIC);
     180                 :            :       }
     181                 :            :       // prepare data vectors
     182         [ #  # ]:          0 :       vector rv = vector (length);
     183         [ #  # ]:          0 :       vector iv = vector (length);
     184         [ #  # ]:          0 :       vector rt = vector (length);
     185         [ #  # ]:          0 :       for (int i = 0; i < length; i++) {
     186                 :          0 :         rv (i) = real (cy[i]);
     187                 :          0 :         iv (i) = imag (cy[i]);
     188                 :          0 :         rt (i) = rx[i];
     189                 :            :       }
     190                 :            :       // pass data vectors to splines and construct these
     191 [ #  # ][ #  # ]:          0 :       rsp->vectors (rv, rt);
         [ #  # ][ #  # ]
                 [ #  # ]
     192 [ #  # ][ #  # ]:          0 :       isp->vectors (iv, rt);
         [ #  # ][ #  # ]
                 [ #  # ]
     193         [ #  # ]:          0 :       rsp->construct ();
     194 [ #  # ][ #  # ]:          0 :       isp->construct ();
         [ #  # ][ #  # ]
     195                 :            :     }
     196                 :            : 
     197                 :            :     // prepare real vector interpolation using spline
     198                 :            :     else {
     199 [ #  # ][ #  # ]:          0 :       if (rsp) delete rsp;
     200         [ #  # ]:          0 :       rsp = new spline (SPLINE_BC_NATURAL);
     201         [ #  # ]:          0 :       if (repeat & REPEAT_YES) rsp->setBoundary (SPLINE_BC_PERIODIC);
     202                 :          0 :       rsp->vectors (ry, rx, length);
     203                 :          0 :       rsp->construct ();
     204                 :            :     }
     205                 :            :   }
     206                 :          0 : }
     207                 :            : 
     208                 :            : /* The function performs a binary search on the ascending sorted
     209                 :            :    x-vector in order to return the left-hand-side index pointer into
     210                 :            :    the x-vector based on the given value. */
     211                 :          0 : int interpolator::findIndex (nr_double_t x) {
     212                 :          0 :   int lo = 0;
     213                 :          0 :   int hi = length;
     214                 :            :   int av;
     215         [ #  # ]:          0 :   while (lo < hi) {
     216                 :          0 :     av = lo + ((hi - lo) / 2);
     217         [ #  # ]:          0 :     if (x >= rx[av])
     218                 :          0 :       lo = av + 1;
     219                 :            :     else
     220                 :            :       // can't be hi = av-1: here rx[av] >= x,
     221                 :            :       // so hi can't be < av if rx[av] == x
     222                 :          0 :       hi = av;
     223                 :            :   }
     224                 :            :   // hi == lo, using hi or lo depends on taste
     225 [ #  # ][ #  # ]:          0 :   if (lo <= length && lo > 0 && x >= rx[lo - 1])
                 [ #  # ]
     226                 :          0 :     return lo - 1; // found
     227                 :            :   else
     228                 :          0 :     return 0; // not found
     229                 :            : }
     230                 :            : 
     231                 :            : /* Return the left-hand-side index pointer into the x-vector based on
     232                 :            :    the given value.  Returns 0 or 'length' if the value is beyond the
     233                 :            :    x-vectors scope. */
     234                 :          0 : int interpolator::findIndex_old (nr_double_t x) {
     235                 :          0 :   int idx = 0;
     236         [ #  # ]:          0 :   for (int i = 0; i < length; i++) {
     237         [ #  # ]:          0 :     if (x >= rx[i]) idx = i;
     238                 :            :   }
     239                 :          0 :   return idx;
     240                 :            : }
     241                 :            : 
     242                 :            : /* Computes simple linear interpolation value for the given values. */
     243                 :          0 : nr_double_t interpolator::linear (nr_double_t x,
     244                 :            :                                   nr_double_t x1, nr_double_t x2,
     245                 :            :                                   nr_double_t y1, nr_double_t y2) {
     246         [ #  # ]:          0 :   if (x1 == x2)
     247                 :          0 :     return (y1 + y2) / 2;
     248                 :            :   else
     249                 :          0 :     return ((x2 - x) * y1 + (x - x1) * y2) / (x2 - x1);
     250                 :            : }
     251                 :            : 
     252                 :            : /* Returns real valued linear interpolation. */
     253                 :          0 : nr_double_t interpolator::rlinear (nr_double_t x, int idx) {
     254                 :          0 :   return linear (x, rx[idx], rx[idx+1], ry[idx], ry[idx+1]);
     255                 :            : }
     256                 :            : 
     257                 :            : /* Returns complex valued linear interpolation. */
     258                 :          0 : nr_complex_t interpolator::clinear (nr_double_t x, int idx) {
     259                 :            :   nr_double_t x1, x2, r, i;
     260                 :          0 :   nr_complex_t y1, y2;
     261                 :          0 :   x1 = rx[idx]; x2 = rx[idx+1];
     262                 :          0 :   y1 = cy[idx]; y2 = cy[idx+1];
     263                 :          0 :   r = linear (x, x1, x2, real (y1), real (y2));
     264                 :          0 :   i = linear (x, x1, x2, imag (y1), imag (y2));
     265                 :          0 :   return nr_complex_t (r, i);
     266                 :            : }
     267                 :            : 
     268                 :            : /* This function interpolates for real values.  Returns the linear
     269                 :            :    interpolation of the real y-vector for the given value in the
     270                 :            :    x-vector. */
     271                 :          0 : nr_double_t interpolator::rinterpolate (nr_double_t x) {
     272                 :          0 :   int idx = -1;
     273                 :          0 :   nr_double_t res = 0.0;
     274                 :            : 
     275                 :            :   // no chance to interpolate
     276         [ #  # ]:          0 :   if (length <= 0) {
     277                 :          0 :     return res;
     278                 :            :   }
     279                 :            :   // no interpolation necessary
     280         [ #  # ]:          0 :   else if (length == 1) {
     281                 :          0 :     res = ry[0];
     282                 :          0 :     return res;
     283                 :            :   }
     284         [ #  # ]:          0 :   else if (repeat & REPEAT_YES)
     285                 :          0 :     x = x - std::floor (x / duration) * duration;
     286                 :            : 
     287                 :            :   // linear interpolation
     288         [ #  # ]:          0 :   if (interpolType & INTERPOL_LINEAR) {
     289                 :          0 :     idx = findIndex (x);
     290                 :            :     // dependency variable in scope or beyond
     291         [ #  # ]:          0 :     if (x == rx[idx])
     292                 :          0 :       res = ry[idx];
     293                 :            :     // dependency variable is beyond scope; use last tangent
     294                 :            :     else {
     295         [ #  # ]:          0 :       if (idx == length - 1) idx--;
     296                 :          0 :       res = rlinear (x, idx);
     297                 :            :     }
     298                 :            :   }
     299                 :            :   // cubic spline interpolation
     300         [ #  # ]:          0 :   else if (interpolType & INTERPOL_CUBIC) {
     301                 :            :     // evaluate spline functions
     302                 :          0 :     res = rsp->evaluate (x).f0;
     303                 :            :   }
     304         [ #  # ]:          0 :   else if (interpolType & INTERPOL_HOLD) {
     305                 :            :     // find appropriate dependency index
     306                 :          0 :     idx = findIndex (x);
     307                 :          0 :     res = ry[idx];
     308                 :            :   }
     309                 :          0 :   return res;
     310                 :            : }
     311                 :            : 
     312                 :            : /* This function interpolates for complex values.  Returns the complex
     313                 :            :    interpolation of the real y-vector for the given value in the
     314                 :            :    x-vector. */
     315                 :          0 : nr_complex_t interpolator::cinterpolate (nr_double_t x) {
     316                 :          0 :   int idx = -1;
     317                 :          0 :   nr_complex_t res = 0.0;
     318                 :            : 
     319                 :            :   // no chance to interpolate
     320         [ #  # ]:          0 :   if (length <= 0) {
     321                 :          0 :     return res;
     322                 :            :   }
     323                 :            :   // no interpolation necessary
     324         [ #  # ]:          0 :   else if (length == 1) {
     325                 :          0 :     res = cy[0];
     326                 :          0 :     return res;
     327                 :            :   }
     328         [ #  # ]:          0 :   else if (repeat & REPEAT_YES)
     329                 :          0 :     x = x - std::floor (x / duration) * duration;
     330                 :            : 
     331                 :            :   // linear interpolation
     332         [ #  # ]:          0 :   if (interpolType & INTERPOL_LINEAR) {
     333                 :          0 :     idx = findIndex (x);
     334                 :            :     // dependency variable in scope or beyond
     335         [ #  # ]:          0 :     if (x == rx[idx])
     336                 :          0 :       res = cy[idx];
     337                 :            :     // dependency variable is beyond scope; use last tangent
     338                 :            :     else {
     339         [ #  # ]:          0 :       if (idx == length - 1) idx--;
     340                 :          0 :       res = clinear (x, idx);
     341                 :            :     }
     342                 :            :   }
     343                 :            :   // cubic spline interpolation
     344         [ #  # ]:          0 :   else if (interpolType & INTERPOL_CUBIC) {
     345                 :            :     // evaluate spline functions
     346         [ #  # ]:          0 :     nr_double_t r = rsp->evaluate (x).f0;
     347         [ #  # ]:          0 :     nr_double_t i = isp->evaluate (x).f0;
     348                 :          0 :     res = nr_complex_t (r, i);
     349                 :            :   }
     350         [ #  # ]:          0 :   else if (interpolType & INTERPOL_HOLD) {
     351                 :            :     // find appropriate dependency index
     352                 :          0 :     idx = findIndex (x);
     353                 :          0 :     res = cy[idx];
     354                 :            :   }
     355                 :            : 
     356                 :            :   // depending on the data type return appropriate complex value
     357         [ #  # ]:          0 :   if (dataType & DATA_POLAR)
     358                 :          0 :     return std::polar (real (res), imag (res));
     359                 :            :   else
     360                 :          0 :     return res;
     361                 :            : }
     362                 :            : 
     363                 :            : } // namespace qucs

Generated by: LCOV version 1.11