github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/num/quat/trig.go (about) 1 // Copyright ©2018 The Gonum 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 // Copyright 2017 The Go Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style 7 // license that can be found in the LICENSE file. 8 9 package quat 10 11 import "math" 12 13 // Sin returns the sine of q. 14 func Sin(q Number) Number { 15 w, uv := split(q) 16 if uv == zero { 17 return lift(math.Sin(w)) 18 } 19 v := Abs(uv) 20 s, c := math.Sincos(w) 21 sh, ch := sinhcosh(v) 22 return join(s*ch, Scale(c*sh/v, uv)) 23 } 24 25 // Sinh returns the hyperbolic sine of q. 26 func Sinh(q Number) Number { 27 w, uv := split(q) 28 if uv == zero { 29 return lift(math.Sinh(w)) 30 } 31 v := Abs(uv) 32 s, c := math.Sincos(v) 33 sh, ch := sinhcosh(w) 34 return join(c*sh, scale(s*ch/v, uv)) 35 } 36 37 // Cos returns the cosine of q. 38 func Cos(q Number) Number { 39 w, uv := split(q) 40 if uv == zero { 41 return lift(math.Cos(w)) 42 } 43 v := Abs(uv) 44 s, c := math.Sincos(w) 45 sh, ch := sinhcosh(v) 46 return join(c*ch, Scale(-s*sh/v, uv)) 47 } 48 49 // Cosh returns the hyperbolic cosine of q. 50 func Cosh(q Number) Number { 51 w, uv := split(q) 52 if uv == zero { 53 return lift(math.Cosh(w)) 54 } 55 v := Abs(uv) 56 s, c := math.Sincos(v) 57 sh, ch := sinhcosh(w) 58 return join(c*ch, scale(s*sh/v, uv)) 59 } 60 61 // Tan returns the tangent of q. 62 func Tan(q Number) Number { 63 d := Cos(q) 64 if d == zero { 65 return Inf() 66 } 67 return Mul(Sin(q), Inv(d)) 68 } 69 70 // Tanh returns the hyperbolic tangent of q. 71 func Tanh(q Number) Number { 72 if math.IsInf(q.Real, 1) { 73 r := Number{Real: 1} 74 // Change signs dependent on imaginary parts. 75 r.Imag *= math.Sin(2 * q.Imag) 76 r.Jmag *= math.Sin(2 * q.Jmag) 77 r.Kmag *= math.Sin(2 * q.Kmag) 78 return r 79 } 80 d := Cosh(q) 81 if d == zero { 82 return Inf() 83 } 84 return Mul(Sinh(q), Inv(d)) 85 } 86 87 // Asin returns the inverse sine of q. 88 func Asin(q Number) Number { 89 _, uv := split(q) 90 if uv == zero { 91 return lift(math.Asin(q.Real)) 92 } 93 u := unit(uv) 94 return Mul(Scale(-1, u), Log(Add(Mul(u, q), Sqrt(Sub(Number{Real: 1}, Mul(q, q)))))) 95 } 96 97 // Asinh returns the inverse hyperbolic sine of q. 98 func Asinh(q Number) Number { 99 return Log(Add(q, Sqrt(Add(Number{Real: 1}, Mul(q, q))))) 100 } 101 102 // Acos returns the inverse cosine of q. 103 func Acos(q Number) Number { 104 w, uv := split(Asin(q)) 105 return join(math.Pi/2-w, Scale(-1, uv)) 106 } 107 108 // Acosh returns the inverse hyperbolic cosine of q. 109 func Acosh(q Number) Number { 110 w := Acos(q) 111 _, uv := split(w) 112 if uv == zero { 113 return w 114 } 115 w = Mul(w, unit(uv)) 116 if w.Real < 0 { 117 w = Scale(-1, w) 118 } 119 return w 120 } 121 122 // Atan returns the inverse tangent of q. 123 func Atan(q Number) Number { 124 w, uv := split(q) 125 if uv == zero { 126 return lift(math.Atan(w)) 127 } 128 u := unit(uv) 129 return Mul(Mul(lift(0.5), u), Log(Mul(Add(u, q), Inv(Sub(u, q))))) 130 } 131 132 // Atanh returns the inverse hyperbolic tangent of q. 133 func Atanh(q Number) Number { 134 w, uv := split(q) 135 if uv == zero { 136 return lift(math.Atanh(w)) 137 } 138 u := unit(uv) 139 return Mul(Scale(-1, u), Atan(Mul(u, q))) 140 } 141 142 // calculate sinh and cosh 143 func sinhcosh(x float64) (sh, ch float64) { 144 if math.Abs(x) <= 0.5 { 145 return math.Sinh(x), math.Cosh(x) 146 } 147 e := math.Exp(x) 148 ei := 0.5 / e 149 e *= 0.5 150 return e - ei, e + ei 151 } 152 153 // scale returns q scaled by f, except that inf×0 is 0. 154 func scale(f float64, q Number) Number { 155 if f == 0 { 156 return Number{} 157 } 158 if q.Real != 0 { 159 q.Real *= f 160 } 161 if q.Imag != 0 { 162 q.Imag *= f 163 } 164 if q.Jmag != 0 { 165 q.Jmag *= f 166 } 167 if q.Kmag != 0 { 168 q.Kmag *= f 169 } 170 return q 171 }