[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
This patch adds the sincos optimization on i386 which was discussed several
times on the list. However, it only adds it for GCC-based platforms because
GCC is the only compiler to feature a powerful enough inline assembly syntax
so as to guarantee that it is really an optimization in all cases.
The GCC syntax is
__asm__ ("fsincos" : "=t" (cosinus), "=u" (sinus) : "0" (angle))
so the compiler knows that the cosinus is in st(0) and the sinus in st(1)
after the calculation.
With Watcom C, the best solution is
double al_sincos(double x, double *c);
#pragma aux al_sincos = \
" fsincos " \
" fstp qword ptr [eax] " \
\
parm [8087] [eax] \
value [8087];
so we need to unconditionally spill the cosinus to memory, which may loose in
some cases.
With MSVC, I think the best solution is
double al_sincos(double x, double *c)
{
_asm {
fld x
fsincos
mov eax c
fstp qword ptr [eax]
}
}
so we need to unconditionally spill the cosinus too.
Applied to mainline.
--
Eric Botcazou
Index: todo.txt
===================================================================
RCS file: /cvsroot/alleg/allegro/todo.txt,v
retrieving revision 1.172
diff -u -p -r1.172 todo.txt
--- todo.txt 4 Dec 2003 06:36:54 -0000 1.172
+++ todo.txt 14 Dec 2003 18:18:39 -0000
@@ -13,7 +13,6 @@ General (Platform independent) todos:
- make the library thread-safe
- fix use of 32-bit 'long' on 64-bit platforms
- add set_harware_volume()
-- add asm/C sincos() internal routine
- don't use BITMAPs for zbuffers
- make the 'save' method of plugins return FALSE on failure
Index: include/allegro/internal/alconfig.h
===================================================================
RCS file: /cvsroot/alleg/allegro/include/allegro/internal/alconfig.h,v
retrieving revision 1.14
diff -u -p -r1.14 alconfig.h
--- include/allegro/internal/alconfig.h 14 Jun 2003 09:48:06 -0000 1.14
+++ include/allegro/internal/alconfig.h 14 Dec 2003 18:18:41 -0000
@@ -105,6 +105,7 @@
#ifdef __i386__
#define ALLEGRO_I386
+ #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x))
#endif
#ifndef AL_CONST
@@ -132,6 +133,10 @@
* features and helper functions, which are conditionalised so they will
* only be included if none of the above headers defined custom versions.
*/
+
+#ifndef _AL_SINCOS
+ #define _AL_SINCOS(x, s, c) do { (c) = cos(x); (s) = sin(x); } while (0)
+#endif
#ifndef INLINE
#define INLINE
Index: src/math3d.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/math3d.c,v
retrieving revision 1.7
diff -u -p -r1.7 math3d.c
--- src/math3d.c 12 Sep 2002 16:23:57 -0000 1.7
+++ src/math3d.c 14 Dec 2003 18:18:44 -0000
@@ -22,9 +22,8 @@
-#define floatcos(x) cos((x) * AL_PI / 128.0)
-#define floatsin(x) sin((x) * AL_PI / 128.0)
-#define floattan(x) tan((x) * AL_PI / 128.0)
+#define FLOATSINCOS(x, s, c) _AL_SINCOS((x) * AL_PI / 128.0, s ,c)
+#define floattan(x) tan((x) * AL_PI / 128.0)
@@ -147,10 +146,10 @@ void get_x_rotate_matrix(MATRIX *m, fixe
*/
void get_x_rotate_matrix_f(MATRIX_f *m, float r)
{
- float c = floatcos(r);
- float s = floatsin(r);
+ float c, s;
ASSERT(m);
+ FLOATSINCOS(r, s, c);
*m = identity_matrix_f;
m->v[1][1] = c;
@@ -189,10 +188,10 @@ void get_y_rotate_matrix(MATRIX *m, fixe
*/
void get_y_rotate_matrix_f(MATRIX_f *m, float r)
{
- float c = floatcos(r);
- float s = floatsin(r);
+ float c, s;
ASSERT(m);
+ FLOATSINCOS(r, s, c);
*m = identity_matrix_f;
m->v[0][0] = c;
@@ -231,10 +230,10 @@ void get_z_rotate_matrix(MATRIX *m, fixe
*/
void get_z_rotate_matrix_f(MATRIX_f *m, float r)
{
- float c = floatcos(r);
- float s = floatsin(r);
+ float c, s;
ASSERT(m);
+ FLOATSINCOS(r, s, c);
*m = identity_matrix_f;
m->v[0][0] = c;
@@ -263,17 +262,17 @@ void get_z_rotate_matrix_f(MATRIX_f *m,
#define MAKE_ROTATION_f(x, y, z) \
- float sin_x = floatsin(x); \
- float cos_x = floatcos(x); \
+ float sin_x, cos_x; \
+ float sin_y, cos_y; \
+ float sin_z, cos_z; \
+ float sinx_siny, cosx_siny; \
\
- float sin_y = floatsin(y); \
- float cos_y = floatcos(y); \
+ FLOATSINCOS(x, sin_x, cos_x); \
+ FLOATSINCOS(y, sin_y, cos_y); \
+ FLOATSINCOS(z, sin_z, cos_z); \
\
- float sin_z = floatsin(z); \
- float cos_z = floatcos(z); \
- \
- float sinx_siny = sin_x * sin_y; \
- float cosx_siny = cos_x * sin_y;
+ sinx_siny = sin_x * sin_y; \
+ cosx_siny = cos_x * sin_y;
@@ -446,11 +445,11 @@ void get_vector_rotation_matrix(MATRIX *
*/
void get_vector_rotation_matrix_f(MATRIX_f *m, float x, float y, float z, float a)
{
- float c = floatcos(a);
- float s = floatsin(a);
- float cc = 1 - c;
+ float c, s, cc;
ASSERT(m);
+ FLOATSINCOS(a, s, c);
+ cc = 1 - c;
normalize_vector_f(&x, &y, &z);
m->v[0][0] = (cc * x * x) + c;
Index: src/quat.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/quat.c,v
retrieving revision 1.7
diff -u -p -r1.7 quat.c
--- src/quat.c 18 Sep 2003 08:31:36 -0000 1.7
+++ src/quat.c 14 Dec 2003 18:18:44 -0000
@@ -22,8 +22,7 @@
-#define floatcos(x) ((float)(cos((x) * AL_PI / 128.0)))
-#define floatsin(x) ((float)(sin((x) * AL_PI / 128.0)))
+#define FLOATSINCOS(x, s, c) _AL_SINCOS((x) * AL_PI / 128.0, s ,c)
#define EPSILON (0.001)
@@ -95,8 +94,7 @@ void get_x_rotate_quat(QUAT *q, float r)
{
ASSERT(q);
- q->w = floatcos(r / 2);
- q->x = floatsin(r / 2);
+ FLOATSINCOS(r/2, q->x, q->w);
q->y = 0;
q->z = 0;
}
@@ -112,9 +110,8 @@ void get_y_rotate_quat(QUAT *q, float r)
{
ASSERT(q);
- q->w = floatcos(r / 2);
+ FLOATSINCOS(r/2, q->y, q->w);
q->x = 0;
- q->y = floatsin(r / 2);
q->z = 0;
}
@@ -129,10 +126,9 @@ void get_z_rotate_quat(QUAT *q, float r)
{
ASSERT(q);
- q->w = floatcos(r / 2);
+ FLOATSINCOS(r/2, q->z, q->w);
q->x = 0;
q->y = 0;
- q->z = floatsin(r / 2);
}
@@ -154,12 +150,9 @@ void get_rotation_quat(QUAT *q, float x,
ASSERT(q);
- sx = floatsin(x / 2);
- sy = floatsin(y / 2);
- sz = floatsin(z / 2);
- cx = floatcos(x / 2);
- cy = floatcos(y / 2);
- cz = floatcos(z / 2);
+ FLOATSINCOS(x/2, sx, cx);
+ FLOATSINCOS(y/2, sy, cy);
+ FLOATSINCOS(z/2, sz, cz);
sysz = sy * sz;
cycz = cy * cz;
@@ -196,8 +189,7 @@ void get_vector_rotation_quat(QUAT *q, f
y /= l;
z /= l;
- q->w = floatcos(a / 2);
- s = floatsin(a / 2);
+ FLOATSINCOS(a/2, s, q->w);
q->x = s * x;
q->y = s * y;
q->z = s * z;
Index: src/rotate.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/rotate.c,v
retrieving revision 1.17
diff -u -p -r1.17 rotate.c
--- src/rotate.c 14 Dec 2003 15:29:38 -0000 1.17
+++ src/rotate.c 14 Dec 2003 18:18:46 -0000
@@ -718,8 +718,7 @@ void _rotate_scale_flip_coordinates(fixe
if (angle >= 0x800000)
angle -= 0x1000000;
- cos_angle = cos(angle * (AL_PI / (double)0x800000));
- sin_angle = sin(angle * (AL_PI / (double)0x800000));
+ _AL_SINCOS(angle * (AL_PI / (double)0x800000), sin_angle, cos_angle);
if (cos_angle >= 0)
fix_cos = (int)(cos_angle * 0x10000 + 0.5);