#ifndef _MATH_H
#define _MATH_H

/*
 *  Header file for the maths related routines in C
 *
 * AMENDMENT HISTORY
 * ~~~~~~~~~~~~~~~~~
 *  23 Oct 93   DJW   - modff() now a routine instead of mapping to modf()
 *
 *  25 Mar 95   DJW   - Added missing Unix constants and functions
 *
 *  15 Nov 95   DJW   - made the HUGE_VAL and HUGE macros point to a
 *                      global constant instead of hard coding the answer.
 */

#ifndef _SYS_TYPES_H
#include <sys/types.h>
#endif

#include <sys/math.h>

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

/**
*
* 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 in 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 */

/**
 *
 * 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 */
 
/**
*
* ANSI mandated Constants 
*
*/
#define HUGE_VAL   (_Infinity)              /* ISO version of huge value */
/**
 *      Unix SVR4 constants
 **
#define M_E     2.7182818284590452354       /* Base of natural logarithm (e) */
#define M_LN2   0.69314718055994530942      /* The natural logarithm of 2 */
#define M_LOG2E 1.4426950408889633870E0     /* The base-2 logarithm of e */
#define M_LN10  2.30258509299404568402      /* The natural logarithm of 10 */
#define M_LOG10E 4.3429448190325182765E-1   /* The base-10 logarithm of e */
#define M_PI    3.14159265358979323846
#define M_PI_2  1.57079632679489661923      /* PI divided by 2 */
#define M_PI_4  0.78539816339744830962      /* PI divided by 4 */
#define M_1_PI  0.31830988618379067154      /* Inverse of PI */
#define M_2_PI  0.63661977236758134308      /* Inverse of PID2 */
#define M_2_SQRTPI 1.12837916709551257390   /* 2 divided by square root of PI */
#define M_SQRT2 1.41421356237309514556      /* positive square root of 2 */
#define M_SQRT1_2 0.70710678118654752440    /* positive sqare root of 1/2 */
#define MAXFLOAT 3.40282346638528860e+38

#define HUGE     (_HUGE_VAL)            /* Traditional Unix value */
/**
 *
 *  LATTICE constants
 *
**/
#define PI   3.14159265358979323846
#define PI2  6.28318530717958647693     /* PI times 2 */
#define PID2 1.57079632679489661923     /* PI divided by 2 */
#define PID4 0.78539816339744830962     /* PI divided by 4 */
#define I_PI 0.31830988618379067154     /* Inverse of PI */
#define I_PID2 0.63661977236758134308   /* Inverse of PID2 */
 
#define TINY 2.2e-308                   /* tiny value */
#define LOGHUGE 709.778                 /* natural log of huge value */
#define LOGTINY -708.396                /* natural log of tiny value */

/**
*
* External declarations
*
*/
extern int _fperr;      /* floating point internal arithmetic error */
extern int errno;       /* UNIX error code */
extern int signgam;

#ifdef __STDC__
#define _P_(params) params
#else
#define _P_(params)
#endif

/**
 *
 *      ANSI defined routines
 *
**/
double acos         _P_((double));
double asin         _P_((double));
double atan         _P_((double));
double atan2        _P_((double, double));
double ceil         _P_((double));
double cos          _P_((double));
double cosh         _P_((double));
double exp          _P_((double));
double fabs         _P_((double));
double floor        _P_((double));
double fmod         _P_((double, double));
double frexp        _P_((double, int *));
double ldexp        _P_((double, int));
double log          _P_((double));
double log10        _P_((double));
double modf         _P_((double, double *));
double pow          _P_((double, double));
double sin          _P_((double));
double sinh         _P_((double));
double sqrt         _P_((double));
double tan          _P_((double));
double tanh         _P_((double));
/**
 *
 *      UNIX/POSIX Routines
 *
**/
int    matherr  _P_((struct exception *));

double acosh        _P_((double));
double asinh        _P_((double));
double atanh        _P_((double));
double cbrt         _P_((double));
double copysign     _P_((double ,double));
double cot          _P_((double));
double erf          _P_((double));
double erfc         _P_((double));
double hypot        _P_((double ,double));
double logb         _P_((double));
double nextafter    _P_((double, double));
double remainder    _P_((double,double));
double rint         _P_((double));
double scalb        _P_((double, double));

double j0           _P_((double));
double j1           _P_((double));
double jn           _P_((int ,double));
double y0           _P_((double));
double y1           _P_((double));
double yn           _P_((int ,double));

double gamma        _P_((double));
double lgamma       _P_((double));

int    finite       _P_((double));
int    isnan        _P_((double));
int    unordered    _P_((double, double));

/**
 *
 *      Versions of routines with float parameters
 *      (under K&R compilers these are normally directly
 *      equivalent to those that take double parameters)
 *      For C68 a few have revised algorithms for
 *      increased speed.  Even those that do not have
 *      not have revised algorithms should be faster at
 *      the expense of accuracy as the use 'float' arithmetic
 *      rather than the 'double' variety.
 *
**/
#define acosf(param)        (float)acos((double)(param))
#define asinf(param)        (float)asin((double)(param))
#define atan2f(param)       (float)atan2((double)(param))
#define atanf(param)        (float)atan((double)(param))
float   ceilf               _P_((float));
#define cosf(param)         (float)cos((double)(param))
#define coshf(param)        (float)cosh((double)(param))
float   expf                _P_((float));
float   fabsf               _P_((float));
float   floorf              _P_((float));
float   fmodf               _P_((float,float));
float   logf                _P_((float));
float   log10f              _P_((float));
float   modff               _P_((float, float *));
float   powf                _P_((float,float));
#define sinf(param)         (float)sin((double)(param))
#define sinhf(param)        (float)sinh((double)(param))
float   sqrtf               _P_((float));
#define tanf(param)         (float)tan((double)(param))
#define tanhf(param)        (float)tanh((double)(param))
/**
 *
 *      LATTICE specific routines?
 *
**/
#define arctan   atan
double  except   _P_((int, char *, double, double, double));
char *  ecvt     _P_((double, int, int *, int *));
char *  fcvt     _P_((double, int, int *, int *));
char *  gcvt     _P_((double, int, char *));

#ifdef _LIBM_SOURCE
#ifndef __LIBRARY__
#define __LIBRARY__
#endif
#endif

#ifdef __LIBRARY__
/*************************************************************************
 *
 *                          C A U T I O N
 *                          ~~~~~~~~~~~~~
 *
 *  The remainder of this header contains definitions that are internal
 *  to the way that the C68 libraries have been implemented on QDOS/SMS.
 *  These definitions should not be used by any user program as they are
 *  subject to change without notice.
 *
 *************************************************************************/

/*
 *  Functions that are private to maths library
 */

double _mult        _P_((double, double));
double _poly        _P_((double, double *, int));

#endif /* __LIBRARY__ */

#undef _P_

#endif /* _MATH_H */

