// Copyright ©2018 The Gonum 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 hyperdual import "math" // Sinh returns the hyperbolic sine of d. // // Special cases are: // // Sinh(±0) = (±0+Nϵ₁+Nϵ₂±0ϵ₁ϵ₂) // Sinh(±Inf) = ±Inf // Sinh(NaN) = NaN func Sinh(d Number) Number { if d.Real == 0 { return Number{ Real: d.Real, E1mag: d.E1mag, E2mag: d.E1mag, E1E2mag: d.Real, } } if math.IsInf(d.Real, 0) { return Number{ Real: d.Real, E1mag: math.Inf(1), E2mag: math.Inf(1), E1E2mag: d.Real, } } fn := math.Sinh(d.Real) deriv := math.Cosh(d.Real) return Number{ Real: fn, E1mag: deriv * d.E1mag, E2mag: deriv * d.E2mag, E1E2mag: deriv*d.E1E2mag + fn*d.E1mag*d.E2mag, } } // Cosh returns the hyperbolic cosine of d. // // Special cases are: // // Cosh(±0) = 1 // Cosh(±Inf) = +Inf // Cosh(NaN) = NaN func Cosh(d Number) Number { if math.IsInf(d.Real, 0) { return Number{ Real: math.Inf(1), E1mag: d.Real, E2mag: d.Real, E1E2mag: math.Inf(1), } } fn := math.Cosh(d.Real) deriv := math.Sinh(d.Real) return Number{ Real: fn, E1mag: deriv * d.E1mag, E2mag: deriv * d.E2mag, E1E2mag: deriv*d.E1E2mag + fn*d.E1mag*d.E2mag, } } // Tanh returns the hyperbolic tangent of d. // // Special cases are: // // Tanh(±0) = (±0+Nϵ₁+Nϵ₂∓0ϵ₁ϵ₂) // Tanh(±Inf) = (±1+0ϵ₁+0ϵ₂∓0ϵ₁ϵ₂) // Tanh(NaN) = NaN func Tanh(d Number) Number { switch d.Real { case 0: return Number{ Real: d.Real, E1mag: d.E1mag, E2mag: d.E2mag, E1E2mag: -d.Real, } case math.Inf(1): return Number{ Real: 1, E1mag: 0, E2mag: 0, E1E2mag: negZero, } case math.Inf(-1): return Number{ Real: -1, E1mag: 0, E2mag: 0, E1E2mag: 0, } } fn := math.Tanh(d.Real) deriv := 1 - fn*fn return Number{ Real: fn, E1mag: deriv * d.E1mag, E2mag: deriv * d.E2mag, E1E2mag: deriv*d.E1E2mag - d.E1mag*d.E2mag*(2*fn*deriv), } } // Asinh returns the inverse hyperbolic sine of d. // // Special cases are: // // Asinh(±0) = (±0+Nϵ₁+Nϵ₂∓0ϵ₁ϵ₂) // Asinh(±Inf) = ±Inf // Asinh(NaN) = NaN func Asinh(d Number) Number { if d.Real == 0 { return Number{ Real: d.Real, E1mag: d.E1mag, E2mag: d.E2mag, E1E2mag: -d.Real, } } fn := math.Asinh(d.Real) deriv1 := d.Real*d.Real + 1 deriv := 1 / math.Sqrt(deriv1) return Number{ Real: fn, E1mag: deriv * d.E1mag, E2mag: deriv * d.E2mag, E1E2mag: deriv*d.E1E2mag + d.E1mag*d.E2mag*(-d.Real*(deriv/deriv1)), } } // Acosh returns the inverse hyperbolic cosine of d. // // Special cases are: // // Acosh(+Inf) = +Inf // Acosh(1) = (0+Infϵ₁+Infϵ₂-Infϵ₁ϵ₂) // Acosh(x) = NaN if x < 1 // Acosh(NaN) = NaN func Acosh(d Number) Number { if d.Real <= 1 { if d.Real == 1 { return Number{ Real: 0, E1mag: math.Inf(1), E2mag: math.Inf(1), E1E2mag: math.Inf(-1), } } return Number{ Real: math.NaN(), E1mag: math.NaN(), E2mag: math.NaN(), E1E2mag: math.NaN(), } } fn := math.Acosh(d.Real) deriv1 := d.Real*d.Real - 1 deriv := 1 / math.Sqrt(deriv1) return Number{ Real: fn, E1mag: deriv * d.E1mag, E2mag: deriv * d.E2mag, E1E2mag: deriv*d.E1E2mag + d.E1mag*d.E2mag*(-d.Real*(deriv/deriv1)), } } // Atanh returns the inverse hyperbolic tangent of d. // // Special cases are: // // Atanh(1) = +Inf // Atanh(±0) = (±0+Nϵ₁+Nϵ₂±0ϵ₁ϵ₂) // Atanh(-1) = -Inf // Atanh(x) = NaN if x < -1 or x > 1 // Atanh(NaN) = NaN func Atanh(d Number) Number { if d.Real == 0 { return Number{ Real: d.Real, E1mag: d.E1mag, E2mag: d.E2mag, E1E2mag: d.Real, } } if math.Abs(d.Real) == 1 { return Number{ Real: math.Inf(int(d.Real)), E1mag: math.NaN(), E2mag: math.NaN(), E1E2mag: math.Inf(int(d.Real)), } } fn := math.Atanh(d.Real) deriv1 := 1 - d.Real*d.Real deriv := 1 / deriv1 return Number{ Real: fn, E1mag: deriv * d.E1mag, E2mag: deriv * d.E2mag, E1E2mag: deriv*d.E1E2mag + d.E1mag*d.E2mag*(2*d.Real/(deriv1*deriv1)), } }