From 3a09aa24b038be094140ddc86069d0a89eeea5c2 Mon Sep 17 00:00:00 2001
From: Raymond Toy <toy.raymond@gmail.com>
Date: Fri, 22 Nov 2013 20:10:50 -0800
Subject: [PATCH] Darwin doesn't need pi reduction; the C library is accurate
 enough.

o Make %trig call the C routines directly on Darwin/x86.
o Add some extra documentation, and a test case.
---
 src/code/irrat.lisp | 41 +++++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/src/code/irrat.lisp b/src/code/irrat.lisp
index 927a5fbda..5944182ca 100644
--- a/src/code/irrat.lisp
+++ b/src/code/irrat.lisp
@@ -187,14 +187,17 @@
     (%sqrt x))
   )
 
-;;; The standard libm routines for sin, cos, and tan on x86 (Linux)
-;;; and ppc are not very accurate for large arguments when compared to
-;;; sparc (and maxima).  This is basically caused by the fact that
-;;; those libraries do not do an accurate argument reduction.  The
-;;; following functions use some routines Sun's free fdlibm library to
-;;; do accurate reduction.  Then we call the standard C functions (or
-;;; vops for x86) on the reduced argument.  This produces much more
-;;; accurate values.
+;;; The standard libm routines for sin, cos, and tan on x86 (Linux,
+;;; 32-bit.  64-bit is apparently ok) and ppc are not very accurate
+;;; for large arguments when compared to sparc (and maxima).  This is
+;;; basically caused by the fact that those libraries do not do an
+;;; accurate argument reduction.  The following functions use some
+;;; routines Sun's free fdlibm library to do accurate reduction.  Then
+;;; we call the standard C functions (or vops for x86) on the reduced
+;;; argument.  This produces much more accurate values.
+;;;
+;;; You can test this by computing (cos (scale-float 1d0 120)).  The
+;;; true answer is -0.9258790228548379d0.
 
 #+(or ppc x86)
 (progn
@@ -220,7 +223,22 @@
 
 )
 
-#+(or ppc sse2)
+;; If the C library is accurate, use %trig as the Lisp name.
+#-(or ppc (and sse2 (not darwin)))
+(progn
+(declaim (inline %sin %cos %tan))
+(macrolet ((frob (alien-name lisp-name)
+	     `(alien:def-alien-routine (,alien-name ,lisp-name) double-float
+		(x double-float))))
+  (frob "sin" %sin)
+  (frob "cos" %cos)
+  (frob "tan" %tan))
+)
+
+;; Make %%trig be the C library routines that don't do accurate
+;; reduction.  This is for PPC and for any SSE2 build except on
+;; Darwin. Darwin has accurate C library routines.
+#+(or ppc (and sse2 (not darwin)))
 (progn
 (declaim (inline %%sin %%cos %%tan))
 (macrolet ((frob (alien-name lisp-name)
@@ -231,7 +249,10 @@
   (frob "tan" %%tan))
 )
 
-#+(or ppc x86)
+;; When the C library is not accurate, define %trig to do accurate
+;; argument reduction and call the appropriate C function on the
+;; reduced arg.  For x87, we can use the x87 FPU trig instructions.
+#+(or ppc (and x86 (not darwin)))
 (macrolet
     ((frob (sin cos tan)
        `(progn
-- 
GitLab