````// 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 cmplx`

`import (`
`	"math"`
`	"math/bits"`
`)`

`// 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 Tan(x complex128) complex128 {`
`	switch re, im := real(x), imag(x); {`
`	case math.IsInf(im, 0):`
`		switch {`
`		case math.IsInf(re, 0) || math.IsNaN(re):`
`			return complex(math.Copysign(0, re), math.Copysign(1, im))`
`		}`
`		return complex(math.Copysign(0, math.Sin(2*re)), math.Copysign(1, im))`
`	case re == 0 && math.IsNaN(im):`
`		return x`
`	}`
`	d := math.Cos(2*real(x)) + math.Cosh(2*imag(x))`
`	if math.Abs(d) < 0.25 {`
`		d = tanSeries(x)`
`	}`
`	if d == 0 {`
`		return Inf()`
`	}`
`	return complex(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d)`
`}`

`// 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 Tanh(x complex128) complex128 {`
`	switch re, im := real(x), imag(x); {`
`	case math.IsInf(re, 0):`
`		switch {`
`		case math.IsInf(im, 0) || math.IsNaN(im):`
`			return complex(math.Copysign(1, re), math.Copysign(0, im))`
`		}`
`		return complex(math.Copysign(1, re), math.Copysign(0, math.Sin(2*im)))`
`	case im == 0 && math.IsNaN(re):`
`		return x`
`	}`
`	d := math.Cosh(2*real(x)) + math.Cos(2*imag(x))`
`	if d == 0 {`
`		return Inf()`
`	}`
`	return complex(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d)`
`}`

`// 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(x 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 reduceThreshold float64 = 1 << 30`
`	if math.Abs(x) < reduceThreshold {`
`		// 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.`
`			PI1 = 3.141592502593994      // 0x400921fb40000000`
`			PI2 = 1.5099578831723193e-07 // 0x3e84442d00000000`
`			PI3 = 1.0780605716316238e-14 // 0x3d08469898cc5170`
`		)`
`		t := x / math.Pi`
`		t += 0.5`
`		t = float64(int64(t)) // int64(t) = the multiple`
`		return ((x - t*PI1) - t*PI2) - t*PI3`
`	}`
`	// Must apply Payne-Hanek range reduction`
`	const (`
`		mask     = 0x7FF`
`		shift    = 64 - 11 - 1`
`		bias     = 1023`
`		fracMask = 1<<shift - 1`
`	)`
`	// Extract out the integer and exponent such that,`
`	// x = ix * 2 ** exp.`
`	ix := math.Float64bits(x)`
`	exp := int(ix>>shift&mask) - bias - shift`
`	ix &= fracMask`
`	ix |= 1 << shift`

`	// 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 mPi = [...]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.`
`	digit, bitshift := uint(exp+64)/64, uint(exp+64)%64`
`	z0 := (mPi[digit] << bitshift) | (mPi[digit+1] >> (64 - bitshift))`
`	z1 := (mPi[digit+1] << bitshift) | (mPi[digit+2] >> (64 - bitshift))`
`	z2 := (mPi[digit+2] << bitshift) | (mPi[digit+3] >> (64 - bitshift))`
`	// Multiply mantissa by the digits and extract the upper two digits (hi, lo).`
`	z2hi, _ := bits.Mul64(z2, ix)`
`	z1hi, z1lo := bits.Mul64(z1, ix)`
`	z0lo := z0 * ix`
`	lo, c := bits.Add64(z1lo, z2hi, 0)`
`	hi, _ := bits.Add64(z0lo, z1hi, c)`
`	// Find the magnitude of the fraction.`
`	lz := uint(bits.LeadingZeros64(hi))`
`	e := uint64(bias - (lz + 1))`
`	// Clear implicit mantissa bit and shift into place.`
`	hi = (hi << (lz + 1)) | (lo >> (64 - (lz + 1)))`
`	hi >>= 64 - shift`
`	// Include the exponent and convert to a float.`
`	hi |= e << shift`
`	x = math.Float64frombits(hi)`
`	// map to (-Pi/2, Pi/2]`
`	if x > 0.5 {`
`		x--`
`	}`
`	return math.Pi * x`
`}`

`// Taylor series expansion for cosh(2y) - cos(2x)`
`func tanSeries(z complex128) float64 {`
`	const MACHEP = 1.0 / (1 << 53)`
`	x := math.Abs(2 * real(z))`
`	y := math.Abs(2 * imag(z))`
`	x = reducePi(x)`
`	x = x * x`
`	y = y * y`
`	x2 := 1.0`
`	y2 := 1.0`
`	f := 1.0`
`	rn := 0.0`
`	d := 0.0`
`	for {`
`		rn++`
`		f *= rn`
`		rn++`
`		f *= rn`
`		x2 *= x`
`		y2 *= y`
`		t := y2 + x2`
`		t /= f`
`		d += t`

`		rn++`
`		f *= rn`
`		rn++`
`		f *= rn`
`		x2 *= x`
`		y2 *= y`
`		t = y2 - x2`
`		t /= f`
`		d += t`
`		if !(math.Abs(t/d) > MACHEP) {`
`			// Caution: Use ! and > instead of <= for correct behavior if t/d is NaN.`
`			// See issue 17577.`
`			break`
`		}`
`	}`
`	return d`
`}`

`// 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 Cot(x complex128) complex128 {`
`	d := math.Cosh(2*imag(x)) - math.Cos(2*real(x))`
`	if math.Abs(d) < 0.25 {`
`		d = tanSeries(x)`
`	}`
`	if d == 0 {`
`		return Inf()`
`	}`
`	return complex(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d)`
`}`
```