Added SDL_sqrtf(), SDL_tan(), SDL_tanf()
authorSam Lantinga <slouken@libsdl.org>
Sat, 07 Jun 2014 18:20:01 -0700
changeset 8840 9b6ddcbdea65
parent 8839 5ba49d7a39a0
child 8841 b7f41b4a7929
Added SDL_sqrtf(), SDL_tan(), SDL_tanf()
configure
configure.in
include/SDL_config.h.cmake
include/SDL_config.h.in
include/SDL_config_android.h
include/SDL_config_iphoneos.h
include/SDL_config_macosx.h
include/SDL_config_pandora.h
include/SDL_config_psp.h
include/SDL_config_windows.h
include/SDL_config_winrt.h
include/SDL_config_wiz.h
include/SDL_stdinc.h
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
src/libm/k_tan.c
src/libm/math_libm.h
src/libm/math_private.h
src/libm/s_tan.c
src/stdlib/SDL_stdlib.c
--- a/configure	Sat Jun 07 17:31:50 2014 -0700
+++ b/configure	Sat Jun 07 18:20:01 2014 -0700
@@ -16639,7 +16639,7 @@
   LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"
 fi
 
-    for ac_func in atan atan2 acos asin ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt
+    for ac_func in atan atan2 acos asin ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt tan tanf
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
--- a/configure.in	Sat Jun 07 17:31:50 2014 -0700
+++ b/configure.in	Sat Jun 07 18:20:01 2014 -0700
@@ -271,7 +271,7 @@
     AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp vsscanf vsnprintf fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname)
 
     AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
-    AC_CHECK_FUNCS(atan atan2 acos asin ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt)
+    AC_CHECK_FUNCS(atan atan2 acos asin ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt tan tanf)
 
     AC_CHECK_LIB(iconv, iconv_open, [LIBS="$LIBS -liconv"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -liconv"])
     AC_CHECK_FUNCS(iconv)
--- a/include/SDL_config.h.cmake	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config.h.cmake	Sat Jun 07 18:20:01 2014 -0700
@@ -145,6 +145,9 @@
 #cmakedefine HAVE_SIN 1
 #cmakedefine HAVE_SINF 1
 #cmakedefine HAVE_SQRT 1
+#cmakedefine HAVE_SQRTF 1
+#cmakedefine HAVE_TAN 1
+#cmakedefine HAVE_TANF 1
 #cmakedefine HAVE_FSEEKO 1
 #cmakedefine HAVE_FSEEKO64 1
 #cmakedefine HAVE_SIGACTION 1
--- a/include/SDL_config.h.in	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config.h.in	Sat Jun 07 18:20:01 2014 -0700
@@ -150,6 +150,9 @@
 #undef HAVE_SIN
 #undef HAVE_SINF
 #undef HAVE_SQRT
+#undef HAVE_SQRTF
+#undef HAVE_TAN
+#undef HAVE_TANF
 #undef HAVE_FSEEKO
 #undef HAVE_FSEEKO64
 #undef HAVE_SIGACTION
--- a/include/SDL_config_android.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_android.h	Sat Jun 07 18:20:01 2014 -0700
@@ -100,6 +100,9 @@
 #define HAVE_SIN    1
 #define HAVE_SINF   1
 #define HAVE_SQRT   1
+#define HAVE_SQRTF  1
+#define HAVE_TAN    1
+#define HAVE_TANF   1
 #define HAVE_SIGACTION  1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP  1
--- a/include/SDL_config_iphoneos.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_iphoneos.h	Sat Jun 07 18:20:01 2014 -0700
@@ -98,6 +98,9 @@
 #define HAVE_SIN    1
 #define HAVE_SINF   1
 #define HAVE_SQRT   1
+#define HAVE_SQRTF  1
+#define HAVE_TAN    1
+#define HAVE_TANF   1
 #define HAVE_SIGACTION  1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP  1
--- a/include/SDL_config_macosx.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_macosx.h	Sat Jun 07 18:20:01 2014 -0700
@@ -96,6 +96,9 @@
 #define HAVE_SIN    1
 #define HAVE_SINF   1
 #define HAVE_SQRT   1
+#define HAVE_SQRTF  1
+#define HAVE_TAN    1
+#define HAVE_TANF   1
 #define HAVE_SIGACTION  1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP  1
--- a/include/SDL_config_pandora.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_pandora.h	Sat Jun 07 18:20:01 2014 -0700
@@ -95,6 +95,9 @@
 #define HAVE_SIN 1
 #define HAVE_SINF 1
 #define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
 #define HAVE_SIGACTION 1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP 1
--- a/include/SDL_config_psp.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_psp.h	Sat Jun 07 18:20:01 2014 -0700
@@ -98,6 +98,9 @@
 #define HAVE_SIN    1
 #define HAVE_SINF   1
 #define HAVE_SQRT   1
+#define HAVE_SQRTF  1
+#define HAVE_TAN    1
+#define HAVE_TANF   1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP  1
 /* #define HAVE_SYSCONF  1 */
--- a/include/SDL_config_windows.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_windows.h	Sat Jun 07 18:20:01 2014 -0700
@@ -132,6 +132,9 @@
 #define HAVE_SIN 1
 #define HAVE_SINF 1
 #define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
 #if _MSC_VER >= 1800
 #define HAVE_STRTOLL 1
 #define HAVE_VSSCANF 1
--- a/include/SDL_config_winrt.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_winrt.h	Sat Jun 07 18:20:01 2014 -0700
@@ -137,6 +137,9 @@
 #define HAVE_SIN 1
 #define HAVE_SINF 1
 #define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
 #define HAVE__FSEEKI64 1
 
 /* Enable various audio drivers */
--- a/include/SDL_config_wiz.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_config_wiz.h	Sat Jun 07 18:20:01 2014 -0700
@@ -89,6 +89,9 @@
 #define HAVE_SIN 1
 #define HAVE_SINF 1
 #define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
 #define HAVE_SIGACTION 1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP 1
--- a/include/SDL_stdinc.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/include/SDL_stdinc.h	Sat Jun 07 18:20:01 2014 -0700
@@ -411,6 +411,9 @@
 extern DECLSPEC double SDLCALL SDL_sin(double x);
 extern DECLSPEC float SDLCALL SDL_sinf(float x);
 extern DECLSPEC double SDLCALL SDL_sqrt(double x);
+extern DECLSPEC float SDLCALL SDL_sqrtf(float x);
+extern DECLSPEC double SDLCALL SDL_tan(double x);
+extern DECLSPEC float SDLCALL SDL_tanf(float x);
 
 /* The SDL implementation of iconv() returns these error codes */
 #define SDL_ICONV_ERROR     (size_t)-1
--- a/src/dynapi/SDL_dynapi_overrides.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/src/dynapi/SDL_dynapi_overrides.h	Sat Jun 07 18:20:01 2014 -0700
@@ -581,3 +581,6 @@
 #define SDL_WinRTGetFSPathUNICODE SDL_WinRTGetFSPathUNICODE_REAL
 #define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL
 #define SDL_WinRTRunApp SDL_WinRTRunApp_REAL
+#define SDL_sqrtf SDL_sqrtf_REAL
+#define SDL_tan SDL_tan_REAL
+#define SDL_tanf SDL_tanf_REAL
--- a/src/dynapi/SDL_dynapi_procs.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/src/dynapi/SDL_dynapi_procs.h	Sat Jun 07 18:20:01 2014 -0700
@@ -613,3 +613,6 @@
 SDL_DYNAPI_PROC(const char*,SDL_WinRTGetFSPathUTF8,(SDL_WinRT_Path a),(a),return)
 #endif
 SDL_DYNAPI_PROC(void,SDL_WarpMouseGlobal,(int a, int b),(a,b),)
+SDL_DYNAPI_PROC(float,SDL_sqrtf,(float a),(a),return)
+SDL_DYNAPI_PROC(double,SDL_tan,(double a),(a),return)
+SDL_DYNAPI_PROC(float,SDL_tanf,(float a),(a),return)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libm/k_tan.c	Sat Jun 07 18:20:01 2014 -0700
@@ -0,0 +1,118 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __kernel_tan( x, y, k )
+ * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k=1) or
+ * -1/tan (if k= -1) is returned.
+ *
+ * Algorithm
+ *	1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ *	2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
+ *	3. tan(x) is approximated by a odd polynomial of degree 27 on
+ *	   [0,0.67434]
+ *		  	         3             27
+ *	   	tan(x) ~ x + T1*x + ... + T13*x
+ *	   where
+ *
+ * 	        |tan(x)         2     4            26   |     -59.2
+ * 	        |----- - (1+T1*x +T2*x +.... +T13*x    )| <= 2
+ * 	        |  x 					|
+ *
+ *	   Note: tan(x+y) = tan(x) + tan'(x)*y
+ *		          ~ tan(x) + (1+x*x)*y
+ *	   Therefore, for better accuracy in computing tan(x+y), let
+ *		     3      2      2       2       2
+ *		r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ *	   then
+ *		 		    3    2
+ *		tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
+ *		tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+
+#include "math_libm.h"
+#include "math_private.h"
+
+static const double
+one   =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pio4  =  7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+pio4lo=  3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
+T[] =  {
+  3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */
+  1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */
+  5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */
+  2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */
+  8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */
+  3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */
+  1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */
+  5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */
+  2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */
+  7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */
+  7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */
+ -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */
+  2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
+};
+
+double __kernel_tan(double x, double y, int iy)
+{
+	double z,r,v,w,s;
+	int32_t ix,hx;
+	GET_HIGH_WORD(hx,x);
+	ix = hx&0x7fffffff;	/* high word of |x| */
+	if(ix<0x3e300000)			/* x < 2**-28 */
+	    {if((int)x==0) {			/* generate inexact */
+	        u_int32_t low;
+		GET_LOW_WORD(low,x);
+		if(((ix|low)|(iy+1))==0) return one/fabs(x);
+		else return (iy==1)? x: -one/x;
+	    }
+	    }
+	if(ix>=0x3FE59428) { 			/* |x|>=0.6744 */
+	    if(hx<0) {x = -x; y = -y;}
+	    z = pio4-x;
+	    w = pio4lo-y;
+	    x = z+w; y = 0.0;
+	}
+	z	=  x*x;
+	w 	=  z*z;
+    /* Break x^5*(T[1]+x^2*T[2]+...) into
+     *	  x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+     *	  x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+     */
+	r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
+	v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
+	s = z*x;
+	r = y + z*(s*(r+v)+y);
+	r += T[0]*s;
+	w = x+r;
+	if(ix>=0x3FE59428) {
+	    v = (double)iy;
+	    return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r)));
+	}
+	if(iy==1) return w;
+	else {		/* if allow error up to 2 ulp,
+			   simply return -1.0/(x+r) here */
+     /*  compute -1.0/(x+r) accurately */
+	    double a,t;
+	    z  = w;
+	    SET_LOW_WORD(z,0);
+	    v  = r-(z - x); 	/* z+v = r+x */
+	    t = a  = -1.0/w;	/* a = -1.0/w */
+	    SET_LOW_WORD(t,0);
+	    s  = 1.0+t*z;
+	    return t+a*(s+t*v);
+	}
+}
--- a/src/libm/math_libm.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/src/libm/math_libm.h	Sat Jun 07 18:20:01 2014 -0700
@@ -33,5 +33,6 @@
 double SDL_uclibc_scalbn(double x, int n);
 double SDL_uclibc_sin(double x);
 double SDL_uclibc_sqrt(double x);
+double SDL_uclibc_tan(double x);
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/libm/math_private.h	Sat Jun 07 17:31:50 2014 -0700
+++ b/src/libm/math_private.h	Sat Jun 07 18:20:01 2014 -0700
@@ -40,6 +40,7 @@
 #define scalbn          SDL_uclibc_scalbn
 #define sin             SDL_uclibc_sin
 #define __ieee754_sqrt  SDL_uclibc_sqrt
+#define tan             SDL_uclibc_tan
 
 /* The original fdlibm code used statements like:
 	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libm/s_tan.c	Sat Jun 07 18:20:01 2014 -0700
@@ -0,0 +1,67 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ *	__kernel_tan		... tangent function on [-pi/4,pi/4]
+ *	__ieee754_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double tan(double x)
+{
+	double y[2],z=0.0;
+	int32_t n, ix;
+
+    /* High word of x. */
+	GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1);
+
+    /* tan(Inf or NaN) is NaN */
+	else if (ix>=0x7ff00000) return x-x;		/* NaN */
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2(x,y);
+	    return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
+							-1 -- n odd */
+	}
+}
+libm_hidden_def(tan)
--- a/src/stdlib/SDL_stdlib.c	Sat Jun 07 17:31:50 2014 -0700
+++ b/src/stdlib/SDL_stdlib.c	Sat Jun 07 18:20:01 2014 -0700
@@ -211,6 +211,36 @@
 #endif
 }
 
+float
+SDL_sqrtf(float x)
+{
+#if defined(HAVE_SQRTF)
+    return sqrtf(x);
+#else
+    return (float)SDL_sqrt((double)x);
+#endif
+}
+
+double
+SDL_tan(double x)
+{
+#if defined(HAVE_TAN)
+    return tan(x);
+#else
+    return SDL_uclibc_tan(x);
+#endif
+}
+
+float
+SDL_tanf(float x)
+{
+#if defined(HAVE_TANF)
+    return tanf(x);
+#else
+    return (float)SDL_tan((double)x);
+#endif
+}
+
 int SDL_abs(int x)
 {
 #ifdef HAVE_ABS