Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 1 | // 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 Pike | 4331293 | 2008-06-27 17:06:23 -0700 | [diff] [blame] | 5 | package math |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 6 | |
Charles L. Dorian | 0f8f5d2 | 2012-09-17 17:18:16 -0400 | [diff] [blame] | 7 | // 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 Pike | 00e2cda | 2010-01-12 07:38:31 +1100 | [diff] [blame] | 56 | |
Charles L. Dorian | 0f8f5d2 | 2012-09-17 17:18:16 -0400 | [diff] [blame] | 57 | var tanhP = [...]float64{ |
| 58 | -9.64399179425052238628E-1, |
| 59 | -9.92877231001918586564E1, |
| 60 | -1.61468768441708447952E3, |
| 61 | } |
| 62 | var tanhQ = [...]float64{ |
| 63 | 1.12811678491632931402E2, |
| 64 | 2.23548839060100448583E3, |
| 65 | 4.84406305325125486048E3, |
| 66 | } |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 67 | |
Oling Cat | 1693e14 | 2013-03-25 08:43:51 -0700 | [diff] [blame] | 68 | // Tanh returns the hyperbolic tangent of x. |
Charles L. Dorian | abc7df9 | 2011-12-05 14:01:24 -0500 | [diff] [blame] | 69 | // |
| 70 | // Special cases are: |
| 71 | // Tanh(±0) = ±0 |
| 72 | // Tanh(±Inf) = ±1 |
| 73 | // Tanh(NaN) = NaN |
Russ Cox | dfc3910 | 2009-03-05 13:31:01 -0800 | [diff] [blame] | 74 | func Tanh(x float64) float64 { |
Charles L. Dorian | 0f8f5d2 | 2012-09-17 17:18:16 -0400 | [diff] [blame] | 75 | 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 Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 80 | return -1 |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 81 | } |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 82 | return 1 |
Charles L. Dorian | 0f8f5d2 | 2012-09-17 17:18:16 -0400 | [diff] [blame] | 83 | 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 Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 95 | } |
Charles L. Dorian | 0f8f5d2 | 2012-09-17 17:18:16 -0400 | [diff] [blame] | 96 | return z |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 97 | } |