#include <math.h>
#include <stdio.h>   
#include "complexf.h"
 /*
 *    command program for fft routine use
 *    program to do fft(s) of standard input & print on standard output
 *    fft subroutine does in place complex to complex transform                
 * Arguments for subroutine call:   
 *    m = number of samples to be analyzed   
 *    isi= -1 for forward transform, +1 for reverse transform 
 *    s = complex array for transforms   
 */

#define PRTARGS \
  while (--argc > 0 ) fprintf(stderr,"%s%c",*++argv, (argc > 1) ? ' ' : '\n');

#define FFTS( GETFFT ,PUTFFT ) \
  for (i=0;i<nffts;++i){ \
    GETFFT  \
    fft(isi,m,s);\
    PUTFFT  \
    }
 
#define SRDEFAULT 1000.0
#define LENFLOAT 4
#define LENWORD 2
#define LENCOMPLEX 2*LENFLOAT
      
#define PUTCOMPLEXFLOAT \
  write(1,s,LENCOMPLEX*m);

#define GETCOMPLEXFLOAT \
  read(0,s,LENCOMPLEX*m); 
 
#define PUTREALFLOAT \
  for ( r0=0; r0 < m; ++r0) { \
    *(fbuff+r0) = s[r0].re; \
    } \
  write(1,s,LENFLOAT*m); 

#define GETREALFLOAT \
  read(0,s,LENFLOAT*m); \
  for ( r0=m-1; r0 >= 0; --r0) { \
    cmplx( *(fbuff+r0), .0, s[r0]); \
    }

#define PUTCOMPLEXASCII \
  for(r0=0;r0<m;++r0) { \
    prtcmplx(s[r0]); \
    printf("\n"); \
    }

#define GETCOMPLEXASCII \
  for(r0=0;r0<m;++r0) { \
    scanf("%f %f",&dr,&di); \
    s[r0].re=dr; s[r0].im=di; \
    }

#define GETREALASCII \
  for(r0=0;r0<m;++r0) { \
    scanf("%f ",&dr); \
    s[r0].re=dr; \
    s[r0].im=0.; \
    }

#define PUTREALASCII \
  for (r0=0;r0<m;++r0) { \
    printf("%15.8e ",s[r0].re); \
    }

#define PUTREALWORD \
  for ( r0=0; r0 < m; ++r0) { \
    *(ibuff+r0) = (int)s[r0].re; \
    } \
  write(1,s,LENWORD*m); 
 
#define GETREALWORD \
  read(0,s,LENWORD*m); \
  for( r0=m-1; r0 >= 0; --r0) { \
    s[r0].re = (float) *(ibuff+r0); \
    s[r0].im = .0; \
    }

/*
 *
 *
 *                                                         */
main(argc,argv)
int argc;
char *argv[];{
  complex s[4096];
  char intype,outtype,*ap;
  int *ibuff;
  long nargs;
  long isi;
  float *fbuff,sr,dr,di,time[3];
  register long nffts;
  register long mv2m1,r0,i,m;
  ibuff = fbuff = &s[0];
  /* default values */
  intype='a';
  outtype='a';
  sr=SRDEFAULT;
  isi= -1;
  m=32;
  nffts=1;
  nargs=argc;
  while (--argc > 0) {
    if ((*++argv)[0] != '-' && nargs-argc < 4){ 
      if (i == 1) m = atol(*argv);
      else time[i-2] = atof(*argv);
      }
    else {    
      for ( ap = argv[0]+1; *ap != '\0'; ap++) {
        switch (*ap) {
          case 'n': 
            nffts=atol(*++argv);
            --argc;
            ap=argv+strlen(*argv);
            break;
          case 'r':
            isi = 1;
            break;
          case 'k': 
            sr=atof(*++argv);
            --argc;
            ap=argv+strlen(*argv);
            break;
          case 'w': 
          case 'f':
          case 'a':
          case 'F':
          case 'A':
            intype = *ap;
            break;
          case 'o': 
            switch ((*++argv)[0]) {
              case'a':
              case'f':
              case'A':
              case'F':
                outtype = (*argv)[0];
                break;
              default:;
              }
            --argc;
            ap=argv+strlen(*argv);
            break;
          case 'l':
          case 'd':
            break;
          default:;
          }
        }
      }
    }
  if (time[1] != 0.) {
    if (sr==0.) sr=SRDEFAULT;
    if (time[1]<0.) nffts=32767;
    else {
      time[1]=time[1]-time[0];
      if (nffts == 1)  nffts=(long) (((time[1]*sr) +1.) /(float) m ) ; 
      }
    }
  fprintf(stderr,"\nCall for %d %d point %c to %c transforms of standard input \ninput type = %c, output type = %c\nnffts=%d start=%f end=%f time increment=%f sr=%f\n",
    nffts,m,intype,outtype,intype,outtype,nffts,time[0],time[1],time[2],sr);
 /*
 *    command program for fft routine use
 *    program to do fft(s) of standard input & print on standard output
 *    fft subroutine does in place complex to complex transform                
 * Arguments for subroutine call:   
 *    m = number of samples to be analyzed   
 *    isi= -1 for forward transform, +1 for reverse transform 
 *    s = complex array for transforms   
 */
  dr=di=0.;
  switch (intype) {
    case'F':
      switch (outtype) {
        case'F':	
          FFTS( GETCOMPLEXFLOAT , PUTCOMPLEXFLOAT )
        break;
        case'f':	
          FFTS( GETCOMPLEXFLOAT , PUTREALFLOAT )
        break;
        case'A':	
          FFTS( GETCOMPLEXFLOAT , PUTCOMPLEXASCII )
        break;
        case'a':	
          FFTS( GETCOMPLEXFLOAT , PUTREALASCII  )
        break;
        default:;
        }
    break;
    case'f':
      switch (outtype) {
        case'F':	
          FFTS( GETREALFLOAT , PUTCOMPLEXFLOAT )
        break;
        case'f':	
          FFTS( GETREALFLOAT , PUTREALFLOAT )
        break;
        case'A':	
          FFTS( GETREALFLOAT , PUTCOMPLEXASCII )
        break;
        case'a':	
          FFTS( GETREALFLOAT , PUTREALASCII  )
        break;
        default:;
        }
    break;
    case'A':
      switch (outtype) {
        case'F':	
          FFTS( GETCOMPLEXASCII , PUTCOMPLEXFLOAT )
        break;
        case'f':	
          FFTS( GETCOMPLEXASCII , PUTREALFLOAT )
        break;
        case'A':	
          FFTS( GETCOMPLEXASCII , PUTCOMPLEXASCII )
        break;
        case'a':	
          FFTS( GETCOMPLEXASCII , PUTREALASCII  )
        break;
        default:;
        }
    break;
    case'a':
      switch (outtype) {
        case'F':	
          FFTS( GETREALASCII , PUTCOMPLEXFLOAT )
        break;
        case'f':	
          FFTS( GETREALASCII , PUTREALFLOAT )
        break;
        case'A':	
          FFTS( GETREALASCII , PUTCOMPLEXASCII )
        break;
        case'a':	
          FFTS( GETREALASCII , PUTREALASCII  )
        break;
        default:;
        }
    break;
    case'w':
      switch (outtype) {
        case'F':	
          FFTS( GETREALWORD , PUTCOMPLEXFLOAT )
        break;
        case'f':	
          FFTS( GETREALWORD , PUTREALFLOAT )
        break;
        case'A':	
          FFTS( GETREALWORD , PUTCOMPLEXASCII )
        break;
        case'a':	
          FFTS( GETREALWORD , PUTREALASCII )
        break;
        case'w':	
          FFTS( GETREALWORD , PUTREALWORD )
        break;
        default:;
        }
    break;
    default:;
    }
    } /* end of main */
