#include "dbext.h"         /* FLOAT, etc., BAD*, ZERO_SCALE */
/*****************************************************************************
*                                                                            *
*      COMMON OCEANOGRAPHIC DATA ACCESS SYSTEM (CODAS)                       *
*                                                                            *
*      WRITTEN BY:  RAMON CABRERA, ERIC FIRING, and JULIE RANADA             *
*                   JOINT INSTITUTE FOR MARINE AND ATMOSPHERIC RESEARCH      *
*                   1000 POPE ROAD  MSB 404                                  *
*                   HONOLULU, HI 96822                                       *
*                                                                            *
*      VERSION:     3.00                                                     *
*                                                                            *
*      DATE:        APRIL 1989                                               *
*                                                                            *
*****************************************************************************/
/*

       FILE:  unscale.c

              FLOATING POINT SUPPORT FUNCTIONS

*/
/*-----------------------------------------------------------------------------

  FUNCTIONS:  UNSCALE_??_TO_FLOAT

      The unscaling functions accept an array of a specific data type.
      Each array element is then reduced by the given offset and divided
      by the given scale.  The results are returned in another array of
      floating point numbers.

      Note that the scaling and unscaling functions are defined to be
      inverse operations when called
      with the same arguments for offset and scale.

      Results: ??_array[i] = (float_array[i] - *offset) / *scale
               float_array[i] = *offset + *scale * ??_array[i]

      For example, for soundspeed the offset is 1500 m/s and
      the new scale is 1E-2 m/s.

      These functions can be used on single values by calling them
      with the addresses of the variables and setting npts to 1.

   PARAMETERS:

      ??_array = the array of data type specified by ??;
                 for the unscaling functions, this array
                 contains the values that must be unscaled and converted
                 to floating point.

      float_array = the array of floating point numbers;
                    for unscaling, this is used to store
                    the result of the unscaling and conversion.

      scale = pointer to the number by which a value must be factored in order
              to convert from the units in which it is expressed to some
              other unit.

      offset = pointer to the number by which a value must be reduced/increased
               in order to convert from the units in which it is expressed
               to some other unit.

      nv   = pointer to the number of values to be unscaled

*/
/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED
int UNSCALE_BYTE_TO_FLOAT(FLOAT float_array[], BYTE byte_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else
int UNSCALE_BYTE_TO_FLOAT(float_array, byte_array, scale, offset, nv)
FLOAT float_array[];
BYTE byte_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (byte_array[i] != BADBYTE ?
                        byte_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED 
int UNSCALE_UBYTE_TO_FLOAT(FLOAT float_array[], UBYTE ubyte_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else 
int UNSCALE_UBYTE_TO_FLOAT(float_array, ubyte_array, scale, offset, nv)
FLOAT float_array[];
UBYTE ubyte_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (ubyte_array[i] != BADUBYTE ?
                        (FLOAT)ubyte_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED  
int UNSCALE_SHORT_TO_FLOAT(FLOAT float_array[], SHORT short_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else
int UNSCALE_SHORT_TO_FLOAT (float_array, short_array, scale, offset, nv)
FLOAT float_array[];
SHORT short_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (short_array[i] != BADSHORT ?
                        short_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED  
int UNSCALE_USHORT_TO_FLOAT(FLOAT float_array[], USHORT ushort_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else
int UNSCALE_USHORT_TO_FLOAT (float_array, ushort_array, scale, offset, nv)
FLOAT float_array[];
USHORT ushort_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (ushort_array[i] != BADUSHORT ?
                        (FLOAT)ushort_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED  
int UNSCALE_LONG_TO_FLOAT(FLOAT float_array[], LONG long_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else
int UNSCALE_LONG_TO_FLOAT (float_array, long_array, scale, offset, nv)
FLOAT float_array[];
LONG long_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (long_array[i] != BADLONG ?
                        long_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED  
int UNSCALE_ULONG_TO_FLOAT(FLOAT float_array[], ULONG ulong_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else
int UNSCALE_ULONG_TO_FLOAT (float_array, ulong_array, scale, offset, nv)
FLOAT float_array[];
ULONG ulong_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (ulong_array[i] != BADULONG ?
                        ulong_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED  
int UNSCALE_FLOAT_TO_FLOAT(FLOAT float_array[], FLOAT float2_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else
int UNSCALE_FLOAT_TO_FLOAT (float_array, float2_array, scale, offset, nv)
FLOAT float2_array[];
FLOAT float_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (float2_array[i] < ADJ_BADFLOAT ?
                        float2_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

/*---------------------------------------------------------------------------*/

#if PROTOTYPE_ALLOWED  
int UNSCALE_DOUBLE_TO_FLOAT(FLOAT float_array[], DOUBLE double_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv)
#else
int UNSCALE_DOUBLE_TO_FLOAT (float_array, double_array, scale, offset, nv)
FLOAT float_array[];
DOUBLE double_array[];
FLOAT *scale, *offset;
unsigned int *nv;
#endif
{
   unsigned int i;

   if (*scale == 0.0) return(ZERO_SCALE);
   for (i = 0; i < *nv; i++)
      float_array[i] = (double_array[i] < BADDOUBLE ?
                        double_array[i] * *scale + *offset : BADFLOAT);
   return(0);
}

#if PROTOTYPE_ALLOWED
int (*unscale[])(FLOAT out_array[], void *in_array, FLOAT *scale, FLOAT *offset, unsigned int *nv) =
#else
int (*unscale[])() =
#endif
{
   UNSCALE_BYTE_TO_FLOAT,
   UNSCALE_UBYTE_TO_FLOAT,
   UNSCALE_UBYTE_TO_FLOAT,  /* CHAR is UBYTE */
   UNSCALE_SHORT_TO_FLOAT,
   UNSCALE_USHORT_TO_FLOAT,
   UNSCALE_LONG_TO_FLOAT,
   UNSCALE_ULONG_TO_FLOAT,
   UNSCALE_FLOAT_TO_FLOAT,
   UNSCALE_DOUBLE_TO_FLOAT
};


