/***************************************************************

      refcalc.c

         Functions for working with profile reference layers.

         Header and library: vector.

     9/20/89 - JR - REFCALC.C
               in function subtract_reference(), changed test against
               ADJ_BADFLOAT from <= to < so it will subtract the mean only
               in the latter case

*/


#include "common.h"
#include "dbext.h"    /* min_val */
#include "vector.h"

/***************************************************************

   array_mean
      Given an array, this returns the mean of the
      elements.  Bad values are neglected.  If there
      are no good values, then BADFLOAT is returned.

*/
#if PROTOTYPE_ALLOWED
double array_mean(float *data, int n)
#else
double array_mean(data, n)
   float *data;
   int n;
#endif
{
   int i, navg=0;
   double x=0;

   for (i=0; i<n; i++, data++)
   {
      if (*data <= ADJ_BADFLOAT)
      {
         x += *data;
         navg++;
      }
   }
   if (navg > 0)  return( x/navg );
   else  return(BADFLOAT);
}                       /* array_mean */

/***************************************************************

   subtract_reference
      Given an array, this subtracts from each element the 
      average of a range of elements.  The range is 
      specified as first, last (inclusive; array indices
      starting from zero).   If the profile does not include
      reference bin range, then the deepest bin will be used.
      The reference value is returned, or BADFLOAT if there
      are no good array values within the reference range, or
      if the first bin is specified as less than zero.
      If there are no good array values within the reference
      range, then the whole array is set to BADFLOAT.
*/

#if PROTOTYPE_ALLOWED
double subtract_reference(float *data, int n, int first, int last)
#else
double subtract_reference(data, n, first, last)
   float *data;
   int n;                   /* number of points in data */
   int first, last;         /* inclusive bin range */
#endif
{
   double ref;
   int nref;
   int i;

   if (first < 0)  return(BADFLOAT);     /* no reference removal */

   last = min_val(n-1, last);
   nref = 1 + last - first;

   if (nref > 0)
      if ( (ref=array_mean(data+first, nref)) <= ADJ_BADFLOAT )
      {
         for (i=0; i<n; i++)
            if (data[i] < ADJ_BADFLOAT)
               data[i] -= ref;
         return(ref);               /* good reference calculation */
      }
   for (i=0; i<n; i++)
      data[i] = BADFLOAT;
   return(BADFLOAT);                /* no good points in reference range */
}
