123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- package math_cmplx
- import "core:builtin"
- import "core:math"
- // The original C code, the long comment, and the constants
- // below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
- // The go code is a simplified version of the original C.
- //
- // Cephes Math Library Release 2.8: June, 2000
- // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
- //
- // The readme file at http://netlib.sandia.gov/cephes/ says:
- // Some software in this archive may be from the book _Methods and
- // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
- // International, 1989) or from the Cephes Mathematical Library, a
- // commercial product. In either event, it is copyrighted by the author.
- // What you see here may be used freely but it comes with no support or
- // guarantee.
- //
- // The two known misprints in the book are repaired here in the
- // source listings for the gamma function and the incomplete beta
- // integral.
- //
- // Stephen L. Moshier
- // [email protected]
- acos :: proc{
- acos_complex32,
- acos_complex64,
- acos_complex128,
- }
- acosh :: proc{
- acosh_complex32,
- acosh_complex64,
- acosh_complex128,
- }
- asin :: proc{
- asin_complex32,
- asin_complex64,
- asin_complex128,
- }
- asinh :: proc{
- asinh_complex32,
- asinh_complex64,
- asinh_complex128,
- }
- atan :: proc{
- atan_complex32,
- atan_complex64,
- atan_complex128,
- }
- atanh :: proc{
- atanh_complex32,
- atanh_complex64,
- atanh_complex128,
- }
- acos_complex32 :: proc "contextless" (x: complex32) -> complex32 {
- w := asin(x)
- return complex(math.PI/2 - real(w), -imag(w))
- }
- acos_complex64 :: proc "contextless" (x: complex64) -> complex64 {
- w := asin(x)
- return complex(math.PI/2 - real(w), -imag(w))
- }
- acos_complex128 :: proc "contextless" (x: complex128) -> complex128 {
- w := asin(x)
- return complex(math.PI/2 - real(w), -imag(w))
- }
- acosh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
- if x == 0 {
- return complex(0, math.copy_sign(math.PI/2, imag(x)))
- }
- w := acos(x)
- if imag(w) <= 0 {
- return complex(-imag(w), real(w))
- }
- return complex(imag(w), -real(w))
- }
- acosh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
- if x == 0 {
- return complex(0, math.copy_sign(math.PI/2, imag(x)))
- }
- w := acos(x)
- if imag(w) <= 0 {
- return complex(-imag(w), real(w))
- }
- return complex(imag(w), -real(w))
- }
- acosh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
- if x == 0 {
- return complex(0, math.copy_sign(math.PI/2, imag(x)))
- }
- w := acos(x)
- if imag(w) <= 0 {
- return complex(-imag(w), real(w))
- }
- return complex(imag(w), -real(w))
- }
- asin_complex32 :: proc "contextless" (x: complex32) -> complex32 {
- return complex32(asin_complex128(complex128(x)))
- }
- asin_complex64 :: proc "contextless" (x: complex64) -> complex64 {
- return complex64(asin_complex128(complex128(x)))
- }
- asin_complex128 :: proc "contextless" (x: complex128) -> complex128 {
- switch re, im := real(x), imag(x); {
- case im == 0 && abs(re) <= 1:
- return complex(math.asin(re), im)
- case re == 0 && abs(im) <= 1:
- return complex(re, math.asinh(im))
- case math.is_nan(im):
- switch {
- case re == 0:
- return complex(re, math.nan_f64())
- case math.is_inf(re, 0):
- return complex(math.nan_f64(), re)
- case:
- return nan_complex128()
- }
- case math.is_inf(im, 0):
- switch {
- case math.is_nan(re):
- return x
- case math.is_inf(re, 0):
- return complex(math.copy_sign(math.PI/4, re), im)
- case:
- return complex(math.copy_sign(0, re), im)
- }
- case math.is_inf(re, 0):
- return complex(math.copy_sign(math.PI/2, re), math.copy_sign(re, im))
- }
- ct := complex(-imag(x), real(x)) // i * x
- xx := x * x
- x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x
- x2 := sqrt(x1) // x2 = sqrt(1 - x*x)
- w := ln(ct + x2)
- return complex(imag(w), -real(w)) // -i * w
- }
- asinh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
- return complex32(asinh_complex128(complex128(x)))
- }
- asinh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
- return complex64(asinh_complex128(complex128(x)))
- }
- asinh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
- switch re, im := real(x), imag(x); {
- case im == 0 && abs(re) <= 1:
- return complex(math.asinh(re), im)
- case re == 0 && abs(im) <= 1:
- return complex(re, math.asin(im))
- case math.is_inf(re, 0):
- switch {
- case math.is_inf(im, 0):
- return complex(re, math.copy_sign(math.PI/4, im))
- case math.is_nan(im):
- return x
- case:
- return complex(re, math.copy_sign(0.0, im))
- }
- case math.is_nan(re):
- switch {
- case im == 0:
- return x
- case math.is_inf(im, 0):
- return complex(im, re)
- case:
- return nan_complex128()
- }
- case math.is_inf(im, 0):
- return complex(math.copy_sign(im, re), math.copy_sign(math.PI/2, im))
- }
- xx := x * x
- x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
- return ln(x + sqrt(x1)) // log(x + sqrt(1 + x*x))
- }
- atan_complex32 :: proc "contextless" (x: complex32) -> complex32 {
- return complex32(atan_complex128(complex128(x)))
- }
- atan_complex64 :: proc "contextless" (x: complex64) -> complex64 {
- return complex64(atan_complex128(complex128(x)))
- }
- atan_complex128 :: proc "contextless" (x: complex128) -> complex128 {
- // Complex circular arc tangent
- //
- // DESCRIPTION:
- //
- // If
- // z = x + iy,
- //
- // then
- // 1 ( 2x )
- // Re w = - arctan(-----------) + k PI
- // 2 ( 2 2)
- // (1 - x - y )
- //
- // ( 2 2)
- // 1 (x + (y+1) )
- // Im w = - log(------------)
- // 4 ( 2 2)
- // (x + (y-1) )
- //
- // Where k is an arbitrary integer.
- //
- // catan(z) = -i catanh(iz).
- //
- // ACCURACY:
- //
- // Relative error:
- // arithmetic domain # trials peak rms
- // DEC -10,+10 5900 1.3e-16 7.8e-18
- // IEEE -10,+10 30000 2.3e-15 8.5e-17
- // The check catan( ctan(z) ) = z, with |x| and |y| < PI/2,
- // had peak relative error 1.5e-16, rms relative error
- // 2.9e-17. See also clog().
- switch re, im := real(x), imag(x); {
- case im == 0:
- return complex(math.atan(re), im)
- case re == 0 && abs(im) <= 1:
- return complex(re, math.atanh(im))
- case math.is_inf(im, 0) || math.is_inf(re, 0):
- if math.is_nan(re) {
- return complex(math.nan_f64(), math.copy_sign(0, im))
- }
- return complex(math.copy_sign(math.PI/2, re), math.copy_sign(0, im))
- case math.is_nan(re) || math.is_nan(im):
- return nan_complex128()
- }
- x2 := real(x) * real(x)
- a := 1 - x2 - imag(x)*imag(x)
- if a == 0 {
- return nan_complex128()
- }
- t := 0.5 * math.atan2(2*real(x), a)
- w := _reduce_pi_f64(t)
- t = imag(x) - 1
- b := x2 + t*t
- if b == 0 {
- return nan_complex128()
- }
- t = imag(x) + 1
- c := (x2 + t*t) / b
- return complex(w, 0.25*math.ln(c))
- }
- atanh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
- z := complex(-imag(x), real(x)) // z = i * x
- z = atan(z)
- return complex(imag(z), -real(z)) // z = -i * z
- }
- atanh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
- z := complex(-imag(x), real(x)) // z = i * x
- z = atan(z)
- return complex(imag(z), -real(z)) // z = -i * z
- }
- atanh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
- z := complex(-imag(x), real(x)) // z = i * x
- z = atan(z)
- return complex(imag(z), -real(z)) // z = -i * z
- }
|