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.

90 lines
2.2 KiB

  1. /***
  2. *ldexp.c - multiply by a power of two
  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 rewritten to support IEEE exceptions
  11. * 5-05-92 GDP bug fix for x denormal
  12. * 07-16-93 SRW ALPHA Merge
  13. * 11-18-93 GJF Merged in NT SDK verion.
  14. *
  15. *******************************************************************************/
  16. #include <math.h>
  17. #include <float.h>
  18. #include <trans.h>
  19. #include <limits.h>
  20. /***
  21. *double ldexp(double x, int exp)
  22. *
  23. *Purpose:
  24. * Compute x * 2^exp
  25. *
  26. *Entry:
  27. *
  28. *Exit:
  29. *
  30. *Exceptions:
  31. * I U O P
  32. *
  33. *******************************************************************************/
  34. double ldexp(double x, int exp)
  35. {
  36. uintptr_t savedcw;
  37. int oldexp;
  38. long newexp; /* for checking out of bounds exponents */
  39. double result, mant;
  40. /* save user fp control word */
  41. savedcw = _maskfp();
  42. /* check for infinity or NAN */
  43. if (IS_D_SPECIAL(x)){
  44. switch (_sptype(x)) {
  45. case T_PINF:
  46. case T_NINF:
  47. RETURN(savedcw,x);
  48. case T_QNAN:
  49. return _handle_qnan2(OP_LDEXP, x, (double)exp, savedcw);
  50. default: //T_SNAN
  51. return _except2(FP_I,OP_LDEXP,x,(double)exp,_s2qnan(x),savedcw);
  52. }
  53. }
  54. if (x == 0.0) {
  55. RETURN(savedcw,x);
  56. }
  57. mant = _decomp(x, &oldexp);
  58. if (ABS(exp) > INT_MAX)
  59. newexp = exp; // avoid possible integer overflow
  60. else
  61. newexp = oldexp + exp;
  62. /* out of bounds cases */
  63. if (newexp > MAXEXP + IEEE_ADJUST) {
  64. return _except2(FP_O|FP_P,OP_LDEXP,x,(double)exp,_copysign(D_INF,mant),savedcw);
  65. }
  66. if (newexp > MAXEXP) {
  67. result = _set_exp(mant, newexp-IEEE_ADJUST);
  68. return _except2(FP_O|FP_P,OP_LDEXP,x,(double)exp,result,savedcw);
  69. }
  70. if (newexp < MINEXP - IEEE_ADJUST) {
  71. return _except2(FP_U|FP_P,OP_LDEXP,x,(double)exp,mant*0.0,savedcw);
  72. }
  73. if (newexp < MINEXP) {
  74. result = _set_exp(mant, newexp+IEEE_ADJUST);
  75. return _except2(FP_U|FP_P,OP_LDEXP,x,(double)exp,result,savedcw);
  76. }
  77. result = _set_exp(mant, (int)newexp);
  78. RETURN(savedcw,result);
  79. }