math.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include <math.h>
  2. /*
  3. * COPYRIGHT: See COPYING in the top level directory
  4. * PROJECT: ReactOS CRT
  5. * FILE: lib/crt/math/cos.c
  6. * PURPOSE: Generic C Implementation of cos
  7. * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
  8. */
  9. #define PRECISION 9
  10. #define M_PI 3.141592653589793238462643
  11. static double cos_off_tbl[] = {0.0, -M_PI/2., 0, -M_PI/2.};
  12. static double cos_sign_tbl[] = {1,-1,-1,1};
  13. static double sin_off_tbl[] = {0.0, -M_PI/2., 0, -M_PI/2.};
  14. static double sin_sign_tbl[] = {1,-1,-1,1};
  15. double sin(double x)
  16. {
  17. int quadrant;
  18. double x2, result;
  19. /* Calculate the quadrant */
  20. quadrant = x * (2./M_PI);
  21. /* Get offset inside quadrant */
  22. x = x - quadrant * (M_PI/2.);
  23. /* Normalize quadrant to [0..3] */
  24. quadrant = (quadrant - 1) & 0x3;
  25. /* Fixup value for the generic function */
  26. x += sin_off_tbl[quadrant];
  27. /* Calculate the negative of the square of x */
  28. x2 = - (x * x);
  29. /* This is an unrolled taylor series using <PRECISION> iterations
  30. * Example with 4 iterations:
  31. * result = 1 - x^2/2! + x^4/4! - x^6/6! + x^8/8!
  32. * To save multiplications and to keep the precision high, it's performed
  33. * like this:
  34. * result = 1 - x^2 * (1/2! - x^2 * (1/4! - x^2 * (1/6! - x^2 * (1/8!))))
  35. */
  36. /* Start with 0, compiler will optimize this away */
  37. result = 0;
  38. #if (PRECISION >= 10)
  39. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20);
  40. result *= x2;
  41. #endif
  42. #if (PRECISION >= 9)
  43. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18);
  44. result *= x2;
  45. #endif
  46. #if (PRECISION >= 8)
  47. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16);
  48. result *= x2;
  49. #endif
  50. #if (PRECISION >= 7)
  51. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14);
  52. result *= x2;
  53. #endif
  54. #if (PRECISION >= 6)
  55. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12);
  56. result *= x2;
  57. #endif
  58. #if (PRECISION >= 5)
  59. result += 1./(1.*2*3*4*5*6*7*8*9*10);
  60. result *= x2;
  61. #endif
  62. result += 1./(1.*2*3*4*5*6*7*8);
  63. result *= x2;
  64. result += 1./(1.*2*3*4*5*6);
  65. result *= x2;
  66. result += 1./(1.*2*3*4);
  67. result *= x2;
  68. result += 1./(1.*2);
  69. result *= x2;
  70. result += 1;
  71. /* Apply correct sign */
  72. result *= sin_sign_tbl[quadrant];
  73. return result;
  74. }
  75. double cos(double x)
  76. {
  77. int quadrant;
  78. double x2, result;
  79. /* Calculate the quadrant */
  80. quadrant = x * (2./M_PI);
  81. /* Get offset inside quadrant */
  82. x = x - quadrant * (M_PI/2.);
  83. /* Normalize quadrant to [0..3] */
  84. quadrant = quadrant & 0x3;
  85. /* Fixup value for the generic function */
  86. x += cos_off_tbl[quadrant];
  87. /* Calculate the negative of the square of x */
  88. x2 = - (x * x);
  89. /* This is an unrolled taylor series using <PRECISION> iterations
  90. * Example with 4 iterations:
  91. * result = 1 - x^2/2! + x^4/4! - x^6/6! + x^8/8!
  92. * To save multiplications and to keep the precision high, it's performed
  93. * like this:
  94. * result = 1 - x^2 * (1/2! - x^2 * (1/4! - x^2 * (1/6! - x^2 * (1/8!))))
  95. */
  96. /* Start with 0, compiler will optimize this away */
  97. result = 0;
  98. #if (PRECISION >= 10)
  99. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20);
  100. result *= x2;
  101. #endif
  102. #if (PRECISION >= 9)
  103. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18);
  104. result *= x2;
  105. #endif
  106. #if (PRECISION >= 8)
  107. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16);
  108. result *= x2;
  109. #endif
  110. #if (PRECISION >= 7)
  111. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14);
  112. result *= x2;
  113. #endif
  114. #if (PRECISION >= 6)
  115. result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12);
  116. result *= x2;
  117. #endif
  118. #if (PRECISION >= 5)
  119. result += 1./(1.*2*3*4*5*6*7*8*9*10);
  120. result *= x2;
  121. #endif
  122. result += 1./(1.*2*3*4*5*6*7*8);
  123. result *= x2;
  124. result += 1./(1.*2*3*4*5*6);
  125. result *= x2;
  126. result += 1./(1.*2*3*4);
  127. result *= x2;
  128. result += 1./(1.*2);
  129. result *= x2;
  130. result += 1;
  131. /* Apply correct sign */
  132. result *= cos_sign_tbl[quadrant];
  133. return result;
  134. }