gonum.org/v1/gonum@v0.14.0/num/hyperdual/hyperdual_hyperbolic.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  package hyperdual
     6  
     7  import "math"
     8  
     9  // Sinh returns the hyperbolic sine of d.
    10  //
    11  // Special cases are:
    12  //
    13  //	Sinh(±0) = (±0+Nϵ₁+Nϵ₂±0ϵ₁ϵ₂)
    14  //	Sinh(±Inf) = ±Inf
    15  //	Sinh(NaN) = NaN
    16  func Sinh(d Number) Number {
    17  	if d.Real == 0 {
    18  		return Number{
    19  			Real:    d.Real,
    20  			E1mag:   d.E1mag,
    21  			E2mag:   d.E1mag,
    22  			E1E2mag: d.Real,
    23  		}
    24  	}
    25  	if math.IsInf(d.Real, 0) {
    26  		return Number{
    27  			Real:    d.Real,
    28  			E1mag:   math.Inf(1),
    29  			E2mag:   math.Inf(1),
    30  			E1E2mag: d.Real,
    31  		}
    32  	}
    33  	fn := math.Sinh(d.Real)
    34  	deriv := math.Cosh(d.Real)
    35  	return Number{
    36  		Real:    fn,
    37  		E1mag:   deriv * d.E1mag,
    38  		E2mag:   deriv * d.E2mag,
    39  		E1E2mag: deriv*d.E1E2mag + fn*d.E1mag*d.E2mag,
    40  	}
    41  }
    42  
    43  // Cosh returns the hyperbolic cosine of d.
    44  //
    45  // Special cases are:
    46  //
    47  //	Cosh(±0) = 1
    48  //	Cosh(±Inf) = +Inf
    49  //	Cosh(NaN) = NaN
    50  func Cosh(d Number) Number {
    51  	if math.IsInf(d.Real, 0) {
    52  		return Number{
    53  			Real:    math.Inf(1),
    54  			E1mag:   d.Real,
    55  			E2mag:   d.Real,
    56  			E1E2mag: math.Inf(1),
    57  		}
    58  	}
    59  	fn := math.Cosh(d.Real)
    60  	deriv := math.Sinh(d.Real)
    61  	return Number{
    62  		Real:    fn,
    63  		E1mag:   deriv * d.E1mag,
    64  		E2mag:   deriv * d.E2mag,
    65  		E1E2mag: deriv*d.E1E2mag + fn*d.E1mag*d.E2mag,
    66  	}
    67  }
    68  
    69  // Tanh returns the hyperbolic tangent of d.
    70  //
    71  // Special cases are:
    72  //
    73  //	Tanh(±0) = (±0+Nϵ₁+Nϵ₂∓0ϵ₁ϵ₂)
    74  //	Tanh(±Inf) = (±1+0ϵ₁+0ϵ₂∓0ϵ₁ϵ₂)
    75  //	Tanh(NaN) = NaN
    76  func Tanh(d Number) Number {
    77  	switch d.Real {
    78  	case 0:
    79  		return Number{
    80  			Real:    d.Real,
    81  			E1mag:   d.E1mag,
    82  			E2mag:   d.E2mag,
    83  			E1E2mag: -d.Real,
    84  		}
    85  	case math.Inf(1):
    86  		return Number{
    87  			Real:    1,
    88  			E1mag:   0,
    89  			E2mag:   0,
    90  			E1E2mag: negZero,
    91  		}
    92  	case math.Inf(-1):
    93  		return Number{
    94  			Real:    -1,
    95  			E1mag:   0,
    96  			E2mag:   0,
    97  			E1E2mag: 0,
    98  		}
    99  	}
   100  	fn := math.Tanh(d.Real)
   101  	deriv := 1 - fn*fn
   102  	return Number{
   103  		Real:    fn,
   104  		E1mag:   deriv * d.E1mag,
   105  		E2mag:   deriv * d.E2mag,
   106  		E1E2mag: deriv*d.E1E2mag - d.E1mag*d.E2mag*(2*fn*deriv),
   107  	}
   108  }
   109  
   110  // Asinh returns the inverse hyperbolic sine of d.
   111  //
   112  // Special cases are:
   113  //
   114  //	Asinh(±0) = (±0+Nϵ₁+Nϵ₂∓0ϵ₁ϵ₂)
   115  //	Asinh(±Inf) = ±Inf
   116  //	Asinh(NaN) = NaN
   117  func Asinh(d Number) Number {
   118  	if d.Real == 0 {
   119  		return Number{
   120  			Real:    d.Real,
   121  			E1mag:   d.E1mag,
   122  			E2mag:   d.E2mag,
   123  			E1E2mag: -d.Real,
   124  		}
   125  	}
   126  	fn := math.Asinh(d.Real)
   127  	deriv1 := d.Real*d.Real + 1
   128  	deriv := 1 / math.Sqrt(deriv1)
   129  	return Number{
   130  		Real:    fn,
   131  		E1mag:   deriv * d.E1mag,
   132  		E2mag:   deriv * d.E2mag,
   133  		E1E2mag: deriv*d.E1E2mag + d.E1mag*d.E2mag*(-d.Real*(deriv/deriv1)),
   134  	}
   135  }
   136  
   137  // Acosh returns the inverse hyperbolic cosine of d.
   138  //
   139  // Special cases are:
   140  //
   141  //	Acosh(+Inf) = +Inf
   142  //	Acosh(1) = (0+Infϵ₁+Infϵ₂-Infϵ₁ϵ₂)
   143  //	Acosh(x) = NaN if x < 1
   144  //	Acosh(NaN) = NaN
   145  func Acosh(d Number) Number {
   146  	if d.Real <= 1 {
   147  		if d.Real == 1 {
   148  			return Number{
   149  				Real:    0,
   150  				E1mag:   math.Inf(1),
   151  				E2mag:   math.Inf(1),
   152  				E1E2mag: math.Inf(-1),
   153  			}
   154  		}
   155  		return Number{
   156  			Real:    math.NaN(),
   157  			E1mag:   math.NaN(),
   158  			E2mag:   math.NaN(),
   159  			E1E2mag: math.NaN(),
   160  		}
   161  	}
   162  	fn := math.Acosh(d.Real)
   163  	deriv1 := d.Real*d.Real - 1
   164  	deriv := 1 / math.Sqrt(deriv1)
   165  	return Number{
   166  		Real:    fn,
   167  		E1mag:   deriv * d.E1mag,
   168  		E2mag:   deriv * d.E2mag,
   169  		E1E2mag: deriv*d.E1E2mag + d.E1mag*d.E2mag*(-d.Real*(deriv/deriv1)),
   170  	}
   171  }
   172  
   173  // Atanh returns the inverse hyperbolic tangent of d.
   174  //
   175  // Special cases are:
   176  //
   177  //	Atanh(1) = +Inf
   178  //	Atanh(±0) = (±0+Nϵ₁+Nϵ₂±0ϵ₁ϵ₂)
   179  //	Atanh(-1) = -Inf
   180  //	Atanh(x) = NaN if x < -1 or x > 1
   181  //	Atanh(NaN) = NaN
   182  func Atanh(d Number) Number {
   183  	if d.Real == 0 {
   184  		return Number{
   185  			Real:    d.Real,
   186  			E1mag:   d.E1mag,
   187  			E2mag:   d.E2mag,
   188  			E1E2mag: d.Real,
   189  		}
   190  	}
   191  	if math.Abs(d.Real) == 1 {
   192  		return Number{
   193  			Real:    math.Inf(int(d.Real)),
   194  			E1mag:   math.NaN(),
   195  			E2mag:   math.NaN(),
   196  			E1E2mag: math.Inf(int(d.Real)),
   197  		}
   198  	}
   199  	fn := math.Atanh(d.Real)
   200  	deriv1 := 1 - d.Real*d.Real
   201  	deriv := 1 / deriv1
   202  	return Number{
   203  		Real:    fn,
   204  		E1mag:   deriv * d.E1mag,
   205  		E2mag:   deriv * d.E2mag,
   206  		E1E2mag: deriv*d.E1E2mag + d.E1mag*d.E2mag*(2*d.Real/(deriv1*deriv1)),
   207  	}
   208  }