Commit 6101e4b20e9a2c9f01e7b07d0f189478e94c818b

Sam Lantinga 2014-06-07T18:20:01

Added SDL_sqrtf(), SDL_tan(), SDL_tanf()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
diff --git a/configure b/configure
index 58cbd75..4ce1163 100755
--- a/configure
+++ b/configure
@@ -16639,7 +16639,7 @@ if test "x$ac_cv_lib_m_pow" = xyes; then :
   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"
diff --git a/configure.in b/configure.in
index 40b9688..2604fa2 100644
--- a/configure.in
+++ b/configure.in
@@ -271,7 +271,7 @@ if test x$enable_libc = xyes; then
     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)
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
index 9b39422..2c9ce6c 100644
--- a/include/SDL_config.h.cmake
+++ b/include/SDL_config.h.cmake
@@ -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
diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in
index 5f1d0db..53ecfcb 100644
--- a/include/SDL_config.h.in
+++ b/include/SDL_config.h.in
@@ -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
diff --git a/include/SDL_config_android.h b/include/SDL_config_android.h
index 738dd94..7310601 100644
--- a/include/SDL_config_android.h
+++ b/include/SDL_config_android.h
@@ -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
diff --git a/include/SDL_config_iphoneos.h b/include/SDL_config_iphoneos.h
index a0f55b6..8b268b7 100644
--- a/include/SDL_config_iphoneos.h
+++ b/include/SDL_config_iphoneos.h
@@ -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
diff --git a/include/SDL_config_macosx.h b/include/SDL_config_macosx.h
index e627aef..b6af492 100644
--- a/include/SDL_config_macosx.h
+++ b/include/SDL_config_macosx.h
@@ -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
diff --git a/include/SDL_config_pandora.h b/include/SDL_config_pandora.h
index ac8b085..aead1ff 100644
--- a/include/SDL_config_pandora.h
+++ b/include/SDL_config_pandora.h
@@ -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
diff --git a/include/SDL_config_psp.h b/include/SDL_config_psp.h
index 2f9d023..617d691 100644
--- a/include/SDL_config_psp.h
+++ b/include/SDL_config_psp.h
@@ -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 */
diff --git a/include/SDL_config_windows.h b/include/SDL_config_windows.h
index 1157270..29e5a47 100644
--- a/include/SDL_config_windows.h
+++ b/include/SDL_config_windows.h
@@ -132,6 +132,9 @@ typedef unsigned int uintptr_t;
 #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
diff --git a/include/SDL_config_winrt.h b/include/SDL_config_winrt.h
index 48d44ee..97c5140 100644
--- a/include/SDL_config_winrt.h
+++ b/include/SDL_config_winrt.h
@@ -137,6 +137,9 @@ typedef unsigned int uintptr_t;
 #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 */
diff --git a/include/SDL_config_wiz.h b/include/SDL_config_wiz.h
index 7efc20b..9204567 100644
--- a/include/SDL_config_wiz.h
+++ b/include/SDL_config_wiz.h
@@ -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
diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h
index 9c79ca5..1b470ce 100644
--- a/include/SDL_stdinc.h
+++ b/include/SDL_stdinc.h
@@ -411,6 +411,9 @@ extern DECLSPEC double SDLCALL SDL_scalbn(double x, int n);
 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
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 4b26185..40ae7dd 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -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
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 44b9fd2..217fcd5 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -613,3 +613,6 @@ SDL_DYNAPI_PROC(const wchar_t*,SDL_WinRTGetFSPathUNICODE,(SDL_WinRT_Path a),(a),
 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)
diff --git a/src/libm/k_tan.c b/src/libm/k_tan.c
new file mode 100644
index 0000000..27e6639
--- /dev/null
+++ b/src/libm/k_tan.c
@@ -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);
+	}
+}
diff --git a/src/libm/math_libm.h b/src/libm/math_libm.h
index 20432bd..6b479f4 100644
--- a/src/libm/math_libm.h
+++ b/src/libm/math_libm.h
@@ -33,5 +33,6 @@ double SDL_uclibc_pow(double x, double y);
 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: */
diff --git a/src/libm/math_private.h b/src/libm/math_private.h
index 6ab0f35..74c8b3d 100644
--- a/src/libm/math_private.h
+++ b/src/libm/math_private.h
@@ -40,6 +40,7 @@ typedef unsigned int u_int32_t;
 #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 *
diff --git a/src/libm/s_tan.c b/src/libm/s_tan.c
new file mode 100644
index 0000000..5a2bc93
--- /dev/null
+++ b/src/libm/s_tan.c
@@ -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)
diff --git a/src/stdlib/SDL_stdlib.c b/src/stdlib/SDL_stdlib.c
index 11f778a..c5f5e9d 100644
--- a/src/stdlib/SDL_stdlib.c
+++ b/src/stdlib/SDL_stdlib.c
@@ -211,6 +211,36 @@ SDL_sqrt(double x)
 #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