blob: cf0ffa1923f9d805dd8c6e8ad3caafe4ef845a6a [file] [log] [blame]
Ken Thompson21810982008-03-28 13:56:47 -07001// Copyright 2009 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
Rob Pike43312932008-06-27 17:06:23 -07005package math
Ken Thompson21810982008-03-28 13:56:47 -07006
Charles L. Dorian0f8f5d22012-09-17 17:18:16 -04007// The original C code, the long comment, and the constants
8// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
9// available from http://www.netlib.org/cephes/cmath.tgz.
10// The go code is a simplified version of the original C.
11// tanh.c
12//
13// Hyperbolic tangent
14//
15// SYNOPSIS:
16//
17// double x, y, tanh();
18//
19// y = tanh( x );
20//
21// DESCRIPTION:
22//
23// Returns hyperbolic tangent of argument in the range MINLOG to MAXLOG.
24// MAXLOG = 8.8029691931113054295988e+01 = log(2**127)
25// MINLOG = -8.872283911167299960540e+01 = log(2**-128)
26//
27// A rational function is used for |x| < 0.625. The form
28// x + x**3 P(x)/Q(x) of Cody & Waite is employed.
29// Otherwise,
30// tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1).
31//
32// ACCURACY:
33//
34// Relative error:
35// arithmetic domain # trials peak rms
36// IEEE -2,2 30000 2.5e-16 5.8e-17
37//
38// Cephes Math Library Release 2.8: June, 2000
39// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
40//
41// The readme file at http://netlib.sandia.gov/cephes/ says:
42// Some software in this archive may be from the book _Methods and
43// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
44// International, 1989) or from the Cephes Mathematical Library, a
45// commercial product. In either event, it is copyrighted by the author.
46// What you see here may be used freely but it comes with no support or
47// guarantee.
48//
49// The two known misprints in the book are repaired here in the
50// source listings for the gamma function and the incomplete beta
51// integral.
52//
53// Stephen L. Moshier
54// moshier@na-net.ornl.gov
55//
Rob Pike00e2cda2010-01-12 07:38:31 +110056
Charles L. Dorian0f8f5d22012-09-17 17:18:16 -040057var tanhP = [...]float64{
58 -9.64399179425052238628E-1,
59 -9.92877231001918586564E1,
60 -1.61468768441708447952E3,
61}
62var tanhQ = [...]float64{
63 1.12811678491632931402E2,
64 2.23548839060100448583E3,
65 4.84406305325125486048E3,
66}
Ken Thompson21810982008-03-28 13:56:47 -070067
Oling Cat1693e142013-03-25 08:43:51 -070068// Tanh returns the hyperbolic tangent of x.
Charles L. Dorianabc7df92011-12-05 14:01:24 -050069//
70// Special cases are:
71// Tanh(±0) = ±0
72// Tanh(±Inf) = ±1
73// Tanh(NaN) = NaN
Russ Coxdfc39102009-03-05 13:31:01 -080074func Tanh(x float64) float64 {
Charles L. Dorian0f8f5d22012-09-17 17:18:16 -040075 const MAXLOG = 8.8029691931113054295988e+01 // log(2**127)
76 z := Abs(x)
77 switch {
78 case z > 0.5*MAXLOG:
79 if x < 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -080080 return -1
Ken Thompson21810982008-03-28 13:56:47 -070081 }
Robert Griesemer40621d52009-11-09 12:07:39 -080082 return 1
Charles L. Dorian0f8f5d22012-09-17 17:18:16 -040083 case z >= 0.625:
84 s := Exp(2 * z)
85 z = 1 - 2/(s+1)
86 if x < 0 {
87 z = -z
88 }
89 default:
90 if x == 0 {
91 return x
92 }
93 s := x * x
94 z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2])
Ken Thompson21810982008-03-28 13:56:47 -070095 }
Charles L. Dorian0f8f5d22012-09-17 17:18:16 -040096 return z
Ken Thompson21810982008-03-28 13:56:47 -070097}