Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Comparing Signals In The Time Domain


May 1991/Comparing Signals In The Time Domain/Listing 1

Listing 1

/*************************************
 *                                   *
 *    LINEAR & NONLINEAR VARIANCE    *
 *            TEST PROGRAM           *
 *                                   *
 *  M.E. Brandt, Ph.D.               *
 *  02/06/91 Revision                *
 *                                   *
 *************************************/

#include <stdio.h>
#include <math.h>
#include <malloc.h>


#define NMAX                   1024
#define NBINS                    10
#define MAX_DELAY                30
#define MAXRAND             32767.0
#define DBL_LEN      sizeof(double)
#define PI        3.141592653589793
#define TWOPI            (2.0 * PI)



double linvar(double *y, double *x, int nn);
double nonlinvar(double *x, double *y, int n, int nbins);
int    number_bins(int x);
void   estimate_delay(double *x, double *y, int n);



main()
{

   int xx, i, j, nb, n, ch;

   double *x, *y, scale, r2, h2, start,
         noise, gain, a, inc, mean, num;
   char u[3], c;


   srand(1);

  /* SELECT A FUNCTION TO TEST */

  do {

       printf("\n\nSelect a y vs. x function and ");
       printf("compute variances:\n");
       printf("\n1. y = ax + noise (linear)");
       printf("\n2. y = sin(x) + noise");
       printf("\n3. y = sgn(x)*(x*x) + noise");
       printf("\n4. y = pow(3*x, 3) + noise");
       printf("\n5. y = pow(5*x, 5) + noise");
       printf("\n6. Exit");
       printf("\n\nSelect 1-6: ");
       scanf ("%d", &ch);

       if(ch == 6) exit(0);

       do {

          printf("\n\nHow many data points?: ");
          scanf("%d", &n);
       }
       while(n > NMAX);

       do {

          printf("\n\nEnter noise gain: ");
          scanf("%lf", &gain);
          }
          while(gain < 0.0 || gain > 1.0);

          /* allocate space for x and y vectors */

          if((x = (double *)malloc(n * DBL_LEN)) == NULL) {
             fprintf(stderr, "\nMalloc error; x\n");
             exit(1);
          }

          if((y = (double *)malloc(n * DBL_LEN)) == NULL) {
             fprintf(stderr, "\nMalloc error; y\n");
             exit(1);
          }

        /* generate a random uniformly distributed x[n]
           between + or - 0.5
        */

        for(i=0; i<n; i++) x[i] =
                         ((double)rand()/MAXRAND - 0.5);


        /* choose y[n] */

        switch(ch) {

           case 1:  printf("\nEnter a: ");
                   scanf("%lf", &a);

                   for(i=0; i<n; i++) {
                      noise = gain *
                         ((double)rand()/MAXRAND - 0.5);
                      y[i] = a * x[i] + noise;
                   }
                   break;

           case 2:  for(i=0; i<n; i++) {
                      noise = gain *
                         ((double)rand()/MAXRAND - 0.5);
                      y[i] = sin(TWOPI * x[i]) + noise;
                   }
                   break;

           case 3:  for(i=0; i<n; i++) {
                      noise = gain *
                         ((double)rand()/MAXRAND - 0.5);
                      y[i] = (x[i] * x[i]);
                      if(x[i] < 0.0) y[i]*= -1.0;
                      y[i] += noise;
                   }
                   break;

           case 4:  for(i=0; i<n; i++) {
                     noise = gain *
                        ((double)rand()/MAXRAND - 0.5);
                     y[i] = pow(3.0*x[i], 3.0) + noise;
                   }
                   break;

           case 5:  for(i=0; i<n; i++) {
                     noise = gain *
                        ((double)rand()/MAXRAND - 0.5);
                     y[i] = pow(5.0*x[i], 5.0) + noise;
                   }
                   break;

          default:  break;

        }

    printf("\nTest delay estimation <y/n>?: ");
    scanf("%s", u);
    c = toupper(*u);
    if(c == 'Y') {
      estimate_delay(x, y, n);
      continue;
    }



    /* compute linear variance of x vs. y */

    r2 = linvar(x, y, n);

    printf("\nLinear r2(x,y) = %f\n", r2);


    /* choose number of bins */

    nb= number_bins(n);

    /* compute nonlinear variance of x vs. y */

    h2 = nonlinvar(x, y, n, nb);

    printf("\nNonlinear h2(x,y) = %f\n", h2);


    /* y vs. x */

    r2 = linvar(y, x, n);

    printf("\nLinear r2(y,x) = %f\n", r2);


    h2 = nonlinvar(y, x, n, nb);

    printf("\nNonlinear h2(y,x) = %f\n", h2);

    free(x); free(y);

  }
  while(1);


}


/* routine to find variances & delay between 2 lagged
   signals */

double buf[NMAX+MAX_DELAY], r2[MAX_DELAY+10],
      h2[MAX_DELAY+10];

void estimate_delay(double *x, double *y, int n)
{
   int i, j, d, delay, lag, max_lag, np, nb;

   double max;


   do {

     printf("\nEnter delay between x and y in samples: ");
     scanf("%d", &delay);
   }
   while((d = abs(delay)) > MAX_DELAY);


   for(i=0; i<d; i++)
      buf[i] = ((double)rand()/MAXRAND - 0.5);
   max_lag = d + 10;

   if(delay > 0) { /* y lags x */

      /* move y to buf */

      for(j=0, i=d; j<n; i++, j++) buf[i] = y[j];

      for(lag=0; lag<max_lag; lag++) {

          np = n - lag;    /* compute across less points */

          /* get linear variance at lag */

          r2[lag] = linvar(x, &buf[lag], np);

          nb= number_bins(np);

          /* get nonlinear variance at lag */

          h2[lag] = nonlinvar(x, &buf[lag], np, nb);

      }
   }

       else if(delay < 0) { /* x lags y */

              for(j=0, i=d; j<n; i++, j++) buf[i] = x[j];

              for(lag=0; lag<max_tag; lag++) {

                  np= n - lag;

                  r2[lag] = linvar(&buf[lag], y, np);

                  nb= number_bins(np);

                  h2[lag] = nonlinvar(&buf[lag], y, np, nb);

              }
       }


      /* find maximum r2 and corresponding delay */

         max = r2[0];
         for(i=1; i<max_lag; i++)
            if(r2[i] > max) {max = r2[i]; j = i;}

         if(delay < 0) j = -j;

         printf("\nTrue delay = %d; maximum r2 = %f \
    found @ sample %d\n",
                 delay, max, j);


      /* find maximum h2 and corresponding delay */

         max = h2[0];
         for(i=1; i<max_lag; i++)
            if(h2[i] > max) {max = h2[i]; j = i;}

         if(delay < 0) j = -j;

         printf("\nTrue delay = %d; maximum h2 = %f \
    found @ sample %d\n",
                 delay, max, j);


    }

    /* compute number of bins for nonlinear variance calc. */

    int number_bins(int x)
    {
        int y;

        if(x < 129) y = NBINS - 4;
        else
        if(x < 257) y = NBINS - 3;
        else
        if(x < 513) y = NBINS - 2;
        else        y = NBINS;

        return y;

    }

    /* routine to compute linear variance measure */

    double linvar(double *y, double *x, int nn)
    {

       register int j;

       double z, smx, smy, sqx, sqy, sxy, corr;
       double sqrt(), varx, vary, cov, nnn;



    /* initialize values */

    nnn = (double)nn;

    corr = sqy = 0.0;


    smx = 0.0;
    smy = 0.0;
    sqx = 0.0;
    sxy = 0.0;

    for(j=0; j<nn; j++) {

       smx += x[j];
       smy += y[j];
       sqx += (x[j] * x[j]);
       sxy += (x[j] * y[j]);


       sqy += (y[j) * y[j]);


    } /* end for */

    /* Compute covariance and variances */

    cov = (nnn * sxy) - (smx * smy);
    varx = (nnn * sqx) - (smx * smx);



    vary = (nnn * sqy) - (smy * smy);

    z = sqrt(varx * vary);

    if(z != 0.0) corr = cov / z;
    else corr = 0.0;

    return(corr*corr);

    }

    /* routine to compute nonlinear variance measure */

    int bin[NBINS] [2*NMAX/NBINS];
    double q[NBINS], p[NBINS];

    double nonlinvar(double *x, double *y, int n, int nbins)
    {
        int i, J, k, l, index, index2, last;

        double min, max, range, width, hwidth, start, end,
              mean, mean2, totvar, unvar, s, f, h2, uu, offset;


         /* find max and min of x array */

         min = max = x[0]; last = 0;

         for(i=1; i<n; i++) {
            if(x[i] > max) {max = x[i]; last = i;}
            else
            if(x[i] < min) min = x[i];
         }

         range = max - min;

         width = range/(double)nbins;

         hwidth = width/2.0;

         for(i=0; i<nbins; i++) bin[i][0] = 0;

        /* get histogram of indexes */

        for(i=0; i<n; i++) {
           for(j=0; j<nbins; j++) {
              start = (double)j*width + min;
              end = start + width;

              if((x[i] >= start) && (x[i] < end)) {
                 ++bin[j][0];
                 bin[j][bin[j][0]] = i;
                 break;
              }
           }
         }

     /* maximum x value (last one) */

     j = nbins-1;
     ++bin[j][0];
     bin[j][bin[j][0]] = last;

   /* compute x-midpoints and y average amplitudes */

    mean2 = 0.0;
    offset = hwidth + min;

    for(i=0; i<nbins; i++) {

       /* x value midpoints for each bin */

       p[i]= ((double)i * width) + offset;

       /* corresponding y average amplitudes */

       mean = 0.0;

       for(k=1; k<=bin[i][0]; k++) mean += y[bin[i][k]];

       q[i] = mean/double)bin[i][0];
       mean2 += mean;

    }


    mean = mean2/(double)n;     /* overall */


    /* compute h*h coefficient */

    /* first compute total variance of y */

    totvar = 0.0;
    for(i=0; i<n; i++) {
        s = y[i] - mean;
        totvar += (s * s);
    }

    /* compute total unexplained variance of y */

    unvar = 0.0;
    for(i=0; i<n; i++) {

        /* find f(x[i]), the nonlinear value */

        for(j=1; j<nbins-1; j++){
           if(x[i] <= p[j]) {
              index = j-1;
              goto out1;
           }
        }

        index = nbins-2;

  out1:
        index2 = index++;

        f = ((q[index2] - q[index])/
            (p[index2] - p[index])) *
              (x[i] - p[index]) + q[index];

        uu = y[i] - f;
        unvar += (uu * uu);

    }

    /* now compute nonlinear regression coefficient */


    h2 = 1.0 - (unvar/totvar);

    return h2;

}


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.