s_ctanl.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* $OpenBSD: s_ctanl.c,v 1.3 2011/07/20 21:02:51 martynas Exp $ */
  2. /*
  3. * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* ctanl()
  18. *
  19. * Complex circular tangent
  20. *
  21. *
  22. *
  23. * SYNOPSIS:
  24. *
  25. * long double complex ctanl();
  26. * long double complex z, w;
  27. *
  28. * w = ctanl( z );
  29. *
  30. *
  31. *
  32. * DESCRIPTION:
  33. *
  34. * If
  35. * z = x + iy,
  36. *
  37. * then
  38. *
  39. * sin 2x + i sinh 2y
  40. * w = --------------------.
  41. * cos 2x + cosh 2y
  42. *
  43. * On the real axis the denominator is zero at odd multiples
  44. * of PI/2. The denominator is evaluated by its Taylor
  45. * series near these points.
  46. *
  47. *
  48. * ACCURACY:
  49. *
  50. * Relative error:
  51. * arithmetic domain # trials peak rms
  52. * DEC -10,+10 5200 7.1e-17 1.6e-17
  53. * IEEE -10,+10 30000 7.2e-16 1.2e-16
  54. * Also tested by ctan * ccot = 1 and catan(ctan(z)) = z.
  55. */
  56. #include <float.h>
  57. #include <openlibm.h>
  58. #include <openlibm_complex.h>
  59. #if LDBL_MANT_DIG == 64
  60. static const long double MACHEPL= 5.42101086242752217003726400434970855712890625E-20L;
  61. #elif LDBL_MANT_DIG == 113
  62. static const long double MACHEPL = 9.629649721936179265279889712924636592690508e-35L;
  63. #endif
  64. static const long double PIL = 3.141592653589793238462643383279502884197169L;
  65. static const long double DP1 = 3.14159265358979323829596852490908531763125L;
  66. static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L;
  67. static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L;
  68. static long double
  69. redupil(long double x)
  70. {
  71. long double t;
  72. long i;
  73. t = x / PIL;
  74. if (t >= 0.0L)
  75. t += 0.5L;
  76. else
  77. t -= 0.5L;
  78. i = t; /* the multiple */
  79. t = i;
  80. t = ((x - t * DP1) - t * DP2) - t * DP3;
  81. return (t);
  82. }
  83. static long double
  84. ctansl(long double complex z)
  85. {
  86. long double f, x, x2, y, y2, rn, t;
  87. long double d;
  88. x = fabsl(2.0L * creall(z));
  89. y = fabsl(2.0L * cimagl(z));
  90. x = redupil(x);
  91. x = x * x;
  92. y = y * y;
  93. x2 = 1.0L;
  94. y2 = 1.0L;
  95. f = 1.0L;
  96. rn = 0.0L;
  97. d = 0.0L;
  98. do {
  99. rn += 1.0L;
  100. f *= rn;
  101. rn += 1.0L;
  102. f *= rn;
  103. x2 *= x;
  104. y2 *= y;
  105. t = y2 + x2;
  106. t /= f;
  107. d += t;
  108. rn += 1.0L;
  109. f *= rn;
  110. rn += 1.0L;
  111. f *= rn;
  112. x2 *= x;
  113. y2 *= y;
  114. t = y2 - x2;
  115. t /= f;
  116. d += t;
  117. }
  118. while (fabsl(t/d) > MACHEPL);
  119. return(d);
  120. }
  121. long double complex
  122. ctanl(long double complex z)
  123. {
  124. long double complex w;
  125. long double d, x, y;
  126. x = creall(z);
  127. y = cimagl(z);
  128. d = cosl(2.0L * x) + coshl(2.0L * y);
  129. if (fabsl(d) < 0.25L) {
  130. d = fabsl(d);
  131. d = ctansl(z);
  132. }
  133. if (d == 0.0L) {
  134. /*mtherr( "ctan", OVERFLOW );*/
  135. w = LDBL_MAX + LDBL_MAX * I;
  136. return (w);
  137. }
  138. w = sinl(2.0L * x) / d + (sinhl(2.0L * y) / d) * I;
  139. return (w);
  140. }