Source code of Windows XP (NT5)
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.

135 lines
2.7 KiB

  1. /***
  2. *fmod.c - floating point remainder
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 8-24-91 GDP written
  10. * 1-13-92 GDP support IEEE exceptions
  11. * 3-04-92 GDP complete rewrite for improved accuracy
  12. * 3-16-92 GDP restore cw properly, do not raise Inexact exception
  13. * 06-23-92 GDP support NCEG special return values (signed 0's etc)
  14. * 02-06-95 JWM Mac merge
  15. * 10-07-97 RDL Added IA64.
  16. *
  17. *******************************************************************************/
  18. #include <math.h>
  19. #include <trans.h>
  20. #if defined(_M_IA64)
  21. #pragma function(fmod)
  22. #endif
  23. /***
  24. *double fmod(double x, double y)
  25. *
  26. *Purpose:
  27. * Return f, s.t. x = i*y + f, where i is an integer, f has the same
  28. * sign as x, and |f| < |y|
  29. *
  30. *Entry:
  31. *
  32. *Exit:
  33. *
  34. *Exceptions:
  35. * I,P
  36. *******************************************************************************/
  37. #define SCALE 53
  38. double fmod(double x, double y)
  39. {
  40. uintptr_t savedcw;
  41. int neg=0;
  42. int denorm=0;
  43. double d,tx,ty,fx,fy;
  44. int nx, ny, nexp;
  45. /* save user fp control word */
  46. savedcw = _maskfp();
  47. /* check for infinity or NAN */
  48. if (IS_D_SPECIAL(y) || IS_D_SPECIAL(x)){
  49. if (IS_D_SNAN(y) || IS_D_SNAN(x)){
  50. return _except2(FP_I,OP_FMOD,x,y,_d_snan2(x,y),savedcw);
  51. }
  52. if (IS_D_QNAN(y) || IS_D_QNAN(x)){
  53. return _handle_qnan2(OP_FMOD,x,y,savedcw);
  54. }
  55. if (IS_D_INF(x) || IS_D_MINF(x)) {
  56. return _except2(FP_I,OP_FMOD,x,y,QNAN_FMOD,savedcw);
  57. }
  58. RETURN(savedcw, x);
  59. }
  60. if (y == 0) {
  61. return _except2(FP_I,OP_FMOD,x,y,QNAN_FMOD,savedcw);
  62. }
  63. if (x == 0) {
  64. RETURN(savedcw, x); // NCEG spec
  65. }
  66. if (x < 0) {
  67. tx = -x;
  68. neg = 1;
  69. }
  70. else {
  71. tx = x;
  72. }
  73. ty = ABS(y);
  74. while (tx >= ty) {
  75. fx = _decomp(tx, &nx);
  76. fy = _decomp(ty, &ny);
  77. if (nx < MINEXP) {
  78. // tx is a denormalized number
  79. denorm = 1;
  80. nx += SCALE;
  81. ny += SCALE;
  82. tx = _set_exp(fx, nx);
  83. ty = _set_exp(fy, ny);
  84. }
  85. if (fx >= fy) {
  86. nexp = nx ;
  87. }
  88. else {
  89. nexp = nx - 1;
  90. }
  91. d = _set_exp(fy, nexp);
  92. tx -= d;
  93. }
  94. if (denorm) {
  95. //
  96. // raise only FP_U exception
  97. //
  98. return _except2(FP_U,
  99. OP_FMOD,
  100. x,
  101. y,
  102. _add_exp(tx, IEEE_ADJUST-SCALE),
  103. savedcw);
  104. }
  105. if (neg) {
  106. tx = -tx;
  107. }
  108. RETURN(savedcw,tx);
  109. }