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.

123 lines
3.1 KiB

  1. /***
  2. *hypot.c - hypotenuse and complex absolute value
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 08-15-91 GDP written
  10. * 10-20-91 GDP removed inline assembly for calling sqrt
  11. *
  12. *******************************************************************************/
  13. #include <math.h>
  14. #include <trans.h>
  15. static double _hypothlp(double x, double y, int who);
  16. /*
  17. * Function name: hypot
  18. *
  19. * Arguments: x, y - double
  20. *
  21. * Description: hypot returns sqrt(x*x + y*y), taking precautions against
  22. * unwarrented over and underflows.
  23. *
  24. * Side Effects: no global data is used or affected.
  25. *
  26. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  27. *
  28. * History:
  29. * 03/13/89 WAJ Minor changes to source.
  30. * 04/13/89 WAJ Now uses _cdecl for _CDECL
  31. * 06/07/91 JCR ANSI naming (_hypot)
  32. * 08/26/91 GDP NaN support, error handling
  33. * 01/13/91 GDP IEEE exceptions support
  34. */
  35. double _hypot(double x, double y)
  36. {
  37. return _hypothlp(x,y,OP_HYPOT);
  38. }
  39. /***
  40. *double _cabs(struct _complex z) - absolute value of a complex number
  41. *
  42. *Purpose:
  43. *
  44. *Entry:
  45. *
  46. *Exit:
  47. *
  48. *Exceptions:
  49. *******************************************************************************/
  50. double _cabs(struct _complex z)
  51. {
  52. return( _hypothlp(z.x, z.y, OP_CABS ) );
  53. }
  54. static double _hypothlp(double x, double y, int who)
  55. {
  56. double max;
  57. double result, sum;
  58. uintptr_t savedcw;
  59. int exp1, exp2, newexp;
  60. /* save user fp control word */
  61. savedcw = _maskfp();
  62. /* check for infinity or NAN */
  63. if (IS_D_SPECIAL(x) || IS_D_SPECIAL(y)){
  64. if (IS_D_SNAN(x) || IS_D_SNAN(y)){
  65. return _except2(FP_I,who,x,y,_d_snan2(x,y),savedcw);
  66. }
  67. if (IS_D_QNAN(x) || IS_D_QNAN(y)){
  68. return _handle_qnan2(who,x,y,savedcw);
  69. }
  70. /* there is at least one infinite argument ... */
  71. RETURN(savedcw,D_INF);
  72. }
  73. /* take the absolute values of x and y, compute the max, and then scale by
  74. max to prevent over or underflowing */
  75. if ( x < 0.0 )
  76. x = - x;
  77. if ( y < 0.0 )
  78. y = - y;
  79. max = ( ( y > x ) ? y : x );
  80. if ( max == 0.0 )
  81. RETURN(savedcw, 0.0 );
  82. x /= max; //this may pollute the fp status word (underflow flag)
  83. y /= max;
  84. sum = x*x + y*y;
  85. result = _decomp(sqrt(sum),&exp1) * _decomp(max,&exp2);
  86. newexp = exp1 + exp2 + _get_exp(result);
  87. // in case of overflow or underflow
  88. // adjusting exp by IEEE_ADJUST will certainly
  89. // bring the result in the representable range
  90. if (newexp > MAXEXP) {
  91. result = _set_exp(result, newexp - IEEE_ADJUST);
  92. return _except2(FP_O | FP_P, who, x, y, result, savedcw);
  93. }
  94. if (newexp < MINEXP) {
  95. result = _set_exp(result, newexp + IEEE_ADJUST);
  96. return _except2(FP_U | FP_P, who, x, y, result, savedcw);
  97. }
  98. result = _set_exp(result, newexp);
  99. // fix needed: P exception is raised even if the result is exact
  100. RETURN_INEXACT2(who, x, y, result, savedcw);
  101. }