/* Copyright (c) 1992 SAS Institute, Inc., Cary, NC USA */
/* All Rights Reserved */


#ifndef _MATH_H
#define _MATH_H 1

#ifndef HUGE_VAL
#ifdef _FFP
#define HUGE_VAL 9.2337177e18
#else
#define HUGE_VAL 1.797693134862317E+308
#endif
#endif


/***
*     ANSI trigonometric functions
***/

#ifndef __ARGS
#define __ARGS(x) x
#endif

/* Use the __ARGS macro below to suppress errors  */
/* if these functions have been #defined by other */
/* header files.                                  */

extern double acos  __ARGS((double));
extern double asin  __ARGS((double));
extern double atan  __ARGS((double));
extern double atan2 __ARGS((double, double));
extern double cos   __ARGS((double));
extern double sin   __ARGS((double));
extern double tan   __ARGS((double));


/***
*     ANSI hyperbolic functions
***/

extern double cosh __ARGS((double));
extern double sinh __ARGS((double));
extern double tanh __ARGS((double));


/***
*     ANSI exponential and logarithmic functions
***/

extern double exp __ARGS((double));
extern double frexp __ARGS((double, int *));
extern double ldexp __ARGS((double, int));
extern double log __ARGS((double));
extern double log10 __ARGS((double));
extern double modf __ARGS((double, double *));


/***
*     ANSI power functions
***/

extern double pow __ARGS((double, double));
extern double sqrt __ARGS((double));


/***
*     ANSI nearest integer, absolute value, and remainder functions
***/

extern double ceil __ARGS((double));
extern double fabs __ARGS((double));
extern double floor __ARGS((double));
extern double fmod __ARGS((double, double));


/***
*     Structure to hold information about math exceptions
***/

struct __exception {
    int     type;          /* error type */
    char    *name;         /* math function name */
    double  arg1, arg2;    /* function arguments */
    double  retval;        /* proposed return value */
};

/***
*     Exception type codes, found exception.type
***/

#define _DOMAIN      1    /* domain error */
#define _SING        2    /* singularity */
#define _OVERFLOW    3    /* overflow */
#define _UNDERFLOW   4    /* underflow */
#define _TLOSS       5    /* total loss of significance */
#define _PLOSS       6    /* partial loss of significance */
#define _RANGE       6    /* range error */


/***
*     Error codes generated by basic arithmetic operations (+ - * /)
***/

#define _FPEUND      1    /* underflow */
#define _FPEOVF      2    /* overflow */
#define _FPEZDV      3    /* zero divisor */
#define _FPENAN      4    /* not a number (invalid operation) */
#define _FPECOM      5    /* not comparable */

extern int _FPERR;

#ifndef _STRICT_ANSI

#define DOMAIN    _DOMAIN
#define SING      _SING
#define OVERFLOW  _OVERFLOW
#define UNDERFLOW _UNDERFLOW
#define TLOSS     _TLOSS
#define PLOSS     _PLOSS
#define RANGE     _RANGE

#define FPEUND    _FPEUND
#define FPEOVF    _FPEOVF
#define FPEZDV    _FPEZDV
#define FPENAN    _FPENAN
#define FPECOM    _FPECOM

/***
*     Floating point constants
***/

#define PI      3.14159265358979323846
#define PID2    1.57079632679489661923       /*  PI/2  */
#define PID4    0.78539816339744830962       /*  PI/4  */
#define I_PI    0.31830988618379067154       /*  1/PI  */
#define I_PID2  0.63661977236758134308       /*  1/(PI/2)  */

#define HUGE      HUGE_VAL

#ifdef _FFP
#define TINY      5.42101070e-20
#define LOGHUGE   4.366827e1
#define LOGTINY  -3.922479e1
#else
#define TINY      2.2e-308
#define LOGHUGE   709.778
#define LOGTINY  -708.396
#endif

/***
*     SAS functions (Non-ANSI)
***/

void __stdargs _CXFERR(int);
extern double cot(double);
extern double drand48(void);
extern double erand48(unsigned short *);
extern double except(int, char *, double, double, double);
extern char   *ecvt(double, int, int *, int *);
extern char   *fcvt(double, int, int *, int *);
extern char   *gcvt(double, int, char *);
extern long   jrand48(unsigned short *);
extern void   lcong48(unsigned short *);
extern long   lrand48(void);
extern double __except(int, char *, double, double, double);
extern int    __matherr(struct __exception *);
extern long   mrand48(void);
extern long   nrand48(unsigned short *);
extern double pow2(double);
extern unsigned short *seed48(unsigned short *);
extern void   srand48(long);

#ifndef max
#define   max(a,b)    ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define   min(a,b)    ((a) <= (b) ? (a) : (b))
#endif

#endif /* _STRICT_ANSI */

#endif
