// Sample Usage:
// gcc -Wall Double.c -o ./Double -lm
// ./Double 6.4 -2 1 0 0.3333333333333333333333333333333333333333333333333333 -4 5
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

static char *binary(long n, int nc) {
  char *str = (char *) malloc(100 * sizeof(char));
  long which = 1;
  int pos = nc + 1;
  for (int i = 0; i < nc; i++) {
    str[pos--] = (n & which) ? '1' : '0';
    if (i == 62 || i == 51) str[pos--] = ' ';
    which <<= 1;
  }
  return str;
}

union
{
  double dbl;
  long i;
  struct {
    unsigned long mant:52;
    unsigned int exp:11;
    unsigned int sgn:1;
  } dStruct;
} dUnion;

int main(int argc, char *argv[]) {
  if (argc < 2) {
    printf("Usage: Double 123.45 -44e4\n");
    exit(0);
  }

  printf("%12s  %-66s  %c  %4s  %18s  %12s\n", "Double", "S Exp(11)     Mantissa(52)", 'S', "Exp", "Mant", "Double");
  for (int i = 1; i < argc; i++) {
    // doubleUnion.dbl = atof(argv[i]);
    // [-] 1.mant x 2**(exp-1023)

    dUnion.dbl = atof(argv[i]);
    // [-] 1.mant x 2**(exp-1023)
    double f = 0;
    if (dUnion.dStruct.exp != 0 || dUnion.dStruct.mant != 0) {
      f = (pow(2, 52) + dUnion.dStruct.mant) / pow(2, (1023 - dUnion.dStruct.exp + 52));
    }
    if (dUnion.dStruct.sgn) f = -f;

    printf("%12g  %s  %c  %4d  %18ld  %12g\n",
    	dUnion.dbl,
    	binary(dUnion.i, 64),
	dUnion.dStruct.sgn ? '-' : '+',
	dUnion.dStruct.exp,
	(long) dUnion.dStruct.mant,
	f);
  }
}

