#ifndef _MATH_H
#define _MATH_H 1

#ifdef NONDP
#include <nondp.h>
#endif

#ifndef HUGE_VAL
#define HUGE_VAL 1.797693134862317E+308
#endif


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

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


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

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


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

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


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

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


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

extern double ceil(double);
extern double fabs(double);
extern double floor(double);
extern double fmod(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 */


#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
#define TINY      2.2e-308
#define LOGHUGE   709.778
#define LOGTINY  -708.396

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

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);

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

#endif /* _STRICT_ANSI */

#endif
