mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
8.3 KiB
297 lines
8.3 KiB
/***
|
|
*trans.h - definitions for computing transcendentals
|
|
*
|
|
* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose: Define constants and macros that are used for computing
|
|
* transcendentals. Some of the definitions are machine dependent.
|
|
* Double is assumed to conform to the IEEE 754 std format.
|
|
*
|
|
*Revision History:
|
|
* 08-14-91 GDP written
|
|
* 10-29-91 GDP removed unused prototypes, added _frnd
|
|
* 01-20-92 GDP significant changes -- IEEE exc. support
|
|
* 03-27-92 GDP put IEEE definitions in fpieee.h
|
|
* 03-31-92 GDP add internal constants for _ctrlfp, _statfp
|
|
* 05-08-92 PLM added M68K switch
|
|
* 05-18-92 XY added exception macro under M68K switch
|
|
* 06-04-92 XY changed to long double version
|
|
*
|
|
*******************************************************************************/
|
|
#include <fpieee.h>
|
|
|
|
#define LD_BIASM1 0x3ffe /* LD_BIAS - 1 */
|
|
|
|
#ifdef B_END
|
|
/* big endian */
|
|
#define LD_EXP(x) ((unsigned short *)&(x))
|
|
#define LD_HI(x) ((unsigned long *)(&(x)+2))
|
|
#define LD_LO(x) ((unsigned long *)(&(x)+6))
|
|
#else
|
|
#define LD_EXP(x) ((unsigned short *)(&(x)+8))
|
|
#define LD_HI(x) ((unsigned long *)(&(x)+4))
|
|
#define LD_LO(x) ((unsigned long *)&(x))
|
|
#endif
|
|
|
|
/* return the int representation of the exponent
|
|
* if x = .f * 2^n, 0.5<=f<1, return n (unbiased)
|
|
* e.g. INTEXP(3.0) == 2
|
|
*/
|
|
#define INTEXPL(x) ((signed short)((*LD_EXP(x) & 0x7fff)) - LD_BIASM1)
|
|
|
|
|
|
/* check for infinity, NAN */
|
|
#define LD_ISINF(x) (( *LD_EXP(x) == 0x7fff) && *LD_HI(x) == 0 && *LD_LO(x) == 0)
|
|
#define IS_LD_SPECIAL(x) ((*LD_EXP(x) & 0x7fff) == 0x7fff)
|
|
#define IS_LD_NAN(x) (IS_LD_SPECIAL(x) && !LD_ISINF(x))
|
|
|
|
#define IS_LD_QNAN(x) ((*LD_EXP(x) & 0x7fff) == 0x7fff && (*LD_HI(x) == 0x80000000))
|
|
#define IS_LD_SNAN(x) ((*LD_EXP(x) & 0x7fff) == 0x7fff && \
|
|
(*LD_HI(x) && 0x80000000 == 0) && (*LD_HI(x) || *LD_LO(x)))
|
|
|
|
|
|
#define IS_LD_DENORM(x) ((*LD_EXP(x) & 0x7fff) == 0 && \
|
|
(*LD_HI(x) << 4 || *LD_LO(x)))
|
|
|
|
|
|
#define IS_LD_INF(x) (*LD_EXP(x) == 0x7fff && *LD_HI(x) == 0 && *LD_LO(x) == 0)
|
|
#define IS_LD_MINF(x) (*LD_EXP(x) == 0xffff && *LD_HI(x) == 0 && *LD_LO(x) == 0)
|
|
|
|
#ifdef MIPS
|
|
#define D_IND_HI 0x7ff7ffff
|
|
#define D_IND_LO 0xffffffff
|
|
#else
|
|
#define LD_IND_EXP 0xffff
|
|
#define LD_IND_HI 0x80000000
|
|
#define LD_IND_LO 0x0
|
|
#endif
|
|
|
|
typedef unsigned char u_char; /* should have 1 byte */
|
|
|
|
typedef union {
|
|
u_char lng[10];
|
|
long double ldbl;
|
|
} _ldbl;
|
|
|
|
extern _ldbl _ld_inf;
|
|
extern _ldbl _ld_ind;
|
|
extern _ldbl _ld_max;
|
|
extern _ldbl _ld_min;
|
|
|
|
#define LD_INF (_ld_inf.ldbl)
|
|
#define LD_IND (_ld_ind.ldbl)
|
|
#define LD_MAX (_ld_max.ldbl)
|
|
#define LD_MIN (_ld_min.ldbl)
|
|
|
|
/* min and max exponents for normalized numbers in the
|
|
* form: 0.xxxxx... * 2^exp (NOT 1.xxxx * 2^exp !)
|
|
*/
|
|
#define MAXEXP 32767
|
|
#define MINEXP -32764
|
|
|
|
#ifdef i386
|
|
|
|
/* Control word for computation of transcendentals */
|
|
#define ICW 0x133f
|
|
|
|
#define IMCW 0xffff
|
|
|
|
#define IMCW_EM 0x003f /* interrupt Exception Masks */
|
|
#define IEM_INVALID 0x0001 /* invalid */
|
|
#define IEM_DENORMAL 0x0002 /* denormal */
|
|
#define IEM_ZERODIVIDE 0x0004 /* zero divide */
|
|
#define IEM_OVERFLOW 0x0008 /* overflow */
|
|
#define IEM_UNDERFLOW 0x0010 /* underflow */
|
|
#define IEM_INEXACT 0x0020 /* inexact (precision) */
|
|
|
|
|
|
#define IMCW_RC 0x0c00 /* Rounding Control */
|
|
#define IRC_CHOP 0x0c00 /* chop */
|
|
#define IRC_UP 0x0800 /* up */
|
|
#define IRC_DOWN 0x0400 /* down */
|
|
#define IRC_NEAR 0x0000 /* near */
|
|
|
|
#define ISW_INVALID 0x0001 /* invalid */
|
|
#define ISW_DENORMAL 0x0002 /* denormal */
|
|
#define ISW_ZERODIVIDE 0x0004 /* zero divide */
|
|
#define ISW_OVERFLOW 0x0008 /* overflow */
|
|
#define ISW_UNDERFLOW 0x0010 /* underflow */
|
|
#define ISW_INEXACT 0x0020 /* inexact (precision) */
|
|
|
|
#define IMCW_PC 0x0300 /* Precision Control */
|
|
#define IPC_24 0x0000 /* 24 bits */
|
|
#define IPC_53 0x0200 /* 53 bits */
|
|
#define IPC_64 0x0300 /* 64 bits */
|
|
|
|
#define IMCW_IC 0x1000 /* Infinity Control */
|
|
#define IIC_AFFINE 0x1000 /* affine */
|
|
#define IIC_PROJECTIVE 0x0000 /* projective */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MIPS
|
|
#define ICW 0x00000f80 /* Internal CW for transcendentals */
|
|
#define IMCW 0xffffff83 /* Internal CW Mask */
|
|
|
|
#define IMCW_EM 0x00000f80 /* interrupt Exception Masks */
|
|
#define IEM_INVALID 0x00000800 /* invalid */
|
|
#define IEM_ZERODIVIDE 0x00000400 /* zero divide */
|
|
#define IEM_OVERFLOW 0x00000200 /* overflow */
|
|
#define IEM_UNDERFLOW 0x00000100 /* underflow */
|
|
#define IEM_INEXACT 0x00000080 /* inexact (precision) */
|
|
|
|
|
|
#define IMCW_RC 0x00000003 /* Rounding Control */
|
|
#define IRC_CHOP 0x00000001 /* chop */
|
|
#define IRC_UP 0x00000002 /* up */
|
|
#define IRC_DOWN 0x00000003 /* down */
|
|
#define IRC_NEAR 0x00000000 /* near */
|
|
|
|
|
|
#define ISW_INVALID (1<<6) /* invalid */
|
|
#define ISW_ZERODIVIDE (1<<5) /* zero divide */
|
|
#define ISW_OVERFLOW (1<<4) /* overflow */
|
|
#define ISW_UNDERFLOW (1<<3) /* underflow */
|
|
#define ISW_INEXACT (1<<2) /* inexact (precision) */
|
|
|
|
#endif
|
|
|
|
#ifdef _M_M68K
|
|
|
|
#include "trans.a"
|
|
|
|
/* LATER -- we don't handle exception until Mac OS has better support on it */
|
|
#define _except1(FP_P, op, arg1, res, cw) _set_statfp(cw),(res)
|
|
#define _except2(FP_P, op, arg1, arg2, res, cw) _set_statfp(cw),(res)
|
|
#define _handle_qnan1(opcode, x, savedcw) _rstorfp(savedcw), (x);
|
|
#define _handle_qnan2(opcode, x, y, savedcw) _rstorfp(savedcw), (x+y);
|
|
|
|
#endif /* _M_M68K*/
|
|
|
|
#define RETURN(fpcw,result) return _rstorfp(fpcw),(result)
|
|
|
|
#define RETURN_INEXACT1(op,arg1,res,cw) \
|
|
if (cw & IEM_INEXACT) { \
|
|
_rstorfp(cw); \
|
|
return res; \
|
|
} \
|
|
else { \
|
|
return _except1(FP_P, op, arg1, res, cw); \
|
|
}
|
|
|
|
|
|
#define RETURN_INEXACT2(op,arg1,arg2,res,cw) \
|
|
if (cw & IEM_INEXACT) { \
|
|
_rstorfp(cw); \
|
|
return res; \
|
|
} \
|
|
else { \
|
|
return _except2(FP_P, op, arg1, arg2, res, cw); \
|
|
}
|
|
|
|
|
|
//handle NaN propagation
|
|
#define _d_snan2(x,y) ((x)+(y))
|
|
#define _s2qnan(x) ((x)+1.0)
|
|
|
|
|
|
|
|
#define _maskfp() _ctrlfp(ICW, IMCW)
|
|
#define _rstorfp(cw) _ctrlfp(cw, IMCW)
|
|
|
|
|
|
#define ABS(x) ((x)<0 ? -(x) : (x) )
|
|
|
|
int _d_inttypel(long double);
|
|
#define _D_NOINT 0
|
|
#define _D_ODD 1
|
|
#define _D_EVEN 2
|
|
|
|
// IEEE exceptions
|
|
#define FP_O 0x01
|
|
#define FP_U 0x02
|
|
#define FP_Z 0x04
|
|
#define FP_I 0x08
|
|
#define FP_P 0x10
|
|
|
|
// An extra flag for matherr support
|
|
// Set together with FP_I from trig functions when the argument is too large
|
|
#define FP_TLOSS 0x20
|
|
|
|
// special types
|
|
#define T_PINF 1
|
|
#define T_NINF 2
|
|
#define T_QNAN 3
|
|
#define T_SNAN 4
|
|
|
|
|
|
// exponent adjustment for IEEE overflow/underflow exceptions
|
|
// used before passing the result to the trap handler
|
|
|
|
#define IEEE_ADJUST 1536
|
|
|
|
// QNAN values
|
|
|
|
#define INT_NAN (~0)
|
|
|
|
#define QNAN_SQRT LD_IND
|
|
#define QNAN_LOG LD_IND
|
|
#define QNAN_LOG10 LD_IND
|
|
#define QNAN_POW LD_IND
|
|
#define QNAN_SINH LD_IND
|
|
#define QNAN_COSH LD_IND
|
|
#define QNAN_TANH LD_IND
|
|
#define QNAN_SIN1 LD_IND
|
|
#define QNAN_SIN2 LD_IND
|
|
#define QNAN_COS1 LD_IND
|
|
#define QNAN_COS2 LD_IND
|
|
#define QNAN_TAN1 LD_IND
|
|
#define QNAN_TAN2 LD_IND
|
|
#define QNAN_ACOS LD_IND
|
|
#define QNAN_ASIN LD_IND
|
|
#define QNAN_ATAN2 LD_IND
|
|
#define QNAN_CEIL LD_IND
|
|
#define QNAN_FLOOR LD_IND
|
|
#define QNAN_MODF LD_IND
|
|
#define QNAN_LDEXP LD_IND
|
|
#define QNAN_FMOD LD_IND
|
|
#define QNAN_FREXP LD_IND
|
|
|
|
|
|
/*
|
|
* Function prototypes
|
|
*/
|
|
|
|
long double _set_expl(long double x, int exp);
|
|
long double _set_bexpl(long double x, int exp);
|
|
long double _add_expl(long double x, int exp);
|
|
long double _frndl(long double);
|
|
long double _fsqrtl(long double);
|
|
#ifndef _M_M68K
|
|
double _except1(int flags, int opcode, double arg, double res, unsigned int cw);
|
|
double _except2(int flags, int opcode, double arg1, double arg2, double res, unsigned int cw);
|
|
#endif
|
|
int _sptypel(long double);
|
|
int _get_expl(long double);
|
|
long double _decompl(long double, int *);
|
|
int _powhlpl(long double x, long double y, long double * result);
|
|
extern unsigned int _fpstatus;
|
|
long double _frndl(long double);
|
|
long double _exphlpl(long double, int *);
|
|
#ifndef _M_M68K
|
|
double _handle_qnan1(unsigned int op, double arg, unsigned int cw);
|
|
double _handle_qnan2(unsigned int op,double arg1,double arg2,unsigned int cw);
|
|
#endif
|
|
unsigned int _clhwfp(void);
|
|
unsigned int _setfpcw(unsigned int);
|
|
int _errcode(unsigned int flags);
|
|
void _set_errno(int matherrtype);
|
|
int _handle_excl(unsigned int flags, long double * presult, unsigned int cw);
|
|
unsigned int _clrfp(void);
|
|
unsigned int _ctrlfp(unsigned int,unsigned int);
|
|
unsigned int _statfp(void);
|
|
#ifdef _M_M68K
|
|
void _set_statfp(unsigned int sw);
|
|
#endif
|