/*********************************************************************
*
*  Task DBTRANS
*
*
*CODE   0 -> SINE
*       1 -> COSINE
*       2 -> TANGENT
*       3 -> INVERSE SINE
*       4 -> INVERSE COSINE
*       5 -> INVERSE TANGENT
*       6 -> Hyperbolic SINE
*       7 -> Hyperbolic COSINE
*       8 -> Hyperbolic TANGENT
*       9 -> Inverse Hyperbolic SINE
*       10-> Inverse Hyperbolic COSINE
*       11-> Inverse Hyperbolic TANGENT
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <io.h>
#include <time.h>
#include <dos.h>
#include <process.h>
#include <ctype.h>
#include <signal.h>

#include "TISAN.H"

char TMPFILE[_MAX_PATH];

main(argc,argv)
short argc;
char *argv[];
   {
   struct FILEHDR FileHeader;
   char BUFFER[sizeof(struct TXData)];
   struct RData *RDataPntr;
   struct TRData *TRDataPntr;
   struct XData *XDataPntr;
   struct TXData *TXDataPntr;
   double Rval;
   struct complex Zval;
   FILE *INSTR, *OUTSTR;
   short ERRFLAG=0, FLAG=0;
   char INFILE[_MAX_PATH], OUTFILE[_MAX_PATH];

   signal(SIGINT,BREAKREQ);

   if (Ztskinit("DBTRANS",argv[0])) Zexit(1);

   if ((CODE <0) || (CODE > 11))
      {
      Zencode(10,"DBTRANS : CODE Out of Range\n");
      Zexit(1);
      }

   ZBuildFileName(M_inname,INFILE);
   ZBuildFileName(M_outname,OUTFILE);
   ZBuildFileName(M_tmpname,TMPFILE);

   Zencode(2,"DBTRANS : Opening Input File '%s'\n",INFILE);
   if (((INSTR = Zopen(INFILE,O_readb)) == NULL) ||
       (!Zgethead(INSTR,&FileHeader))) Zexit(1);

   switch (FileHeader.type)
      {
      case R_Data:
      case TR_Data:
      case X_Data:
      case TX_Data:
         break;
      default:
         Zencode(10,"DBTRANS : Invalid File Type.\n");
         Zexit(1);
      }

   Zencode(2,"DBTRANS : Opening Scratch File '%s'\n",TMPFILE);
   if ((OUTSTR = Zopen(TMPFILE,O_writeb)) == NULL) Zexit(1);

   if (Zputhead(OUTSTR,&FileHeader))
      {
      ERRFLAG = 1;
      goto EXIT;
      }

   RDataPntr =  (struct  RData *)BUFFER;
   TRDataPntr = (struct TRData *)BUFFER;
   XDataPntr =  (struct  XData *)BUFFER;
   TXDataPntr = (struct TXData *)BUFFER;

   while (Zread(INSTR,BUFFER,FileHeader.type))
      {
      switch (FileHeader.type)
         {
         case R_Data:
            Rval = RDataPntr->y;
            FLAG = RDataPntr->f;
            break;
         case TR_Data:
            Rval = TRDataPntr->y;
            break;
         case X_Data:
            Zval = XDataPntr->z;
            FLAG = RDataPntr->f;
            break;
         case TX_Data:
            Zval = TXDataPntr->z;
            break;
         }

      if (!FLAG)
         {
         switch (CODE)
            {
            case 0: /* SINE of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = sin(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_sin(Zval);
                     break;
                  }
               break;
            case 1: /* COSINE of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = cos(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_cos(Zval);
                     break;
                  }
               break;
            case 2: /* TANGENT of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = tan(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_tan(Zval);
                     break;
                  }
               break;
            case 3: /* INVERSE SINE of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = asin(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_asin(Zval);
                     break;
                  }
               break;
            case 4: /* INVERSE COSINE of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = acos(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_acos(Zval);
                     break;
                  }
               break;
            case 5: /* INVERSE TANGENT of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = atan(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_atan(Zval);
                     break;
                  }
               break;
            case 6: /* Hyperbolic SINE of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = sinh(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_sinh(Zval);
                     break;
                  }
               break;
            case 7: /* Hyperbolic COSINE */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = cosh(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_cosh(Zval);
                     break;
                  }
               break;
            case 8: /* Hyperbolic TANGENT of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = tanh(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_tanh(Zval);
                     break;
                  }
               break;
            case 9: /* INVERSE Hyperbolic SINE of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     Rval = asinh(Rval);
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_asinh(Zval);
                     break;
                  }
               break;
            case 10: /* INVERSE Hyperbolic COSINE of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     if (Rval >= 1.)
                        Rval = acosh(Rval);
                     else
                        {
                        Zencode(9,"DBTRANS : ArcCosh Range Error\n");
                        Rval = 0.;
                        }
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_acosh(Zval);
                     break;
                  }
               break;
            case 11: /* INVERSE Hyperbolic TANGENT of Data */
               switch (FileHeader.type)
                  {
                  case R_Data:
                  case TR_Data:
                     if (Square(Rval) < 1.)
                        Rval = atanh(Rval);
                     else
                        {
                        Zencode(9,"DBTRANS : ArcTanh Range Error\n");
                        Rval = 0.;
                        }
                     break;
                  case X_Data:
                  case TX_Data:
                     Zval = c_atanh(Zval);
                     break;
                  }
               break;
            } /* end switch */
         } /* end if FLAG */

      switch (FileHeader.type)
         {
         case R_Data:
            RDataPntr->y = Rval;
            break;
         case TR_Data:
            TRDataPntr->y = Rval;
            break;
         case X_Data:
            XDataPntr->z = Zval;
            break;
         case TX_Data:
            TXDataPntr->z = Zval;
            break;
         }

      if (Zwrite(OUTSTR,BUFFER,FileHeader.type))
         {
         ERRFLAG = 1;
         break;
         }
      } /* end while */

   if (ferror(INSTR)) ERRFLAG = 1;

EXIT:
   Zclose(INSTR);
   Zclose(OUTSTR);
   ERRFLAG = Znameout(OUTFILE,TMPFILE,ERRFLAG);
   Zexit(ERRFLAG);
   }

/***************************************************************
**
** Process ^C Interrupt
*/
short BREAKREQ()
   {
   fcloseall();
   unlink(TMPFILE);
   Zexit(3);
   }