fmod.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:4k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* fmod.c - fmod math routine */
  2. /* Copyright 1992-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 03b,01apr02,pfl  clean up fix for SPR 20486 plus 
  7.                  ISO/IEC 9899:1999 conformance
  8. 02a,31oct01,md3  +gkc +ycl rewrite: fixed SPR #20486.
  9. 01f,05feb93,jdi  doc changes based on kdl review.
  10. 01e,02dec92,jdi  doc tweaks.
  11. 01d,28oct92,jdi  documentation cleanup.
  12. 01c,20sep92,smb  documentation additions
  13. 01b,30jul92,kdl  changed _d_type() calls to fpTypeGet().
  14. 01a,08jul92,smb  documentation.
  15. */
  16. /*
  17. DESCRIPTION
  18. SEE ALSO: American National Standard X3.159-1989
  19. NOMANUAL
  20. */
  21. #include "vxWorks.h"
  22. #include "math.h"
  23. #include "stddef.h"
  24. #include "errno.h"
  25. #include "private/mathP.h"
  26. #include "errnoLib.h"
  27. /* mask to extract exponent part of a double */
  28. #define  MASK_DB_EXP  0x7ff00000
  29. /* mask to extract high 20 significant bits */
  30. #define  MASK_DB_HI20  0x000fffff
  31. /* mask to filter exponent part of double */
  32. #define  MASK_DB_MANT  0x800fffff
  33. /* for big endian machine */
  34. #if (_BYTE_ORDER==_BIG_ENDIAN)   
  35. /* high 32 bits of Db - 1-bit sign + 11-bits exponent + 20-bit significant */
  36. #define DB_HI(d) ((unsigned int) *((int*)&d))
  37. /* hi 20 bits of a double's significant */
  38. #define DB_HI_SIG(d) ((unsigned int) *((int*)&d) & MASK_DB_HI20)  
  39. /* lower 32 bits of double's significant */
  40. #define DB_LO_SIG(d) ((unsigned int) *(1+(int*)&d))      
  41. /* for little endian machine */
  42. #else /* (_BYTE_ORDER != _BIG_ENDIAN) */  
  43. /* high 32 bits of Db - 1-bit sign + 11-bits exponent + 20-bit significant */
  44. #define DB_HI(d) ((unsigned int) *(1+(int*)&d))      
  45. /* hi 20 bits of a double's significant */
  46. #define DB_HI_SIG(d) ((unsigned int) *(1+(int*)&d) & MASK_DB_HI20)  
  47. /* lower 32 bits of double's significant */
  48. #define DB_LO_SIG(d) ((unsigned int) *((int*)&d))                           
  49. #endif /* (_BYTE_ORDER==_BIG_ENDIAN) */
  50. /* return (significant of d1) > (significant of d2) */
  51. #define DB_GT_SIG(d1,d2) 
  52.         ((DB_HI_SIG(d1) > DB_HI_SIG(d2)) || 
  53.          ((DB_HI_SIG(d1) == DB_HI_SIG(d2)) && (DB_LO_SIG(d1) > DB_LO_SIG(d2))))
  54. /* NAN value */
  55. #define NAN_VAL(d) {*(int *)(&d) = 0xffffffff; *(1+(int *)&d)=0xffffffff;}
  56. /*******************************************************************************
  57. *
  58. * fmod - compute the remainder of x/y (ANSI)
  59. *
  60. * This routine returns the remainder of <x>/<y> with the sign of <x>,
  61. * in double precision.
  62. * INCLUDE FILES: math.h
  63. *
  64. * RETURNS: The value <x> - <i> * <y>, for some integer <i>.  If <y> is
  65. * non-zero, the result has the same sign as <x> and magnitude less than the
  66. * magnitude of <y>.  If <y> is zero, fmod() returns zero.
  67. *
  68. * ERRNO: EDOM
  69. *
  70. * SEE ALSO: mathALib
  71. */
  72. double fmod
  73.     (
  74.     double x,    /* numerator   */
  75.     double y     /* denominator */
  76.     )
  77.     {
  78.     double       negative = 1.0;                /* used for sign of return   */
  79.     double       yMult2n;                    /* computed next decrement   */
  80.     unsigned int zeroExp_y;             /* factor for next decrement */
  81.     int          errx = fpTypeGet (x, NULL);    /* determine number type */
  82.     int          erry = fpTypeGet (y, NULL);    /* determine number type */
  83.     /* 
  84.      * Per ISO/IEC 9899:1999, ANSI/IEEE 754-1985
  85.      * fmod ( +-0,     y) = +-0 (if y != 0)
  86.      * fmod (   x,     y) = NAN (if x  = INF or y = 0) 
  87.      * fmod (   x, +-INF) = x   (if x != INF)
  88.      */
  89.    
  90.     /* check for boundary conditions returning NAN */
  91.     
  92.     if (errx == NAN || erry == NAN || errx == INF || erry == ZERO)
  93.         {
  94.         errnoSet(EDOM);         /* Domain error is set to maintain backward
  95.    compatibility with ANSI X3.159-1989 */
  96. NAN_VAL(x);
  97.         return (x); /* return NAN */
  98.         }
  99.     /* check for boundary conditions returning X */
  100.     if (errx == ZERO || erry == INF)
  101.         return (x);
  102.     /* make Y absolute */
  103.     if (y < 0.0)
  104.         y = -y;
  105.     /* make X absolute, record sign for return. */
  106.     if (x < 0.0)
  107.         {
  108.         x = -x;
  109.         negative = -1.0;
  110.         }
  111.     /* initial decrementing conditions */
  112.     yMult2n = y;
  113.     zeroExp_y= MASK_DB_MANT & (DB_HI(y));
  114.     /* compute fmod by subtracting estimated decrementations */
  115.     while (x>=y) 
  116.         {
  117.         if (DB_GT_SIG(y,x))
  118.             {
  119.              (DB_HI(yMult2n)) = ( (DB_HI(x)-0x100000) & MASK_DB_EXP ) | zeroExp_y;
  120.              }
  121.          else
  122.              {
  123.              (DB_HI(yMult2n)) = ( DB_HI(x) & MASK_DB_EXP ) | zeroExp_y;
  124.              }
  125.          x-= yMult2n ;
  126.          }
  127.     return (negative*x);
  128.     }