[goffice] Math: add go_sinpi, go_cospi, go_tanpi.



commit 5145c7db37081488a0cacaba35c777581faa628e
Author: Morten Welinder <terra gnome org>
Date:   Wed Dec 18 12:22:03 2013 -0500

    Math: add go_sinpi, go_cospi, go_tanpi.

 ChangeLog              |    5 ++
 NEWS                   |    1 +
 goffice/math/go-math.c |  159 +++++++++++++++++++++++++++++++++++++++++------
 goffice/math/go-math.h |    9 +++
 tests/.gitignore       |    1 +
 tests/Makefile.am      |    7 ++-
 tests/test-math.c      |   51 +++++++++++++++
 tests/test-quad.c      |    3 +
 8 files changed, 213 insertions(+), 23 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 605a227..bb0e01e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-18  Morten Welinder  <terra gnome org>
+
+       * goffice/math/go-math.c (go_sinpi, go_cospi, go_tanpi): New
+       functions.
+
 2013-12-17  Morten Welinder  <terra gnome org>
 
        * goffice/math/go-math.c (go_add_epsilon, go_sub_epsilon): Base
diff --git a/NEWS b/NEWS
index eb1cd54..acaf077 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@ Jean
 Morten:
        * Improve complex math, notably complex power.
        * Add quad precision log, atan2, hypot, asin, acos functions.
+       * Add go_sinpi, go_cospi, and go_tanpi.
 
 --------------------------------------------------------------------------
 goffice 0.10.9:
diff --git a/goffice/math/go-math.c b/goffice/math/go-math.c
index c4545b2..ec9c14f 100644
--- a/goffice/math/go-math.c
+++ b/goffice/math/go-math.c
@@ -30,27 +30,6 @@
 #include <signal.h>
 #include <errno.h>
 
-#if defined (HAVE_IEEEFP_H) || defined (HAVE_IEEE754_H)
-/* Make sure we have this symbol defined, since the existance of either
-   header file implies it.  */
-#ifndef IEEE_754
-#define IEEE_754
-#endif
-#endif
-
-#ifdef HAVE_SUNMATH_H
-#include <sunmath.h>
-#endif
-
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-#ifdef HAVE_IEEE754_H
-#include <ieee754.h>
-#endif
-
-#define ML_UNDERFLOW (GO_EPSILON * GO_EPSILON)
-
 double go_nan;
 double go_pinf;
 double go_ninf;
@@ -923,3 +902,141 @@ go_stern_brocot (double val, int max_denom, int *res_num, int *res_denom)
                *res_denom = bd;
        }
 }
+
+/* ------------------------------------------------------------------------- */
+
+static double
+reduce_half (double x, int *pk)
+{
+       int k = 0;
+
+       if (x < 0) {
+               x = -reduce_half (-x, &k);
+               k = 4 - k;
+               if (x == -0.25)
+                       x += 0.5, k += 3;
+       } else {
+               x = fmod (x, 2);
+               if (x >= 1)
+                       x -= 1, k += 2;
+               if (x >= 0.5)
+                       x -= 0.5, k++;
+               if (x > 0.25)
+                       x -= 0.5, k++;
+       }
+
+       *pk = (k & 3);
+       return x;
+}
+
+static double
+do_sin (double x, int k)
+{
+       double y;
+
+       if (x == 0)
+               y = k & 1;
+       else if (x == 0.25)
+               y = 0.707106781186547524400844362104849039284835937688474036588339;
+       else
+               y = (k & 1) ? cos (M_PI * x) : sin (M_PI * x);
+
+       return (k & 2) ? 0 - y : y;
+}
+
+
+double
+go_sinpi (double x)
+{
+       int k;
+       x = reduce_half (x, &k);
+       return do_sin (x, k);
+}
+
+double
+go_cospi (double x)
+{
+       int k;
+       x = reduce_half (x, &k);
+       return do_sin (x, k + 1);
+}
+
+double
+go_tanpi (double x)
+{
+       int k;
+       x = reduce_half (x, &k);
+       return do_sin (x, k) / do_sin (x, k + 1);
+}
+
+#ifdef GOFFICE_WITH_LONG_DOUBLE
+
+#define M_PIgo    
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117L
+
+static long double
+reduce_halfl (long double x, int *pk)
+{
+       int k = 0;
+
+       if (x < 0) {
+               x = -reduce_halfl (-x, &k);
+               k = 4 - k;
+               if (x == -0.25)
+                       x += 0.5, k += 3;
+       } else {
+               x = fmod (x, 2);
+               if (x >= 1)
+                       x -= 1, k += 2;
+               if (x >= 0.5)
+                       x -= 0.5, k++;
+               if (x > 0.25)
+                       x -= 0.5, k++;
+       }
+
+       *pk = (k & 3);
+       return x;
+}
+
+static long double
+do_sinl (long double x, int k)
+{
+       long double y;
+
+       if (x == 0)
+               y = k & 1;
+       else if (x == 0.25)
+               y = 0.707106781186547524400844362104849039284835937688474036588339L;
+       else
+               y = (k & 1) ? cos (M_PIgo * x) : sin (M_PIgo * x);
+
+       return (k & 2) ? 0 - y : y;
+}
+
+
+long double
+go_sinpil (long double x)
+{
+       int k;
+       x = reduce_halfl (x, &k);
+       return do_sinl (x, k);
+}
+
+long double
+go_cospil (long double x)
+{
+       int k;
+       x = reduce_halfl (x, &k);
+       return do_sinl (x, k + 1);
+}
+
+long double
+go_tanpil (long double x)
+{
+       int k;
+       x = reduce_halfl (x, &k);
+       return do_sinl (x, k) / do_sinl (x, k + 1);
+}
+
+#endif
+
+/* ------------------------------------------------------------------------- */
diff --git a/goffice/math/go-math.h b/goffice/math/go-math.h
index 1e89dea..3d88085 100644
--- a/goffice/math/go-math.h
+++ b/goffice/math/go-math.h
@@ -38,6 +38,11 @@ double go_pow10 (int n);
 
 double go_strtod (const char *s, char **end);
 double go_ascii_strtod (const char *s, char **end);
+
+double go_sinpi (double x);
+double go_cospi (double x);
+double go_tanpi (double x);
+
 /*
  * We provide working versions of these functions for doubles.
  */
@@ -79,6 +84,10 @@ long double go_pow10l (int n);
 long double go_strtold (const char *s, char **end);
 long double go_ascii_strtold (const char *s, char **end);
 
+long double go_sinpil (long double x);
+long double go_cospil (long double x);
+long double go_tanpil (long double x);
+
 /*
  * We provide working versions of these functions for long doubles.
  */
diff --git a/tests/.gitignore b/tests/.gitignore
index 048d6f2..cdb61bd 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -11,4 +11,5 @@ go-demo
 mf-demo
 pie-demo
 shapes-demo
+test-math
 test-quad
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cfee370..9433c51 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,12 +1,12 @@
 if WITH_GTK
-check_PROGRAMS = pie-demo go-demo shapes-demo mf-demo test-quad
+check_PROGRAMS = pie-demo go-demo shapes-demo mf-demo test-quad test-math
 endif
 
 include $(top_srcdir)/goffice.mk
 
 AM_CFLAGS = $(GOFFICE_CFLAGS)
 
-TESTS = test-quad
+TESTS = test-quad test-math
 
 pie_demo_LDADD = $(GOFFICE_PLUGIN_LIBADD)
 pie_demo_SOURCES = pie-demo.c
@@ -23,5 +23,8 @@ mf_demo_SOURCES = mf-demo.c
 test_quad_LDADD = $(GOFFICE_PLUGIN_LIBADD)
 test_quad_SOURCES = test-quad.c
 
+test_math_LDADD = $(GOFFICE_PLUGIN_LIBADD)
+test_math_SOURCES = test-math.c
+
 EXTRA_DIST = go-demo.ui
 
diff --git a/tests/test-math.c b/tests/test-math.c
new file mode 100644
index 0000000..0e93829
--- /dev/null
+++ b/tests/test-math.c
@@ -0,0 +1,51 @@
+#include <goffice/goffice.h>
+
+#define REFTEST(a_,f_,r_, txt_)                                \
+do {                                                   \
+       double a = (a_);                                \
+       double r = (r_);                                \
+       double fa = f_(a);                              \
+       g_printerr ("%s(%g) = %g  [%g]\n",              \
+                   txt_, a, fa, r);                    \
+       if (r == floor (r))                             \
+               g_assert (r == fa);                     \
+       else                                            \
+               g_assert (fabs (r - fa) / r < 1e-14);   \
+} while (0)
+
+
+/* ------------------------------------------------------------------------- */
+
+static double fake_sinpi (double x) { return x == floor (x) ? 0 : sin (x * M_PI); }
+static double fake_cospi (double x) { return fake_sinpi (x + 0.5); }
+
+
+
+#define TEST1(a_) do {                                 \
+       REFTEST(a_,go_sinpi,fake_sinpi(a_),"sinpi");    \
+       REFTEST(a_,go_cospi,fake_cospi(a_),"cospi");    \
+       REFTEST(a_,go_tanpi,(fake_sinpi(a_)/fake_cospi(a_)),"tanpi");   \
+} while (0)
+
+static void
+trig_tests (void)
+{
+       double d;
+
+       for (d = 0; d < 10; d += 0.125) {
+               TEST1(d);
+               TEST1(-d);
+       }
+}
+
+#undef TEST1
+
+/* ------------------------------------------------------------------------- */
+
+int
+main (int argc, char **argv)
+{
+       trig_tests ();
+
+       return 0;
+}
diff --git a/tests/test-quad.c b/tests/test-quad.c
index b4fe2f9..88f8514 100644
--- a/tests/test-quad.c
+++ b/tests/test-quad.c
@@ -100,6 +100,9 @@ atan2_tests (void)
        TEST1 (-3, 0);
        TEST1 (0, 0);
        TEST1 (+1, +1);
+       TEST1 (-1, +1);
+       TEST1 (+1, -1);
+       TEST1 (-1, -1);
        TEST1 (+2.3, +1.2);
        TEST1 (+2.3, -1.2);
        TEST1 (+2.3, +0.2);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]