From efafb640b70a87b1ec2a5c684d7f05e71abd7813 Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Tue, 11 Oct 2011 22:01:47 +0000
Subject: [PATCH] core: implement tan() for real numbers.

---
 src/real.cpp | 24 ++++++++++++++++++++++++
 src/real.h   |  1 +
 2 files changed, 25 insertions(+)

diff --git a/src/real.cpp b/src/real.cpp
index b6427317..1bc90c0d 100644
--- a/src/real.cpp
+++ b/src/real.cpp
@@ -746,6 +746,30 @@ real cos(real const &x)
     return sin(real::R_PI_2 - x);
 }
 
+real tan(real const &x)
+{
+    /* Constrain input to [-π,π] */
+    real y = fmod(x, real::R_PI);
+
+    /* Constrain input to [-π/2,π/2] */
+    if (y < -real::R_PI_2)
+        y += real::R_PI;
+    else if (y > real::R_PI_2)
+        y -= real::R_PI;
+
+    /* In [-π/4,π/4] return sin/cos */
+    if (fabs(y) <= real::R_PI_4)
+        return sin(y) / cos(y);
+
+    /* Otherwise, return cos/sin */
+    if (y > real::R_0)
+        y = real::R_PI_2 - y;
+    else
+        y = -real::R_PI_2 - y;
+
+    return cos(y) / sin(y);
+}
+
 static real asinacos(real const &x, bool is_asin, bool is_negative)
 {
     /* Strategy for asin(): in [-0.5..0.5], use a Taylor series around
diff --git a/src/real.h b/src/real.h
index e4fab283..529063a4 100644
--- a/src/real.h
+++ b/src/real.h
@@ -76,6 +76,7 @@ public:
 
     friend real sin(real const &x);
     friend real cos(real const &x);
+    friend real tan(real const &x);
     friend real asin(real const &x);
     friend real acos(real const &x);
     friend real atan(real const &x);