github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/math/sincos.go (about) 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 5 package math 6 7 // Coefficients _sin[] and _cos[] are found in pkg/math/sin.go. 8 9 // Sincos returns Sin(x), Cos(x). 10 // 11 // Special cases are: 12 // Sincos(±0) = ±0, 1 13 // Sincos(±Inf) = NaN, NaN 14 // Sincos(NaN) = NaN, NaN 15 func Sincos(x float64) (sin, cos float64) { 16 const ( 17 PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts 18 PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, 19 PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, 20 ) 21 // special cases 22 switch { 23 case x == 0: 24 return x, 1 // return ±0.0, 1.0 25 case IsNaN(x) || IsInf(x, 0): 26 return NaN(), NaN() 27 } 28 29 // make argument positive 30 sinSign, cosSign := false, false 31 if x < 0 { 32 x = -x 33 sinSign = true 34 } 35 36 var j uint64 37 var y, z float64 38 if x >= reduceThreshold { 39 j, z = trigReduce(x) 40 } else { 41 j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle 42 y = float64(j) // integer part of x/(Pi/4), as float 43 44 if j&1 == 1 { // map zeros to origin 45 j++ 46 y++ 47 } 48 j &= 7 // octant modulo 2Pi radians (360 degrees) 49 z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic 50 } 51 if j > 3 { // reflect in x axis 52 j -= 4 53 sinSign, cosSign = !sinSign, !cosSign 54 } 55 if j > 1 { 56 cosSign = !cosSign 57 } 58 59 zz := z * z 60 cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5]) 61 sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) 62 if j == 1 || j == 2 { 63 sin, cos = cos, sin 64 } 65 if cosSign { 66 cos = -cos 67 } 68 if sinSign { 69 sin = -sin 70 } 71 return 72 }