#include #include "dbhost.h" /* PROTOTYPE_ALLOWED */ #include "dbext.h" /* FLOAT, etc., MIN*, MAX*, 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: scale.c FLOATING POINT SUPPORT FUNCTIONS */ /*----------------------------------------------------------------------------- FUNCTIONS: SCALE_FLOAT_TO_?? The scaling functions accept an array of floating point numbers and perform the inverse of the unscaling operations. The results are returned in an array of the specified data type. 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 scaling functions, this array is used to store the result of the scaling operation; float_array = the array of floating point numbers; for scaling, this contains the values that must be scaled and converted to some other data type; 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 scaled nbad = on exit, this contains the number of values in the resulting array that have been set to BAD?? because the scaling result was out of range. */ #define out_of_range(min, max) (fs < min || fs > max ? printf("\n WARNING: attempt to convert float out of range\n original float: %f\n scaled: %f\n", float_array[i], fs) : 0 ) /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_BYTE(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; BYTE *byte_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { byte_array[i] = BADBYTE; if (float_array[i] < ADJ_BADFLOAT) { fs = (int) round_val( (float_array[i] - *offset) / *scale ); if (!out_of_range(MINBYTE, MAXBYTE)) byte_array[i] = fs; else (*nbad)++; } } return(0); } /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_UBYTE(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; UBYTE *ubyte_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { ubyte_array[i] = BADUBYTE; if (float_array[i] < ADJ_BADFLOAT) { fs = (int) round_val( (float_array[i] - *offset) / *scale ); if (!out_of_range((double)MINUBYTE, (double)MAXUBYTE)) ubyte_array[i] = fs; else (*nbad)++; } } return(0); } /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_SHORT(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; SHORT *short_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { short_array[i] = BADSHORT; if (float_array[i] < ADJ_BADFLOAT) { fs = (long int) round_val( (float_array[i] - *offset) / *scale ); if (!out_of_range(MINSHORT, MAXSHORT)) short_array[i] = fs; else (*nbad)++; } } return(0); } /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_USHORT(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; USHORT *ushort_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { ushort_array[i] = BADUSHORT; if (float_array[i] < ADJ_BADFLOAT) { fs = (unsigned long int) round_val( (float_array[i] - *offset) / *scale ); if (!out_of_range((double)MINUSHORT, (double)MAXUSHORT)) ushort_array[i] = fs; else (*nbad)++; } } return(0); } /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_LONG(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; LONG *long_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { long_array[i] = BADLONG; if (float_array[i] < ADJ_BADFLOAT) { fs = round_val( (float_array[i] - *offset) / *scale ); if (!out_of_range((double)MINLONG, (double)MAXLONG)) long_array[i] = fs; else (*nbad)++; } } return(0); } /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_ULONG(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; ULONG *ulong_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { ulong_array[i] = BADULONG; if (float_array[i] < ADJ_BADFLOAT) { fs = round_val( (float_array[i] - *offset) / *scale ); if (!out_of_range(MINULONG, MAXULONG)) ulong_array[i] = fs; else (*nbad)++; } } return(0); } /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_FLOAT(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; FLOAT *float2_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { float2_array[i] = BADFLOAT; if (float_array[i] < ADJ_BADFLOAT) { fs = (float_array[i] - *offset) / *scale; if (!out_of_range(-MAXFLOAT, MAXFLOAT)) float2_array[i] = fs; else (*nbad)++; } } return(0); } /*---------------------------------------------------------------------------*/ int SCALE_FLOAT_TO_DOUBLE(void *out_array, FLOAT float_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) { unsigned int i; double fs; DOUBLE *double_array = out_array; if (*scale == 0.0) return(ZERO_SCALE); *nbad = 0; for (i = 0; i < *nv; i++) { double_array[i] = BADDOUBLE; if (float_array[i] < ADJ_BADFLOAT) { fs = (float_array[i] - *offset) / *scale; if (!out_of_range(-MAXDOUBLE, MAXDOUBLE)) double_array[i] = fs; else (*nbad)++; } } return(0); } int (*scale[])(void *out_array, FLOAT in_array[], FLOAT *scale, FLOAT *offset, unsigned int *nv, unsigned int *nbad) = { SCALE_FLOAT_TO_BYTE, SCALE_FLOAT_TO_UBYTE, SCALE_FLOAT_TO_UBYTE, /* CHAR is UBYTE */ SCALE_FLOAT_TO_SHORT, SCALE_FLOAT_TO_USHORT, SCALE_FLOAT_TO_LONG, SCALE_FLOAT_TO_ULONG, SCALE_FLOAT_TO_FLOAT, SCALE_FLOAT_TO_DOUBLE };