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 | |
Russ Cox | b4586a7 | 2009-11-17 08:39:56 -0800 | [diff] [blame] | 7 | // Atan2 returns the arc tangent of y/x, using |
Russ Cox | dfc3910 | 2009-03-05 13:31:01 -0800 | [diff] [blame] | 8 | // the signs of the two to determine the quadrant |
| 9 | // of the return value. |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 10 | // |
| 11 | // Special cases are (in order): |
| 12 | // Atan2(y, NaN) = NaN |
| 13 | // Atan2(NaN, x) = NaN |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 14 | // Atan2(+0, x>=0) = +0 |
| 15 | // Atan2(-0, x>=0) = -0 |
| 16 | // Atan2(+0, x<=-0) = +Pi |
| 17 | // Atan2(-0, x<=-0) = -Pi |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 18 | // Atan2(y>0, 0) = +Pi/2 |
| 19 | // Atan2(y<0, 0) = -Pi/2 |
| 20 | // Atan2(+Inf, +Inf) = +Pi/4 |
| 21 | // Atan2(-Inf, +Inf) = -Pi/4 |
| 22 | // Atan2(+Inf, -Inf) = 3Pi/4 |
| 23 | // Atan2(-Inf, -Inf) = -3Pi/4 |
| 24 | // Atan2(y, +Inf) = 0 |
| 25 | // Atan2(y>0, -Inf) = +Pi |
| 26 | // Atan2(y<0, -Inf) = -Pi |
| 27 | // Atan2(+Inf, x) = +Pi/2 |
| 28 | // Atan2(-Inf, x) = -Pi/2 |
Russ Cox | dd8dc6f | 2011-12-13 15:20:12 -0500 | [diff] [blame] | 29 | func Atan2(y, x float64) float64 |
| 30 | |
| 31 | func atan2(y, x float64) float64 { |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 32 | // special cases |
| 33 | switch { |
Luuk van Dijk | 8dd3de4 | 2012-02-01 16:08:31 +0100 | [diff] [blame] | 34 | case IsNaN(y) || IsNaN(x): |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 35 | return NaN() |
| 36 | case y == 0: |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 37 | if x >= 0 && !Signbit(x) { |
| 38 | return Copysign(0, y) |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 39 | } |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 40 | return Copysign(Pi, y) |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 41 | case x == 0: |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 42 | return Copysign(Pi/2, y) |
Luuk van Dijk | 8dd3de4 | 2012-02-01 16:08:31 +0100 | [diff] [blame] | 43 | case IsInf(x, 0): |
| 44 | if IsInf(x, 1) { |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 45 | switch { |
Luuk van Dijk | 8dd3de4 | 2012-02-01 16:08:31 +0100 | [diff] [blame] | 46 | case IsInf(y, 0): |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 47 | return Copysign(Pi/4, y) |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 48 | default: |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 49 | return Copysign(0, y) |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 50 | } |
| 51 | } |
| 52 | switch { |
Luuk van Dijk | 8dd3de4 | 2012-02-01 16:08:31 +0100 | [diff] [blame] | 53 | case IsInf(y, 0): |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 54 | return Copysign(3*Pi/4, y) |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 55 | default: |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 56 | return Copysign(Pi, y) |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 57 | } |
Luuk van Dijk | 8dd3de4 | 2012-02-01 16:08:31 +0100 | [diff] [blame] | 58 | case IsInf(y, 0): |
Charles L. Dorian | 9aa8f95 | 2010-04-08 13:24:04 -0700 | [diff] [blame] | 59 | return Copysign(Pi/2, y) |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 60 | } |
Charles L. Dorian | 072b560 | 2010-02-05 14:55:19 -0800 | [diff] [blame] | 61 | |
| 62 | // Call atan and determine the quadrant. |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 63 | q := Atan(y / x) |
Russ Cox | b4586a7 | 2009-11-17 08:39:56 -0800 | [diff] [blame] | 64 | if x < 0 { |
Russ Cox | dfc3910 | 2009-03-05 13:31:01 -0800 | [diff] [blame] | 65 | if q <= 0 { |
Robert Griesemer | 3bb0032 | 2009-11-09 21:23:52 -0800 | [diff] [blame] | 66 | return q + Pi |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 67 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 68 | return q - Pi |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 69 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 70 | return q |
Ken Thompson | 2181098 | 2008-03-28 13:56:47 -0700 | [diff] [blame] | 71 | } |