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