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 | |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 7 | /* |
Rob Pike | 00e2cda | 2010-01-12 07:38:31 +1100 | [diff] [blame] | 8 | Floating-point arctangent. |
Rob Pike | 00e2cda | 2010-01-12 07:38:31 +1100 | [diff] [blame] | 9 | */ |
| 10 | |
Charles L. Dorian | 35c3afd | 2012-06-24 19:39:07 -0400 | [diff] [blame] | 11 | // The original C code, the long comment, and the constants below were |
| 12 | // from http://netlib.sandia.gov/cephes/cmath/atan.c, available from |
| 13 | // http://www.netlib.org/cephes/cmath.tgz. |
| 14 | // The go code is a version of the original C. |
| 15 | // |
| 16 | // atan.c |
| 17 | // Inverse circular tangent (arctangent) |
| 18 | // |
| 19 | // SYNOPSIS: |
| 20 | // double x, y, atan(); |
| 21 | // y = atan( x ); |
| 22 | // |
| 23 | // DESCRIPTION: |
| 24 | // Returns radian angle between -pi/2 and +pi/2 whose tangent is x. |
| 25 | // |
| 26 | // Range reduction is from three intervals into the interval from zero to 0.66. |
| 27 | // The approximant uses a rational function of degree 4/5 of the form |
| 28 | // x + x**3 P(x)/Q(x). |
| 29 | // |
| 30 | // ACCURACY: |
| 31 | // Relative error: |
| 32 | // arithmetic domain # trials peak rms |
| 33 | // DEC -10, 10 50000 2.4e-17 8.3e-18 |
| 34 | // IEEE -10, 10 10^6 1.8e-16 5.0e-17 |
| 35 | // |
| 36 | // Cephes Math Library Release 2.8: June, 2000 |
| 37 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier |
| 38 | // |
| 39 | // The readme file at http://netlib.sandia.gov/cephes/ says: |
| 40 | // Some software in this archive may be from the book _Methods and |
| 41 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster |
| 42 | // International, 1989) or from the Cephes Mathematical Library, a |
| 43 | // commercial product. In either event, it is copyrighted by the author. |
| 44 | // What you see here may be used freely but it comes with no support or |
| 45 | // guarantee. |
| 46 | // |
| 47 | // The two known misprints in the book are repaired here in the |
| 48 | // source listings for the gamma function and the incomplete beta |
| 49 | // integral. |
| 50 | // |
| 51 | // Stephen L. Moshier |
| 52 | // moshier@na-net.ornl.gov |
| 53 | |
| 54 | // xatan evaluates a series valid in the range [0, 0.66]. |
| 55 | func xatan(x float64) float64 { |
Russ Cox | 2c5ec1e | 2009-10-06 19:40:35 -0700 | [diff] [blame] | 56 | const ( |
Charles L. Dorian | 35c3afd | 2012-06-24 19:39:07 -0400 | [diff] [blame] | 57 | P0 = -8.750608600031904122785e-01 |
| 58 | P1 = -1.615753718733365076637e+01 |
| 59 | P2 = -7.500855792314704667340e+01 |
| 60 | P3 = -1.228866684490136173410e+02 |
| 61 | P4 = -6.485021904942025371773e+01 |
| 62 | Q0 = +2.485846490142306297962e+01 |
| 63 | Q1 = +1.650270098316988542046e+02 |
| 64 | Q2 = +4.328810604912902668951e+02 |
| 65 | Q3 = +4.853903996359136964868e+02 |
| 66 | Q4 = +1.945506571482613964425e+02 |
Russ Cox | 2c8d9a5 | 2009-01-15 19:11:32 -0800 | [diff] [blame] | 67 | ) |
Charles L. Dorian | 35c3afd | 2012-06-24 19:39:07 -0400 | [diff] [blame] | 68 | z := x * x |
| 69 | z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4) |
| 70 | z = x*z + x |
| 71 | return z |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 72 | } |
| 73 | |
Rob Pike | 00e2cda | 2010-01-12 07:38:31 +1100 | [diff] [blame] | 74 | // satan reduces its argument (known to be positive) |
Charles L. Dorian | 35c3afd | 2012-06-24 19:39:07 -0400 | [diff] [blame] | 75 | // to the range [0, 0.66] and calls xatan. |
| 76 | func satan(x float64) float64 { |
| 77 | const ( |
| 78 | Morebits = 6.123233995736765886130e-17 // pi/2 = PIO2 + Morebits |
| 79 | Tan3pio8 = 2.41421356237309504880 // tan(3*pi/8) |
| 80 | ) |
| 81 | if x <= 0.66 { |
| 82 | return xatan(x) |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 83 | } |
Charles L. Dorian | 35c3afd | 2012-06-24 19:39:07 -0400 | [diff] [blame] | 84 | if x > Tan3pio8 { |
| 85 | return Pi/2 - xatan(1/x) + Morebits |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 86 | } |
Charles L. Dorian | 35c3afd | 2012-06-24 19:39:07 -0400 | [diff] [blame] | 87 | return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 88 | } |
| 89 | |
Rob Pike | 9795882 | 2013-10-07 16:32:47 -0700 | [diff] [blame] | 90 | // Atan returns the arctangent, in radians, of x. |
Charles L. Dorian | 22f84c5 | 2010-04-26 22:44:39 -0700 | [diff] [blame] | 91 | // |
| 92 | // Special cases are: |
Charles L. Dorian | 35c3afd | 2012-06-24 19:39:07 -0400 | [diff] [blame] | 93 | // Atan(±0) = ±0 |
| 94 | // Atan(±Inf) = ±Pi/2 |
Russ Cox | dd8dc6f | 2011-12-13 15:20:12 -0500 | [diff] [blame] | 95 | func Atan(x float64) float64 |
| 96 | |
| 97 | func atan(x float64) float64 { |
Charles L. Dorian | 22f84c5 | 2010-04-26 22:44:39 -0700 | [diff] [blame] | 98 | if x == 0 { |
| 99 | return x |
| 100 | } |
Russ Cox | dfc3910 | 2009-03-05 13:31:01 -0800 | [diff] [blame] | 101 | if x > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 102 | return satan(x) |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 103 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 104 | return -satan(-x) |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 105 | } |