sin.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright 2010 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package cmplx
  5. import "math"
  6. // The original C code, the long comment, and the constants
  7. // below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
  8. // The go code is a simplified version of the original C.
  9. //
  10. // Cephes Math Library Release 2.8: June, 2000
  11. // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
  12. //
  13. // The readme file at http://netlib.sandia.gov/cephes/ says:
  14. // Some software in this archive may be from the book _Methods and
  15. // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
  16. // International, 1989) or from the Cephes Mathematical Library, a
  17. // commercial product. In either event, it is copyrighted by the author.
  18. // What you see here may be used freely but it comes with no support or
  19. // guarantee.
  20. //
  21. // The two known misprints in the book are repaired here in the
  22. // source listings for the gamma function and the incomplete beta
  23. // integral.
  24. //
  25. // Stephen L. Moshier
  26. // moshier@na-net.ornl.gov
  27. // Complex circular sine
  28. //
  29. // DESCRIPTION:
  30. //
  31. // If
  32. // z = x + iy,
  33. //
  34. // then
  35. //
  36. // w = sin x cosh y + i cos x sinh y.
  37. //
  38. // csin(z) = -i csinh(iz).
  39. //
  40. // ACCURACY:
  41. //
  42. // Relative error:
  43. // arithmetic domain # trials peak rms
  44. // DEC -10,+10 8400 5.3e-17 1.3e-17
  45. // IEEE -10,+10 30000 3.8e-16 1.0e-16
  46. // Also tested by csin(casin(z)) = z.
  47. // Sin returns the sine of x.
  48. func Sin(x complex128) complex128 {
  49. switch re, im := real(x), imag(x); {
  50. case im == 0 && (math.IsInf(re, 0) || math.IsNaN(re)):
  51. return complex(math.NaN(), im)
  52. case math.IsInf(im, 0):
  53. switch {
  54. case re == 0:
  55. return x
  56. case math.IsInf(re, 0) || math.IsNaN(re):
  57. return complex(math.NaN(), im)
  58. }
  59. case re == 0 && math.IsNaN(im):
  60. return x
  61. }
  62. s, c := math.Sincos(real(x))
  63. sh, ch := sinhcosh(imag(x))
  64. return complex(s*ch, c*sh)
  65. }
  66. // Complex hyperbolic sine
  67. //
  68. // DESCRIPTION:
  69. //
  70. // csinh z = (cexp(z) - cexp(-z))/2
  71. // = sinh x * cos y + i cosh x * sin y .
  72. //
  73. // ACCURACY:
  74. //
  75. // Relative error:
  76. // arithmetic domain # trials peak rms
  77. // IEEE -10,+10 30000 3.1e-16 8.2e-17
  78. // Sinh returns the hyperbolic sine of x.
  79. func Sinh(x complex128) complex128 {
  80. switch re, im := real(x), imag(x); {
  81. case re == 0 && (math.IsInf(im, 0) || math.IsNaN(im)):
  82. return complex(re, math.NaN())
  83. case math.IsInf(re, 0):
  84. switch {
  85. case im == 0:
  86. return complex(re, im)
  87. case math.IsInf(im, 0) || math.IsNaN(im):
  88. return complex(re, math.NaN())
  89. }
  90. case im == 0 && math.IsNaN(re):
  91. return complex(math.NaN(), im)
  92. }
  93. s, c := math.Sincos(imag(x))
  94. sh, ch := sinhcosh(real(x))
  95. return complex(c*sh, s*ch)
  96. }
  97. // Complex circular cosine
  98. //
  99. // DESCRIPTION:
  100. //
  101. // If
  102. // z = x + iy,
  103. //
  104. // then
  105. //
  106. // w = cos x cosh y - i sin x sinh y.
  107. //
  108. // ACCURACY:
  109. //
  110. // Relative error:
  111. // arithmetic domain # trials peak rms
  112. // DEC -10,+10 8400 4.5e-17 1.3e-17
  113. // IEEE -10,+10 30000 3.8e-16 1.0e-16
  114. // Cos returns the cosine of x.
  115. func Cos(x complex128) complex128 {
  116. switch re, im := real(x), imag(x); {
  117. case im == 0 && (math.IsInf(re, 0) || math.IsNaN(re)):
  118. return complex(math.NaN(), -im*math.Copysign(0, re))
  119. case math.IsInf(im, 0):
  120. switch {
  121. case re == 0:
  122. return complex(math.Inf(1), -re*math.Copysign(0, im))
  123. case math.IsInf(re, 0) || math.IsNaN(re):
  124. return complex(math.Inf(1), math.NaN())
  125. }
  126. case re == 0 && math.IsNaN(im):
  127. return complex(math.NaN(), 0)
  128. }
  129. s, c := math.Sincos(real(x))
  130. sh, ch := sinhcosh(imag(x))
  131. return complex(c*ch, -s*sh)
  132. }
  133. // Complex hyperbolic cosine
  134. //
  135. // DESCRIPTION:
  136. //
  137. // ccosh(z) = cosh x cos y + i sinh x sin y .
  138. //
  139. // ACCURACY:
  140. //
  141. // Relative error:
  142. // arithmetic domain # trials peak rms
  143. // IEEE -10,+10 30000 2.9e-16 8.1e-17
  144. // Cosh returns the hyperbolic cosine of x.
  145. func Cosh(x complex128) complex128 {
  146. switch re, im := real(x), imag(x); {
  147. case re == 0 && (math.IsInf(im, 0) || math.IsNaN(im)):
  148. return complex(math.NaN(), re*math.Copysign(0, im))
  149. case math.IsInf(re, 0):
  150. switch {
  151. case im == 0:
  152. return complex(math.Inf(1), im*math.Copysign(0, re))
  153. case math.IsInf(im, 0) || math.IsNaN(im):
  154. return complex(math.Inf(1), math.NaN())
  155. }
  156. case im == 0 && math.IsNaN(re):
  157. return complex(math.NaN(), im)
  158. }
  159. s, c := math.Sincos(imag(x))
  160. sh, ch := sinhcosh(real(x))
  161. return complex(c*ch, s*sh)
  162. }
  163. // calculate sinh and cosh
  164. func sinhcosh(x float64) (sh, ch float64) {
  165. if math.Abs(x) <= 0.5 {
  166. return math.Sinh(x), math.Cosh(x)
  167. }
  168. e := math.Exp(x)
  169. ei := 0.5 / e
  170. e *= 0.5
  171. return e - ei, e + ei
  172. }