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  }