/*
*| Name:
*|      GouldToNative - converts Gould format floating point to native format.
*|
*| Interface:
*|      double
*|      GouldToNative(unsigned char *inVal)
*|
*| Input:
*|      inVal     - input value, pointer to 4 byte Gould format floating point
*|
*| Input and Output:
*|      none
*|
*| Output:
*|      none
*|
*| Return values:
*|      input value converted to native floating point format
*|
*| Remarks:
*|      Gould format description can be found in the NOAA Gvar Transmission
*| Format document, section 3.5.4.
*|
*| Categories:
*|      converter
*/
#include <stdio.h>
#include <string.h>
#include <math.h>

double GouldToNative (
  unsigned char *inVal
)

{
  double nativeVal;
  double temp;
  double dblMant;
  int compVal;
  int sign;
  int exponent;
  float mant;
  unsigned char tmpVal[4];
  union u_tag{
        unsigned char uchar[4];
        long l;
  } u;

 /*
  * an example conversion:
  *
  * input value (hex): BD DA 4D 07
  *  a) convert to binary: 
  *     1011 1110 1101 1010 0100 1101 0000 0111
  *  b) sign bit is set, so take twos complement:
  *     0100 0001 0010 0101 1011 0010 1111 1001
  *  c) convert this back to hex: 41 25 B2 F9
  *  d) mantissa = 2470649
  *  e) exponent = 65
  *  f) tempVal = mantissa / 16 exp (70 - 65)
  *  g) outputVal = tempVal * sign = -2.3561944
  *
  */

  /* load input into a temporary buffer for munging */
  memcpy(tmpVal, inVal, 4);

  /* determine sign of number; if negative, take 2's complement */
  sign = 1;
  if (tmpVal[0] & 0x80) {
    sign = -1;
/*   compVal = TwosComp(* ((int *) inVal)); */
    memcpy(u.uchar, inVal, 4);
/*   printf(" long: %X\n",u.l); */
    compVal = ((unsigned long)u.l ^ (unsigned long)0xffffffff) +1;
/*  printf(" compVal: %X\n",compVal);  */
    memcpy(tmpVal, &compVal, 4);
  }

  /* determine the exponent, biased at 64 */
  exponent = (tmpVal[0] & 0x7f);
  if (exponent == 0)
    exponent = 64;

  /* determine the value of the mantissa, load into a double */
  mant = (float) (tmpVal[3] + (tmpVal[2] * 256) + (tmpVal[1] * 65536));
  dblMant = mant;

  /* now adjust the mantissa according to the exponent */
  temp = pow((double) 16, (double) (70 - exponent));
  nativeVal = dblMant / temp;
  nativeVal = nativeVal * sign;

/*printf(" sign:%d output:%lf\n",sign,nativeVal);*/
  /* return value as a double, caller can cast if needed */
  return nativeVal;

}