Using sincos (was Re: [cairo] Questions and optimizations in
cairo-arc)
Behdad Esfahbod
behdad at cs.toronto.edu
Tue Jul 26 17:20:12 PDT 2005
> > Please feel free to put a patch together for this change alone, (along
> > with the necessary configure magic to define HAVE_SINCOS
> > appropriately).
Infact the check for sincos was already in configure and in one
place in the code it was conditionally used. The attached patch
defines a macro named _cairo_sincos and uses it all over the
code. (not that many places really)
I had to introduce AC_GNU_SOURCE in configure.in, as sincos is
not declared in math.h unless __USE_GNU is defined... But we do
want to use GNU extensions, so AC_GNU_SOURCE should be harmless.
--behdad
http://behdad.org/
-------------- next part --------------
Index: configure.in
===================================================================
RCS file: /cvs/cairo/cairo/configure.in,v
retrieving revision 1.111
diff -u -p -r1.111 configure.in
--- configure.in 18 Jul 2005 18:51:42 -0000 1.111
+++ configure.in 27 Jul 2005 00:19:11 -0000
@@ -31,20 +31,19 @@ AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
+AC_GNU_SOURCE
AC_PROG_CC
AC_PROG_CPP
AM_PROG_LIBTOOL
AC_STDC_HEADERS
AC_C_BIGENDIAN
-AC_CHECK_FUNCS(vasnprintf)
-
+AC_CHECK_FUNCS(vasnprintf, sincos)
+
AC_CHECK_LIBM
LIBS="$LIBS $LIBM"
-AC_CHECK_FUNCS(sincos)
-
dnl ===========================================================================
AC_ARG_ENABLE(xlib,
Index: src/cairo-arc.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-arc.c,v
retrieving revision 1.3
diff -u -p -r1.3 cairo-arc.c
--- src/cairo-arc.c 11 Jul 2005 20:29:46 -0000 1.3
+++ src/cairo-arc.c 27 Jul 2005 00:19:11 -0000
@@ -61,7 +61,10 @@
static double
_arc_error_normalized (double angle)
{
- return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
+ double sin_, cos_;
+
+ _cairo_sincos (angle / 4, &sin_, &cos_);
+ return 2.0/27.0 * pow (sin_, 6) / pow (cos_, 2);
}
static double
@@ -164,10 +167,12 @@ _cairo_arc_segment (cairo_t *cr,
double r_sin_B, r_cos_B;
double h;
- r_sin_A = radius * sin (angle_A);
- r_cos_A = radius * cos (angle_A);
- r_sin_B = radius * sin (angle_B);
- r_cos_B = radius * cos (angle_B);
+ _cairo_sincos (angle_A, &r_sin_A, &r_cos_A);
+ _cairo_sincos (angle_B, &r_sin_B, &r_cos_B);
+ r_sin_A *= radius;
+ r_cos_A *= radius;
+ r_sin_B *= radius;
+ r_cos_B *= radius;
h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
Index: src/cairo-matrix.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-matrix.c,v
retrieving revision 1.29
diff -u -p -r1.29 cairo-matrix.c
--- src/cairo-matrix.c 20 Jun 2005 19:54:15 -0000 1.29
+++ src/cairo-matrix.c 27 Jul 2005 00:19:11 -0000
@@ -227,17 +227,12 @@ void
cairo_matrix_init_rotate (cairo_matrix_t *matrix,
double radians)
{
- double s;
- double c;
-#if HAVE_SINCOS
- sincos (radians, &s, &c);
-#else
- s = sin (radians);
- c = cos (radians);
-#endif
+ double sin_, cos_;
+
+ _cairo_sincos (radians, &sin_, &cos_);
cairo_matrix_init (matrix,
- c, s,
- -s, c,
+ cos_, sin_,
+ -sin_, cos_,
0, 0);
}
slim_hidden_def(cairo_matrix_init_rotate);
Index: src/cairo-pattern.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-pattern.c,v
retrieving revision 1.50
diff -u -p -r1.50 cairo-pattern.c
--- src/cairo-pattern.c 14 Jul 2005 22:47:18 -0000 1.50
+++ src/cairo-pattern.c 27 Jul 2005 00:19:12 -0000
@@ -1100,6 +1100,8 @@ _cairo_image_data_set_radial (cairo_radi
denumerator = -2.0 * c0_e * c0_c1;
if (denumerator != 0.0) {
+ double sin_, cos_;
+
fraction = (c1_e * c1_e - c0_e * c0_e - c0_c1 * c0_c1) /
denumerator;
@@ -1110,8 +1112,9 @@ _cairo_image_data_set_radial (cairo_radi
angle_c0 = acos (fraction);
- c0_y = cos (angle_c0) * c0_c1;
- c1_y = sin (angle_c0) * c0_c1;
+ _cairo_sincos (angle_c0, &sin_, &cos_);
+ c0_y = cos_ * c0_c1;
+ c1_y = sin_ * c0_c1;
y_x = sqrt (r1_2 - c1_y * c1_y);
c0_x = y_x + c0_y;
Index: src/cairo-pen.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-pen.c,v
retrieving revision 1.23
diff -u -p -r1.23 cairo-pen.c
--- src/cairo-pen.c 7 Apr 2005 17:01:49 -0000 1.23
+++ src/cairo-pen.c 27 Jul 2005 00:19:12 -0000
@@ -102,8 +102,11 @@ _cairo_pen_init (cairo_pen_t *pen, doubl
*/
for (i=0; i < pen->num_vertices; i++) {
double theta = 2 * M_PI * i / (double) pen->num_vertices;
- double dx = radius * cos (reflect ? -theta : theta);
- double dy = radius * sin (reflect ? -theta : theta);
+ double dx, dy;
+
+ _cairo_sincos (reflect ? -theta : theta, &dx, &dy);
+ dx *= radius;
+ dy *= radius;
cairo_pen_vertex_t *v = &pen->vertices[i];
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
v->point.x = _cairo_fixed_from_double (dx);
Index: src/cairo.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.c,v
retrieving revision 1.114
diff -u -p -r1.114 cairo.c
--- src/cairo.c 25 Jul 2005 19:29:24 -0000 1.114
+++ src/cairo.c 27 Jul 2005 00:19:12 -0000
@@ -1013,6 +1013,8 @@ cairo_arc (cairo_t *cr,
double radius,
double angle1, double angle2)
{
+ double sin_, cos_;
+
if (cr->status) {
_cairo_error (cr, cr->status);
return;
@@ -1025,9 +1027,11 @@ cairo_arc (cairo_t *cr,
while (angle2 < angle1)
angle2 += 2 * M_PI;
+ _cairo_sincos (angle1, &sin_, &cos_);
+
cairo_line_to (cr,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
+ xc + radius * cos_,
+ yc + radius * sin_);
_cairo_arc_path (cr, xc, yc, radius,
angle1, angle2);
@@ -1053,6 +1057,8 @@ cairo_arc_negative (cairo_t *cr,
double radius,
double angle1, double angle2)
{
+ double sin_, cos_;
+
if (cr->status) {
_cairo_error (cr, cr->status);
return;
@@ -1065,9 +1071,11 @@ cairo_arc_negative (cairo_t *cr,
while (angle2 > angle1)
angle2 -= 2 * M_PI;
+ _cairo_sincos (angle1, &sin_, &cos_);
+
cairo_line_to (cr,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
+ xc + radius * cos_,
+ yc + radius * sin_);
_cairo_arc_path_negative (cr, xc, yc, radius,
angle1, angle2);
Index: src/cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.169
diff -u -p -r1.169 cairoint.h
--- src/cairoint.h 25 Jul 2005 23:23:05 -0000 1.169
+++ src/cairoint.h 27 Jul 2005 00:19:13 -0000
@@ -65,6 +65,16 @@
#include "cairo.h"
#include <pixman.h>
+#if HAVE_SINCOS
+# define _cairo_sincos(angle,s,c) sincos((angle), (s), (c))
+#else
+# define _cairo_sincos(angle,s,c) do { \
+ double _sincos_angle = (angle); \
+ *(s) = sin(_sincos_angle); \
+ *(c) = cos(_sincos_angle); \
+ } while (0)
+#endif
+
#if __GNUC__ >= 3 && defined(__ELF__)
# define slim_hidden_proto(name) slim_hidden_proto1(name, INT_##name)
# define slim_hidden_def(name) slim_hidden_def1(name, INT_##name)
More information about the cairo
mailing list