/*
 * Signal processing functions:
 *
 * spf_mean()
 * spf_mean_f()
 * spf_rms()
 * spf_rms_f()
 * spf_max()
 * spf_max_f()
 * spf_min()
 * spf_min_f()
 * spf_fir()
 *
 */

#include <math.h>
 
/*
 * This function takes a vector of step*turns elements,
 * averages elements at  [m*turns..(m+1)*turns-1] and
 * fills in vector out of step elements
 */
void spf_mean(double *in, double *out, int step, int turns)
{
  int m, k;

  for (m = 0; m < step; m++)
  {
    *(out + m) = 0.0;
    for (k = 0; k < turns; k++)
      *(out + m) += *(in +m*turns + k)/turns;
  }
}

/*
 * This function takes a vector of step*turns elements,
 * averages squares of elements at  [m*turns..(m+1)*turns-1] and
 * fills in vector out of step elements with sqrt(mean(in^2))
 */
void spf_rms(double *in, double *out, int step, int turns)
{
  int m, k;

  for (m = 0; m < step; m++)
  {
    *(out + m) = 0.0;
    for (k = 0; k < turns; k++)
      *(out + m) += pow(*(in + m*turns + k), 2.0)/turns;
    *(out + m) = sqrt(*(out + m));
  }
}

/*
 * This function takes a vector of nelm elements and
 * finds a maximum.
 */
int spf_max(double *in, double *mval, int nelm)
{
  int m, k;

  *mval = in[0]; k = 0;
  for (m = 1; m < nelm; m++)
    if (in[m] > *mval)
    {
      *mval = in[m];
      k = m;
    }
  return k;
}

/*
 * This function takes a vector of nelm elements and
 * finds a minimum.
 */
int spf_min(double *in, double *mval, int nelm)
{
  int m, k;

  *mval = in[0]; k = 0;
  for (m = 1; m < nelm; m++)
    if (in[m] < *mval)
    {
      *mval = in[m];
      k = m;
    }
  return k;
}

/*
 * This function takes a vector of step*turns elements,
 * averages elements at  [m*turns..(m+1)*turns-1] and
 * fills in vector out of step elements
 */
void spf_mean_f(float *in, double *out, int step, int turns)
{
  int m, k;

  for (m = 0; m < step; m++)
  {
    *(out + m) = 0.0;
    for (k = 0; k < turns; k++)
      *(out + m) += *(in +m*turns + k)/turns;
  }
}

/*
 * This function takes a vector of step*turns elements,
 * averages squares of elements at  [m*turns..(m+1)*turns-1] and
 * fills in vector out of step elements with sqrt(mean(in^2))
 */
void spf_rms_f(float *in, double *out, int step, int turns)
{
  int m, k;

  for (m = 0; m < step; m++)
  {
    *(out + m) = 0.0;
    for (k = 0; k < turns; k++)
      *(out + m) += pow(*(in + m*turns + k), 2.0)/turns;
    *(out + m) = sqrt(*(out + m));
  }
}

/*
 * This function takes a vector of nelm elements and
 * finds a maximum.
 */
int spf_max_f(float *in, double *mval, int nelm)
{
  int m, k;

  *mval = in[0]; k = 0;
  for (m = 1; m < nelm; m++)
    if (in[m] > *mval)
    {
      *mval = in[m];
      k = m;
    }
  return k;
}

/*
 * This function takes a vector of nelm elements and
 * finds a minimum.
 */
int spf_min_f(float *in, double *mval, int nelm)
{
  int m, k;

  *mval = in[0]; k = 0;
  for (m = 1; m < nelm; m++)
    if (in[m] < *mval)
    {
      *mval = in[m];
      k = m;
    }
  return k;
}

void spf_fir(double *in, double *out, int step, int turns,
             double *coeff, int clen)
{
  int k, m, n;
  
  /* Step through bunches */
  for (k = 0; k < step; k++)
    /* Step through samples */
    for (m = clen - 1; m < turns; m++)
    {
      *(out + k*turns + m) = 0.0;
      /* Step through coefficients */
      for (n = 0; n < clen; n++)
        *(out + k*turns + m) += *(in + k*turns + m - n) * coeff[n];
    }
}
