pow.c 950 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #include <lib9.h>
  2. double
  3. pow(double x, double y) /* return x ^ y (exponentiation) */
  4. {
  5. double xy, y1, ye;
  6. long i;
  7. int ex, ey, flip;
  8. if(y == 0.0)
  9. return 1.0;
  10. flip = 0;
  11. if(y < 0.){
  12. y = -y;
  13. flip = 1;
  14. }
  15. y1 = modf(y, &ye);
  16. if(y1 != 0.0){
  17. if(x <= 0.)
  18. goto zreturn;
  19. if(y1 > 0.5) {
  20. y1 -= 1.;
  21. ye += 1.;
  22. }
  23. xy = exp(y1 * log(x));
  24. }else
  25. xy = 1.0;
  26. if(ye > 0x7FFFFFFF){ /* should be ~0UL but compiler can't convert double to ulong */
  27. if(x <= 0.){
  28. zreturn:
  29. if(x==0. && !flip)
  30. return 0.;
  31. return NaN();
  32. }
  33. if(flip){
  34. if(y == .5)
  35. return 1./sqrt(x);
  36. y = -y;
  37. }else if(y == .5)
  38. return sqrt(x);
  39. return exp(y * log(x));
  40. }
  41. x = frexp(x, &ex);
  42. ey = 0;
  43. i = ye;
  44. if(i)
  45. for(;;){
  46. if(i & 1){
  47. xy *= x;
  48. ey += ex;
  49. }
  50. i >>= 1;
  51. if(i == 0)
  52. break;
  53. x *= x;
  54. ex <<= 1;
  55. if(x < .5){
  56. x += x;
  57. ex -= 1;
  58. }
  59. }
  60. if(flip){
  61. xy = 1. / xy;
  62. ey = -ey;
  63. }
  64. return ldexp(xy, ey);
  65. }