Source File
tan.go
Belonging Package
math/cmplx
// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package cmplximport ()// 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// moshier@na-net.ornl.gov// Complex circular tangent//// DESCRIPTION://// If// z = x + iy,//// then//// sin 2x + i sinh 2y// w = --------------------.// cos 2x + cosh 2y//// On the real axis the denominator is zero at odd multiples// of PI/2. The denominator is evaluated by its Taylor// series near these points.//// ctan(z) = -i ctanh(iz).//// ACCURACY://// Relative error:// arithmetic domain # trials peak rms// DEC -10,+10 5200 7.1e-17 1.6e-17// IEEE -10,+10 30000 7.2e-16 1.2e-16// Also tested by ctan * ccot = 1 and catan(ctan(z)) = z.// Tan returns the tangent of x.func ( complex128) complex128 {switch , := real(), imag(); {case math.IsInf(, 0):switch {case math.IsInf(, 0) || math.IsNaN():return complex(math.Copysign(0, ), math.Copysign(1, ))}return complex(math.Copysign(0, math.Sin(2*)), math.Copysign(1, ))case == 0 && math.IsNaN():return}:= math.Cos(2*real()) + math.Cosh(2*imag())if math.Abs() < 0.25 {= tanSeries()}if == 0 {return Inf()}return complex(math.Sin(2*real())/, math.Sinh(2*imag())/)}// Complex hyperbolic tangent//// DESCRIPTION://// tanh z = (sinh 2x + i sin 2y) / (cosh 2x + cos 2y) .//// ACCURACY://// Relative error:// arithmetic domain # trials peak rms// IEEE -10,+10 30000 1.7e-14 2.4e-16// Tanh returns the hyperbolic tangent of x.func ( complex128) complex128 {switch , := real(), imag(); {case math.IsInf(, 0):switch {case math.IsInf(, 0) || math.IsNaN():return complex(math.Copysign(1, ), math.Copysign(0, ))}return complex(math.Copysign(1, ), math.Copysign(0, math.Sin(2*)))case == 0 && math.IsNaN():return}:= math.Cosh(2*real()) + math.Cos(2*imag())if == 0 {return Inf()}return complex(math.Sinh(2*real())/, math.Sin(2*imag())/)}// reducePi reduces the input argument x to the range (-Pi/2, Pi/2].// x must be greater than or equal to 0. For small arguments it// uses Cody-Waite reduction in 3 float64 parts based on:// "Elementary Function Evaluation: Algorithms and Implementation"// Jean-Michel Muller, 1997.// For very large arguments it uses Payne-Hanek range reduction based on:// "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit"// K. C. Ng et al, March 24, 1992.func reducePi( float64) float64 {// reduceThreshold is the maximum value of x where the reduction using// Cody-Waite reduction still gives accurate results. This threshold// is set by t*PIn being representable as a float64 without error// where t is given by t = floor(x * (1 / Pi)) and PIn are the leading partial// terms of Pi. Since the leading terms, PI1 and PI2 below, have 30 and 32// trailing zero bits respectively, t should have less than 30 significant bits.// t < 1<<30 -> floor(x*(1/Pi)+0.5) < 1<<30 -> x < (1<<30-1) * Pi - 0.5// So, conservatively we can take x < 1<<30.const float64 = 1 << 30if math.Abs() < {// Use Cody-Waite reduction in three parts.const (// PI1, PI2 and PI3 comprise an extended precision value of PI// such that PI ~= PI1 + PI2 + PI3. The parts are chosen so// that PI1 and PI2 have an approximately equal number of trailing// zero bits. This ensures that t*PI1 and t*PI2 are exact for// large integer values of t. The full precision PI3 ensures the// approximation of PI is accurate to 102 bits to handle cancellation// during subtraction.= 3.141592502593994 // 0x400921fb40000000= 1.5099578831723193e-07 // 0x3e84442d00000000= 1.0780605716316238e-14 // 0x3d08469898cc5170):= / math.Pi+= 0.5= float64(int64()) // int64(t) = the multiplereturn (( - *) - *) - *}// Must apply Payne-Hanek range reductionconst (= 0x7FF= 64 - 11 - 1= 1023= 1<< - 1)// Extract out the integer and exponent such that,// x = ix * 2 ** exp.:= math.Float64bits():= int(>>&) - -&=|= 1 <<// mPi is the binary digits of 1/Pi as a uint64 array,// that is, 1/Pi = Sum mPi[i]*2^(-64*i).// 19 64-bit digits give 1216 bits of precision// to handle the largest possible float64 exponent.var = [...]uint64{0x0000000000000000,0x517cc1b727220a94,0xfe13abe8fa9a6ee0,0x6db14acc9e21c820,0xff28b1d5ef5de2b0,0xdb92371d2126e970,0x0324977504e8c90e,0x7f0ef58e5894d39f,0x74411afa975da242,0x74ce38135a2fbf20,0x9cc8eb1cc1a99cfa,0x4e422fc5defc941d,0x8ffc4bffef02cc07,0xf79788c5ad05368f,0xb69b3f6793e584db,0xa7a31fb34f2ff516,0xba93dd63f5f2f8bd,0x9e839cfbc5294975,0x35fdafd88fc6ae84,0x2b0198237e3db5d5,}// Use the exponent to extract the 3 appropriate uint64 digits from mPi,// B ~ (z0, z1, z2), such that the product leading digit has the exponent -64.// Note, exp >= 50 since x >= reduceThreshold and exp < 971 for maximum float64., := uint(+64)/64, uint(+64)%64:= ([] << ) | ([+1] >> (64 - )):= ([+1] << ) | ([+2] >> (64 - )):= ([+2] << ) | ([+3] >> (64 - ))// Multiply mantissa by the digits and extract the upper two digits (hi, lo)., := bits.Mul64(, ), := bits.Mul64(, ):= *, := bits.Add64(, , 0), := bits.Add64(, , )// Find the magnitude of the fraction.:= uint(bits.LeadingZeros64()):= uint64( - ( + 1))// Clear implicit mantissa bit and shift into place.= ( << ( + 1)) | ( >> (64 - ( + 1)))>>= 64 -// Include the exponent and convert to a float.|= <<= math.Float64frombits()// map to (-Pi/2, Pi/2]if > 0.5 {--}return math.Pi *}// Taylor series expansion for cosh(2y) - cos(2x)func tanSeries( complex128) float64 {const = 1.0 / (1 << 53):= math.Abs(2 * real()):= math.Abs(2 * imag())= reducePi()= *= *:= 1.0:= 1.0:= 1.0:= 0.0:= 0.0for {++*=++*=*=*=:= +/=+=++*=++*=*=*== -/=+=if !(math.Abs(/) > ) {// Caution: Use ! and > instead of <= for correct behavior if t/d is NaN.// See issue 17577.break}}return}// Complex circular cotangent//// DESCRIPTION://// If// z = x + iy,//// then//// sin 2x - i sinh 2y// w = --------------------.// cosh 2y - cos 2x//// On the real axis, the denominator has zeros at even// multiples of PI/2. Near these points it is evaluated// by a Taylor series.//// ACCURACY://// Relative error:// arithmetic domain # trials peak rms// DEC -10,+10 3000 6.5e-17 1.6e-17// IEEE -10,+10 30000 9.2e-16 1.2e-16// Also tested by ctan * ccot = 1 + i0.// Cot returns the cotangent of x.func ( complex128) complex128 {:= math.Cosh(2*imag()) - math.Cos(2*real())if math.Abs() < 0.25 {= tanSeries()}if == 0 {return Inf()}return complex(math.Sin(2*real())/, -math.Sinh(2*imag())/)}
![]() |
The pages are generated with Golds v0.7.9-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |