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.

98 lines
2.0 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. ldexp.c
  5. Abstract:
  6. multiply by a power of two
  7. Author:
  8. Revision History:
  9. 29-sept-1999 ATM Shafiqul Khalid [askhalid] copied from rtl library.
  10. --*/
  11. #include <math.h>
  12. #include <float.h>
  13. #include <trans.h>
  14. #include <limits.h>
  15. /***
  16. *double ldexp(double x, int exp)
  17. *
  18. *Purpose:
  19. * Compute x * 2^exp
  20. *
  21. *Entry:
  22. *
  23. *Exit:
  24. *
  25. *Exceptions:
  26. * I U O P
  27. *
  28. *******************************************************************************/
  29. double ldexp(double x, int exp)
  30. {
  31. unsigned int savedcw;
  32. int oldexp;
  33. long newexp; /* for checking out of bounds exponents */
  34. double result, mant;
  35. /* save user fp control word */
  36. savedcw = _maskfp();
  37. /* check for infinity or NAN */
  38. if (IS_D_SPECIAL(x)){
  39. switch (_sptype(x)) {
  40. case T_PINF:
  41. case T_NINF:
  42. RETURN(savedcw,x);
  43. case T_QNAN:
  44. return _handle_qnan2(OP_LDEXP, x, (double)exp, savedcw);
  45. default: //T_SNAN
  46. return _except2(FP_I,OP_LDEXP,x,(double)exp,_s2qnan(x),savedcw);
  47. }
  48. }
  49. if (x == 0.0) {
  50. RETURN(savedcw,x);
  51. }
  52. mant = _decomp(x, &oldexp);
  53. if (ABS(exp) > INT_MAX)
  54. newexp = exp; // avoid possible integer overflow
  55. else
  56. newexp = oldexp + exp;
  57. /* out of bounds cases */
  58. if (newexp > MAXEXP + IEEE_ADJUST) {
  59. return _except2(FP_O|FP_P,OP_LDEXP,x,(double)exp,_copysign(D_INF,mant),savedcw);
  60. }
  61. if (newexp > MAXEXP) {
  62. result = _set_exp(mant, newexp-IEEE_ADJUST);
  63. return _except2(FP_O|FP_P,OP_LDEXP,x,(double)exp,result,savedcw);
  64. }
  65. if (newexp < MINEXP - IEEE_ADJUST) {
  66. return _except2(FP_U|FP_P,OP_LDEXP,x,(double)exp,mant*0.0,savedcw);
  67. }
  68. if (newexp < MINEXP) {
  69. result = _set_exp(mant, newexp+IEEE_ADJUST);
  70. return _except2(FP_U|FP_P,OP_LDEXP,x,(double)exp,result,savedcw);
  71. }
  72. result = _set_exp(mant, (int)newexp);
  73. RETURN(savedcw,result);
  74. }