/* RCS $Id: j_tan.c,v 1.2 1997/07/15 14:57:04 ae13 Exp $ */
/*
$Log: j_tan.c,v $
 * Revision 1.2  1997/07/15  14:57:04  ae13
 * *** empty log message ***
 *
 * Revision 1.1  1997/05/16  13:26:20  ae13
 * Initial revision
 *
 */
/****************************************************************/
/*                                                              */
/*      Entries         : a_intv j_tan(a_intv x)                */
/*                        a_intv x  ;                           */
/*                                                              */
/*      Arguments       : x = interval argument of tan(x)       */
/*                                                              */
/*      Description     : Fast interval tangent                 */
/*                        function for double IEEE              */
/*                        Floating-Point Arithmetic             */
/*                                                              */
/*      Date            : 1997-03-10                            */
/*                                                              */
/*      Author          : W. Hofschuster                        */
/*                                                              */
/****************************************************************/

#ifndef ALL_IN_ONE
#ifdef AIX
#include "/u/p88c/runtime/o_defs.h"
#else
#include "o_defs.h"
#endif
#define local
#endif


#include "q_defs.h"
#include "q_fcth.h"

#ifdef LINT_ARGS
local a_intv j_tan(a_intv x)
#else
local a_intv j_tan(x)

a_intv x;
#endif
{
  a_intv res;
  double h1,h2;
  long int k1,k2,q1;

#ifdef PXSCTRAP  
  E_SPUSH("j_tan");
#endif
  if ((x.INF<-q_sint[2])||(x.SUP>q_sint[2]))
    res=q_abortr2(INV_ARG,&x.INF,&x.SUP,12);  /* abs. argument too big */

  if (x.INF==x.SUP)                           /* point interval */
  { 
    if ((x.INF>=-q_sint[4])&&(x.INF<0))
    {
      res.INF=r_pred(x.INF);
      res.SUP=x.INF;
    }
    else if ((x.INF>=0)&&(x.INF<=q_sint[4]))
    {         
      res.INF=x.INF;
      if (x.INF==0)
        res.SUP=0; 
      else
        res.SUP=r_succ(x.INF);
    }
    else
    {
      res.INF=q_tan(x.INF);
      if (res.INF<0)
      {
        res.SUP=res.INF*q_tanm;
        res.INF*=q_tanp;
      }
      else
      {
        res.SUP=res.INF*q_tanp;
        res.INF*=q_tanm;
      }
    }
  }
  else                                      /* x is not a point interval */
  {
    h1=x.INF*q_pi2i; 
    k1=CUTINT(h1);
    if (k1<0) q1=(k1-1)%2; else q1=k1%2; if (q1<0) q1+=2;

    h2=x.SUP*q_pi2i;
    k2=CUTINT(h2); 

    if ((k1==k2) || (q1==1)&(k1==k2-1))
    {
      if ((-q_sint[4]<x.INF)&&(x.INF<0))
        res.INF=r_pred(x.INF);
      else if ((0<=x.INF)&&(x.INF<q_sint[4]))
        res.INF=x.INF;
      else
      { 
        res.INF=q_tan(x.INF);
        if (res.INF>=0)
          res.INF*=q_tanm;
        else
          res.INF*=q_tanp;
      }

      if ((-q_sint[4]<x.SUP)&&(x.SUP<=0))
        res.SUP=x.SUP;
      else if ((0<x.SUP)&&(x.SUP<q_sint[4]))
        res.SUP=r_succ(x.SUP);
      else
      { 
        res.SUP=q_tan(x.SUP);
        if (res.SUP>=0)
          res.SUP*=q_tanp;
        else
          res.SUP*=q_tanm;
      }
    }
    else                                           /* invalid argument */
    {
      res=q_abortr2(INV_ARG,&x.INF,&x.SUP,12);
    }
  }   
  
#ifdef PXSCTRAP
  E_SPOPP("j_tan");
#endif
  return(res);
}
