home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March B / SCO_CASTOR4RRT.iso / uccs / root.13 / usr / include / ieeefp.h < prev    next >
C/C++ Source or Header  |  1998-08-19  |  17KB  |  468 lines

  1. /*
  2.  * Copyright (c) 1998 The Santa Cruz Operation, Inc.. All Rights Reserved. 
  3.  *                                                                         
  4.  *        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF THE               
  5.  *                   SANTA CRUZ OPERATION INC.                             
  6.  *                                                                         
  7.  *   The copyright notice above does not evidence any actual or intended   
  8.  *   publication of such source code.                                      
  9.  */
  10.  
  11. #ifndef _IEEEFP_H
  12. #define _IEEEFP_H
  13.  
  14. #ident    "@(#)sgs-head:i386/head/ieeefp.h    1.23"
  15.  
  16. #ifdef __cplusplus
  17. extern "C" {
  18. #endif
  19.  
  20. /*
  21.  * Floating point enviornment for machines that support
  22.  * the IEEE 754 floating-point standard.  This file currently 
  23.  * supports the 3B2 and 80*87 families.
  24.  *
  25.  * This header defines the following interfaces:
  26.  *    1) Classes of floating point numbers
  27.  *    2) Rounding Control
  28.  *    3) Exception Control
  29.  *    4) Exception Handling
  30.  *    5) Utility Macros
  31.  *    6) Full Exception Environment Control
  32.  */
  33. #if defined(__STDC__)
  34. #define __i386 #machine(i386)
  35. #else
  36. #define __i386 i386
  37. #endif
  38.  
  39. /* CLASSES of floating point numbers *************************
  40.  * IEEE floating point values fall into 1 of the following 10
  41.  * classes
  42.  */
  43. typedef    enum    fpclass_t {
  44.     FP_SNAN = 0,    /* signaling NaN */
  45.     FP_QNAN = 1,    /* quiet NaN */
  46.     FP_NINF = 2,    /* negative infinity */
  47.     FP_PINF = 3,    /* positive infinity */
  48.     FP_NDENORM = 4, /* negative denormalized non-zero */
  49.     FP_PDENORM = 5, /* positive denormalized non-zero */
  50.     FP_NZERO = 6,    /* -0.0 */
  51.     FP_PZERO = 7,   /* +0.0 */
  52.     FP_NNORM = 8,    /* negative normalized non-zero */
  53.     FP_PNORM = 9    /* positive normalized non-zero */
  54.     } fpclass_t;
  55.  
  56. #if defined(__STDC__)
  57. extern fpclass_t fpclass(double);    /* get class of double value */
  58. extern int    finite( double );
  59. extern int    unordered( double, double );
  60. #if __i386
  61. extern fpclass_t fpclassl(long double);    /* get class of long double value */
  62. extern int    finitel( long double );
  63. extern int    unorderedl( long double, long double );
  64. #endif
  65. #else
  66. extern fpclass_t fpclass();    /* get class of double value */
  67. #if __i386
  68. extern fpclass_t fpclassl();    /* get class of long double value */
  69. #endif
  70. #endif
  71.  
  72. /* ROUNDING CONTROL ******************************************
  73.  *
  74.  * At all times, floating-point math is done using one of four
  75.  * mutually-exclusive rounding modes.
  76.  */
  77.  
  78. #if __i386
  79.  
  80. /*
  81.  * NOTE: the values given are chosen to match those used by the
  82.  * 80*87 rounding mode field in the control word.
  83.  */
  84. typedef    enum    fp_rnd {
  85.     FP_RN = 0,    /* round to nearest representable number, tie -> even */
  86.     FP_RM = 1,  /* round toward minus infinity                        */
  87.     FP_RP = 2,  /* round toward plus infinity                         */
  88.     FP_RZ = 3    /* round toward zero (truncate)                  */
  89.     } fp_rnd;
  90.  
  91. #else  /* 3B */
  92.  
  93. /* NOTE: the values given are chosen to match
  94.  * the values needed by the FPA and MAU rounding-control fields.
  95.  */
  96. typedef    enum    fp_rnd {
  97.     FP_RN = 0,    /* round to nearest representable number, tie -> even */
  98.     FP_RP = 1,    /* round toward plus infinity                  */
  99.     FP_RM = 2,    /* round toward minus infinity                  */
  100.     FP_RZ = 3    /* round toward zero (truncate)                  */
  101.     } fp_rnd;
  102.  
  103. #endif
  104.  
  105. #if defined(__STDC__)
  106. extern fp_rnd   fpsetround(fp_rnd);     /* set rounding mode, return previous */
  107. extern fp_rnd   fpgetround(void);       /* return current rounding mode       */
  108.  
  109. #else
  110. extern fp_rnd    fpsetround();    /* set rounding mode, return previous */
  111. extern fp_rnd    fpgetround();    /* return current rounding mode       */
  112.  
  113. #endif
  114.  
  115. /* EXCEPTION CONTROL *****************************************
  116.  *
  117.  */
  118.  
  119. #define    fp_except    int
  120.  
  121. #define    FP_DISABLE    0    /* exception will be ignored    */
  122. #define    FP_ENABLE    1    /* exception will cause SIGFPE    */
  123. #define    FP_CLEAR    0    /* exception has not occurred    */
  124. #define    FP_SET        1    /* exception has occurred    */
  125.  
  126. #if __i386
  127.  
  128. /*
  129.  * There are six floating point exceptions, which can be individually
  130.  * ENABLED (== 1) or DISABLED (== 0).  When an exception occurs
  131.  * (ENABLED or not), the fact is noted by changing an associated
  132.  * "sticky bit" from CLEAR (==0) to SET (==1).
  133.  *
  134.  * NOTE: the bit positions in fp_except are chosen to match those of
  135.  * the 80*87 control word mask bits.  Although the 87 chips actually
  136.  * ENABLE exceptions with a mask value of 0 (not 1, as on the 3b), it
  137.  * is felt that switching these values may create more problems than
  138.  * it solves.
  139.  */
  140.  
  141. /* an fp_except can have the following (not exclusive) values:  */
  142. #define FP_X_INV        0x01    /* invalid operation exception  */
  143. #define FP_X_DNML       0x02    /* denormalization exception    */
  144. #define FP_X_DZ         0x04    /* divide-by-zero exception     */
  145. #define    FP_X_OFL    0x08    /* overflow exception        */
  146. #define FP_X_UFL        0x10    /* underflow exception          */
  147. #define FP_X_IMP        0x20    /* imprecise (loss of precision)*/
  148.  
  149. #else /* 3B */
  150.  
  151. /*
  152.  * There are five floating-point exceptions, which can be individually
  153.  * ENABLED (== 1) or DISABLED (== 0).  When an exception occurs
  154.  * (ENABLED or not), the fact is noted by changing an associated
  155.  * "sticky bit" from CLEAR (==0) to SET (==1).
  156.  *
  157.  * NOTE: the bit positions in an fp_except are chosen to match that in
  158.  * the MAU and the FPA hardware mask bits.
  159.  */
  160.  
  161. /* an fp_except can have the following (not exclusive) values:  */
  162. #define    FP_X_INV    0x10    /* invalid operation exception    */
  163. #define    FP_X_OFL    0x08    /* overflow exception        */
  164. #define    FP_X_UFL    0x04    /* underflow exception        */
  165. #define    FP_X_DZ        0x02    /* divide-by-zero exception    */
  166. #define    FP_X_IMP    0x01    /* imprecise (loss of precision)*/
  167.  
  168. #endif
  169.  
  170. #if defined(__STDC__)
  171. extern fp_except fpgetmask(void);               /* current exception mask       */
  172. extern fp_except fpsetmask(fp_except);          /* set mask, return previous    */
  173. extern fp_except fpgetsticky(void);             /* return logged exceptions     */
  174. extern fp_except fpsetsticky(fp_except);        /* change logged exceptions     */
  175.  
  176. #else
  177. extern fp_except fpgetmask();    /* current exception mask       */
  178. extern fp_except fpsetmask();    /* set mask, return previous    */
  179. extern fp_except fpgetsticky();    /* return logged exceptions     */
  180. extern fp_except fpsetsticky();    /* change logged exceptions     */
  181.  
  182. #endif 
  183.  
  184. /* UTILITY MACROS ********************************************
  185.  */
  186.  
  187. #if defined(__STDC__)
  188. extern int isnanf(float);               
  189. extern int isnand(double);
  190. #if __i386
  191. extern int isnanl(long double);               
  192. #endif
  193.  
  194. #else
  195. extern int isnand();
  196. #define isnanf(x)    (((*(long *)&(x) & 0x7f800000L)==0x7f800000L)&& \
  197.              ((*(long *)&(x) & 0x007fffffL)!=0x00000000L) )
  198. #if __i386
  199. extern int isnanl();
  200. #endif
  201. #endif
  202.  
  203. #if __i386
  204.  
  205. #ifndef SS
  206. #include <sys/reg.h>
  207. #endif
  208. /* EXCEPTION HANDLING ****************************************
  209.  *
  210.  * When a signal handler catches an FPE, it will have a freshly initialized
  211.  * coprocessor.  This allows signal handling routines to make use of
  212.  * floating point arithmetic, if need be.  The previous state of the 87
  213.  * chip is available, however.  There are two ways to get at this information,
  214.  * depending on how the signal handler was set up.
  215.  *
  216.  * If the handler was set via signal() or sigset(), the old, SVR3, method
  217.  * should be used: the signal handler assumes that it has a single parameter,
  218.  * which is of type struct _fpstackframe, defined below.  By investigating
  219.  * this parameter, the cause of the FPE may be determined.  By modifying it,
  220.  * the state of the coprocessor can be changed upon return to the main task.
  221.  * THIS METHOD IS OBSOLETE, AND MAY NOT BE SUPPORTED IN FUTURE RELEASES.
  222.  *
  223.  * If the handler was set via sigaction(), the new, SVR4, method should be
  224.  * used: the third argument to the handler will be a pointer to a ucontext
  225.  * structure (see sys/ucontext.h).  The uc_mcontext.fpregs member of the
  226.  * ucontext structure holds the saved floating-point registers.  This can be
  227.  * examined and/or modified.  By modifying it, the state of the coprocessor
  228.  * can be changed upon return to the main task.
  229.  */
  230.  
  231. struct _fpstackframe {  /* signal handler's argument                    */
  232.     long signo;             /* signal number arg                    */
  233.     long regs[SS+1];        /* all registers                        */
  234.     struct _fpstate *fpsp;  /* address of saved 387 state           */
  235.     char *wsp;              /* address of saved Weitek state        */
  236. };
  237.  
  238. struct _fpreg {         /* structure of a temp real fp register         */
  239.     unsigned short significand[4];  /* 64 bit mantissa value        */
  240.     unsigned short exponent;        /* 15 bit exponent and sign bit */
  241. };
  242.  
  243. struct _fpstate {       /* saved state info from an exception           */
  244.     unsigned long cw,       /* cotrol word                          */
  245.               sw,       /* status word after fnclex-not useful  */
  246.               tag,      /* tag word                             */
  247.               ipoff,    /* %eip register                        */
  248.               cssel,    /* code segment selector                */
  249.               dataoff,  /* data operand address                 */
  250.               datasel;  /* data operand selector                */
  251.     struct _fpreg _st[8];   /* saved register stack                 */
  252.     unsigned long status;   /* status word saved at exception       */
  253. };
  254.  
  255. /* The structure of the 80*87 status and control words are given by the
  256.  * following structs.
  257.  */
  258. struct _cw87 {
  259.     unsigned    mask:   6,  /* exception masks                      */
  260.             res1:   2,  /* not used                             */
  261.             prec:   2,  /* precision control field              */
  262.             rnd:    2,  /* rounding control field               */
  263.             inf:    1,  /* infinity control (not on 387)        */
  264.             res2:   3;  /* not used                             */
  265. };
  266.  
  267. struct _sw87 {
  268.     unsigned    excp:   6,  /* exception sticky bits                */
  269.             res1:   1,  /* not used                             */
  270.             errs:   1,  /* error summary-set if unmasked excep  */
  271.             c012:   3,  /* condition code bits 0..2             */
  272.             stkt:   3,  /* stack top pointer                    */
  273.             c3:     1,  /* condition code bit 3                 */
  274.             busy:   1;  /* coprocessor busy                     */
  275. };
  276.  
  277. #else /* 3B */
  278.  
  279. /* EXCEPTION HANDLING ****************************************
  280.  * When a floating-point exception handler is entered, the variables
  281.  * _fpftype -- floating-point fault type, and
  282.  * _fpfault -- pointer to floating-point exception structure
  283.  * will be established. _fpftype identifies the primary exception
  284.  * (if both underflow and inexact are generated, _fpftype is underflow)
  285.  * and _fpfault points to all the other information needed.
  286.  * Two integer faults also use this mechanism: "integer overflow" and
  287.  * "integer divide by zero". If either of these faults is indicated,
  288.  * or if _fpftype == UNKNOWN, _fpfault will be NULL.
  289.  */
  290.  
  291. #undef UNKNOWN
  292.  
  293. typedef    enum    fp_ftype {
  294.     UNKNOWN    = 0,    /* library code could not determine type      */
  295.     INT_DIVZ    = 1,    /* integer divide by zero              */
  296.     INT_OVFLW    = 2,    /* integer overflow, including float->int conv*/
  297.     FP_OVFLW    = 3,    /* floating-point overflow              */
  298.     FP_UFLW    = 4,    /* floating-point underflow              */
  299.     FP_INXACT    = 5,    /* floating-point loss of precision          */
  300.     FP_DIVZ    = 6,    /* floating-point divide by zero          */
  301.     FP_INVLD    = 7,    /* floating-point invalid operation          */
  302.     FP_IN_OVFLW = 8,    /* inexact AND overflow                       */
  303.     FP_IN_UFLW  = 9    /* inexact AND underflow                      */
  304.     } fp_ftype;
  305.  
  306. extern fp_ftype _fpftype;
  307.  
  308. /* reporting a floating-point exception requires a discriminated union
  309.  * of all relevant data-types. The following defines the discriminant.
  310.  * The particular values are arbitrary.
  311.  */
  312. typedef    enum    fp_type {
  313.     FP_NULL    = 0,    /* uninitialized data                  */
  314.     FP_C    = 1,    /* result of comparison, returned from trap   */
  315.     FP_L    = 2,    /* long int data, being converted to/from flt.*/
  316.     FP_F    = 3,    /* single-precision floating-point          */
  317.     FP_D    = 4,    /* double-precision floating-point          */
  318.     FP_X    = 5,    /* double-extended-precision floating-point   */
  319.     FP_P    = 6,    /* packed-decimal floating-point          */
  320.     FP_U    = 7,    /* unsigned int data, being converted           */
  321.     FP_S    = 8,    /* short int data                  */
  322.     FP_DEC    = 9    /* decimal ascii data being converted          */
  323.     }    fp_type;
  324.  
  325. /* floating-point data types                    */
  326. typedef struct extended { /* double-extended floating point    */
  327.     unsigned long    w[3];
  328.     } extended;
  329.  
  330. typedef struct packdec { /* packed-decimal floating point    */
  331.     unsigned long    w[3];
  332.     } packdec;
  333.  
  334. typedef struct decimal { /* ascii-decimal floating point    */
  335.     char *    i;        /* significand ascii digit string    */
  336.     char *    e;        /* exponent ascii digit string        */
  337.     char    sign;        /* sign of number            */
  338.                 /*     0    +            */
  339.                 /*     1    -            */
  340.     char    esign;        /* sign of exponent            */
  341.                 /*     0    +            */
  342.                 /*     1    -            */
  343.                 /*    2    NaN            */
  344.                 /*    3    infinity        */
  345.     int        ilen;        /* # digits in significand        */
  346.     int        elen;        /* # digits in exponent            */
  347.     } decimal;
  348.  
  349. typedef    enum    fp_cmp { /* result of comparison        */
  350.     FP_LT    = -1,    /* less than    */
  351.     FP_EQ    =  0,    /* equal    */
  352.     FP_GT    =  1,    /* greater than    */
  353.     FP_UO    =  2    /* unordered    */
  354.     } fp_cmp;
  355.  
  356. typedef union fp_union { /* union of all types            */
  357.     fp_cmp    c;
  358.     long    l;
  359.     unsigned    u;
  360.     float    f;
  361.     double    d;
  362.     extended    x;    /* not used on 3B20  */
  363.     packdec    p;    /* not used on 3B20  */
  364.     short    s;      /* only used on 3B20 */
  365.     decimal    *dec;
  366.     } fp_union;
  367.  
  368. typedef struct fp_dunion { /* discriminated union        */
  369.     fp_type    type;
  370.     fp_union    value;
  371.     } fp_dunion;
  372.  
  373. /* the rest of the information pointed to by _fp_fault includes:
  374.  *    the type of operation being performed,
  375.  *    the types and values of the operands,
  376.  *    the type of a trapped value (if any), and
  377.  *    the desired type of the result.
  378.  * the following defines and struct give the information layout.
  379.  */
  380.  
  381. typedef    enum    fp_op {    /* floating-point operations              */
  382.     FP_ADD  = 0,    /* floating-point addition              */
  383.     FP_SUB  = 1,    /* floating-point subtraction              */
  384.     FP_MULT = 2,    /* floating-point multiplication          */
  385.     FP_DIV  = 3,    /* floating-point division              */
  386.     FP_SQRT = 4,    /* floating-point square root              */
  387.     FP_REM  = 5,    /* floating-point remainder              */
  388.     FP_CONV = 6,    /* data movement, including changing format   */
  389.     FP_RNDI = 7,    /* round to integer (keep in floating format) */
  390.     FP_CMPT = 8,    /* trapping floating-point compare          */
  391.     FP_CMP  = 9,    /* non-trapping floating-point compare          */
  392.     FP_NEG  = 10,    /* (MAU) negate operation              */
  393.     FP_ABS  = 11,    /* (MAU) absolute value operation          */
  394.     FP_SIN  = 12,    /* floating-point sine                  */
  395.     FP_COS  = 13,    /* floating-point cosine              */
  396.     FP_ATN  = 14    /* floating-point arc tangent              */
  397.     }    fp_op;
  398.  
  399. struct fp_fault {
  400.     fp_op    operation;
  401.     fp_dunion    operand[2];
  402.     fp_dunion    t_value;
  403.     fp_dunion    result;
  404.     };
  405.  
  406. extern struct fp_fault    * _fpfault;
  407.  
  408.  
  409. /* FULL EXCEPTION ENVIRONMENT CONTROL ************************
  410.  *
  411.  * The complete exception environment defined above requires
  412.  * a significant amount of code to be picked up from the libraries.
  413.  * The "glue" routines _getfltsw() and _getflthw() are provided
  414.  * in two versions, one with full capability and one without.
  415.  * The version without full capability has the following behavior:
  416.  *    floating-point faults will raise SIGFPE, but
  417.  *    the user handler will have _fpftype == UNKNOWN, and
  418.  *    _fpfault == NULL. If SIGFPE is set to SIG_DFL, a core dump
  419.  *    will be produced.
  420.  * If ANY module in the final a.out #includes ieeefp.h (except as noted
  421.  * below), the code below will force in the FULL environment,
  422.  * 
  423.  * NOTES: 1) code in the library (e.g. for setround(), etc.) which
  424.  *    needs the definitions above, but does not care which fault
  425.  *    environment is picked up SHOULD #define P754_NOFAULT
  426.  *    before #including ieeefp.h.
  427.  *    2) If a user program does not wish to do any fault recovery,
  428.  *    just produce a core dump, it MAY also #define P754_NOFAULT,
  429.  *    and may gain a code size reduction. However, if it uses a
  430.  *    routine    in the math library that does request the full fault
  431.  *    environment then the full environment WILL be included.
  432.  */
  433. #ifndef P754_NOFAULT
  434. #define    P754_NOFAULT    1
  435.  
  436. #if defined(__STDC__)
  437. extern void    _getflthw(int *, int (*)());
  438. extern fp_union    _getfltsw(fp_ftype,fp_op,char *,fp_union *,fp_union *,fp_union *);
  439. static void    (* _p754_1)(int *, int (*)()) = _getflthw;
  440. static fp_union    (* _p754_2)(fp_ftype,fp_op,char *,fp_union *,fp_union *,fp_union *) =    _getfltsw;
  441.  
  442. extern void _s2dec(const float *, decimal *, int);
  443. extern void _d2dec(const double *, decimal *, int);
  444. extern void _dec2s(decimal *, float *, int);
  445. extern void _dec2d(decimal *, double *, int);
  446.  
  447. #else
  448. extern void    _getflthw();
  449. extern fp_union    _getfltsw();
  450. static void    (* _p754_1)() = _getflthw;
  451. static fp_union    (* _p754_2)() =    _getfltsw;
  452.  
  453. extern void _s2dec();
  454. extern void _d2dec();
  455. extern void _dec2s();
  456. extern void _dec2d();
  457. #endif
  458.  
  459. #endif  /* ndef P&%$_NOFAULT 1 */
  460.  
  461. #endif  /* __i386 */
  462.  
  463. #ifdef __cplusplus
  464. }
  465. #endif
  466.  
  467. #endif  /* _IEEEFP_H */
  468.