Leaked source code of windows server 2003
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.

131 lines
3.2 KiB

  1. /***
  2. *log.c - logarithmic functions
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Compute log(x) and log10(x)
  8. *
  9. *Revision History:
  10. * 8-15-91 GDP written
  11. * 12-20-91 GDP support IEEE exceptions
  12. * 10-07-97 RDL Added IA64.
  13. *
  14. *******************************************************************************/
  15. #include <math.h>
  16. #include <trans.h>
  17. #if defined(_M_IA64)
  18. #pragma function(log, log10)
  19. #endif
  20. static double _log_hlp( double x, int flag);
  21. /* constants */
  22. static double const c0 = 0.70710678118654752440; /* sqrt(0.5) */
  23. static double const c1 = 0.69335937500000000000;
  24. static double const c2 = -2.121944400546905827679e-4;
  25. static double const c3 = 0.43429448190325182765;
  26. /* coefficients for rational approximation */
  27. static double const a0 = -0.64124943423745581147e2 ;
  28. static double const a1 = 0.16383943563021534222e2 ;
  29. static double const a2 = -0.78956112887491257267e0 ;
  30. static double const b0 = -0.76949932108494879777e3 ;
  31. static double const b1 = 0.31203222091924532844e3 ;
  32. static double const b2 = -0.35667977739034646171e2 ;
  33. /* b3=1.0 is not used -avoid multiplication by 1.0 */
  34. #define A(w) (((w) * a2 + a1) * (w) + a0)
  35. #define B(w) ((((w) + b2) * (w) + b1) * (w) + b0)
  36. /***
  37. *double log(double x) - natural logarithm
  38. *double log10(double x) - base-10 logarithm
  39. *
  40. *Purpose:
  41. * Compute the natural and base-10 logarithm of a number.
  42. * The algorithm (reduction / rational approximation) is
  43. * taken from Cody & Waite.
  44. *
  45. *Entry:
  46. *
  47. *Exit:
  48. *
  49. *Exceptions:
  50. * I P Z
  51. *******************************************************************************/
  52. double log10(double x)
  53. {
  54. return(_log_hlp(x,OP_LOG10));
  55. }
  56. double log(double x)
  57. {
  58. return(_log_hlp(x,OP_LOG));
  59. }
  60. static double _log_hlp(double x, int opcode)
  61. {
  62. uintptr_t savedcw;
  63. int n;
  64. double f,result;
  65. double z,w,znum,zden;
  66. double rz,rzsq;
  67. /* save user fp control word */
  68. savedcw = _maskfp();
  69. /* check for infinity or NAN */
  70. if (IS_D_SPECIAL(x)){
  71. switch (_sptype(x)) {
  72. case T_PINF:
  73. RETURN(savedcw, x);
  74. case T_QNAN:
  75. return _handle_qnan1(opcode, x, savedcw);
  76. case T_SNAN:
  77. return _except1(FP_I, opcode, x, _s2qnan(x), savedcw);
  78. }
  79. /* NINF will be handled in the x<0 case */
  80. }
  81. if (x <= 0.0) {
  82. double qnan;
  83. if (x == 0.0) {
  84. return _except1(FP_Z,opcode,x,-D_INF,savedcw);
  85. }
  86. qnan = (opcode == OP_LOG ? QNAN_LOG : QNAN_LOG10);
  87. return _except1(FP_I,opcode,x,qnan,savedcw);
  88. }
  89. if (x == 1.0) {
  90. // no precision ecxeption
  91. RETURN(savedcw, 0.0);
  92. }
  93. f = _decomp(x, &n);
  94. if (f > c0) {
  95. znum = (f - 0.5) - 0.5;
  96. zden = f * 0.5 + 0.5;
  97. }
  98. else {
  99. n--;
  100. znum = f - 0.5;
  101. zden = znum * 0.5 + 0.5;
  102. }
  103. z = znum / zden;
  104. w = z * z;
  105. rzsq = w * A(w)/B(w) ;
  106. rz = z + z*rzsq;
  107. result = (n * c2 + rz) + n * c1;
  108. if (opcode == OP_LOG10) {
  109. result *= c3;
  110. }
  111. RETURN_INEXACT1(opcode,x,result,savedcw);
  112. }