unity.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* unity.c
  2. *
  3. * Relative error approximations for function arguments near
  4. * unity.
  5. *
  6. * log1p(x) = log(1+x)
  7. * expm1(x) = exp(x) - 1
  8. * cosm1(x) = cos(x) - 1
  9. *
  10. */
  11. #include "mconf.h"
  12. #ifdef ANSIPROT
  13. extern int isnan(double);
  14. extern int isfinite(double);
  15. extern double log(double);
  16. extern double polevl(double, void *, int);
  17. extern double p1evl(double, void *, int);
  18. extern double exp(double);
  19. extern double cos(double);
  20. #else
  21. double log(), polevl(), p1evl(), exp(), cos();
  22. int isnan(), isfinite();
  23. #endif
  24. extern double INFINITY;
  25. /* log1p(x) = log(1 + x) */
  26. /* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
  27. * 1/sqrt(2) <= x < sqrt(2)
  28. * Theoretical peak relative error = 2.32e-20
  29. */
  30. static double LP[] = {
  31. 4.5270000862445199635215E-5, 4.9854102823193375972212E-1,
  32. 6.5787325942061044846969E0, 2.9911919328553073277375E1,
  33. 6.0949667980987787057556E1, 5.7112963590585538103336E1,
  34. 2.0039553499201281259648E1,
  35. };
  36. static double LQ[] = {
  37. /* 1.0000000000000000000000E0,*/
  38. 1.5062909083469192043167E1, 8.3047565967967209469434E1,
  39. 2.2176239823732856465394E2, 3.0909872225312059774938E2,
  40. 2.1642788614495947685003E2, 6.0118660497603843919306E1,
  41. };
  42. #define SQRTH 0.70710678118654752440
  43. #define SQRT2 1.41421356237309504880
  44. double log1p(x) double x;
  45. {
  46. double z;
  47. z = 1.0 + x;
  48. if ((z < SQRTH) || (z > SQRT2))
  49. return (log(z));
  50. z = x * x;
  51. z = -0.5 * z + x * (z * polevl(x, LP, 6) / p1evl(x, LQ, 6));
  52. return (x + z);
  53. }
  54. /* expm1(x) = exp(x) - 1 */
  55. /* e^x = 1 + 2x P(x^2)/( Q(x^2) - P(x^2) )
  56. * -0.5 <= x <= 0.5
  57. */
  58. static double EP[3] = {
  59. 1.2617719307481059087798E-4,
  60. 3.0299440770744196129956E-2,
  61. 9.9999999999999999991025E-1,
  62. };
  63. static double EQ[4] = {
  64. 3.0019850513866445504159E-6,
  65. 2.5244834034968410419224E-3,
  66. 2.2726554820815502876593E-1,
  67. 2.0000000000000000000897E0,
  68. };
  69. double expm1(x) double x;
  70. {
  71. double r, xx;
  72. #ifdef NANS
  73. if (isnan(x))
  74. return (x);
  75. #endif
  76. #ifdef INFINITIES
  77. if (x == INFINITY)
  78. return (INFINITY);
  79. if (x == -INFINITY)
  80. return (-1.0);
  81. #endif
  82. if ((x < -0.5) || (x > 0.5))
  83. return (exp(x) - 1.0);
  84. xx = x * x;
  85. r = x * polevl(xx, EP, 2);
  86. r = r / (polevl(xx, EQ, 3) - r);
  87. return (r + r);
  88. }
  89. /* cosm1(x) = cos(x) - 1 */
  90. static double coscof[7] = {
  91. 4.7377507964246204691685E-14, -1.1470284843425359765671E-11,
  92. 2.0876754287081521758361E-9, -2.7557319214999787979814E-7,
  93. 2.4801587301570552304991E-5, -1.3888888888888872993737E-3,
  94. 4.1666666666666666609054E-2,
  95. };
  96. extern double PIO4;
  97. double cosm1(x) double x;
  98. {
  99. double xx;
  100. if ((x < -PIO4) || (x > PIO4))
  101. return (cos(x) - 1.0);
  102. xx = x * x;
  103. xx = -0.5 * xx + xx * xx * polevl(xx, coscof, 6);
  104. return xx;
  105. }