[goffice] Quad: sinpi, cospi.



commit 7f65bb4bfbfa6792bd04099c27d14cf44fe03c50
Author: Morten Welinder <terra gnome org>
Date:   Wed Dec 18 20:25:07 2013 -0500

    Quad: sinpi, cospi.

 ChangeLog                 |    5 ++
 NEWS                      |    3 +-
 goffice/math/go-complex.c |   24 +++++++----
 goffice/math/go-quad.c    |  103 +++++++++++++++++++++++++++++++++++++++++++++
 goffice/math/go-quad.h    |    4 ++
 tests/test-quad.c         |    2 +
 6 files changed, 132 insertions(+), 9 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index aad4372..af347bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,13 @@
 2013-12-18  Morten Welinder  <terra gnome org>
 
+       * goffice/math/go-quad.c (go_quad_sin, go_quad_sinpi)
+       (go_quad_asin, go_quad_cos, go_quad_cospi, go_quad_acos): New
+       functions.
+
        * goffice/math/go-complex.c (go_complex_from_polar_pi): Use
        go_sinpi and go_cospi.
        (go_complex_angle_pi): Use go_atan2pi.
+       (go_complex_pow): Improve accuracy.
 
        * goffice/math/go-math.c (go_sinpi, go_cospi, go_tanpi): New
        functions.
diff --git a/NEWS b/NEWS
index 44284a6..afd4ae2 100644
--- a/NEWS
+++ b/NEWS
@@ -8,7 +8,8 @@ Jean
 Morten:
        * Improve complex math, notably complex power.
        * Add quad precision log and hypot functions.
-       * Add quad precision atan2, sin, asin, cos, acos functions.
+       * Add quad precision atan2, sin, sinpi, asin, cos, cospi, acos
+         functions.
        * Add go_sinpi, go_cospi, go_tanpi, go_atan2pi.
 
 --------------------------------------------------------------------------
diff --git a/goffice/math/go-complex.c b/goffice/math/go-complex.c
index d897905..8f8e91b 100644
--- a/goffice/math/go-complex.c
+++ b/goffice/math/go-complex.c
@@ -358,8 +358,9 @@ SUFFIX(go_complex_pow) (COMPLEX *dst, COMPLEX const *a, COMPLEX const *b)
                        SUFFIX(go_complex_div) (dst, &one, &t);
                }
        } else {
-               DOUBLE res_r, res_a, e1, e2;
-               SUFFIX(GOQuad) qr, qa, qb, qarg;
+               DOUBLE e1, e2;
+               int e;
+               SUFFIX(GOQuad) qr, qa, qb, qarg, qrr, qra;
                void *state = SUFFIX(go_quad_start) ();
 
                SUFFIX(go_quad_init) (&qa, a->re);
@@ -373,19 +374,26 @@ SUFFIX(go_complex_pow) (COMPLEX *dst, COMPLEX const *a, COMPLEX const *b)
                SUFFIX(go_quad_mul) (&qb, &qb, &qarg);
                SUFFIX(go_quad_mul) (&qb, &qb, &SUFFIX(go_quad_pi));
                SUFFIX(go_quad_exp) (&qb, &e2, &qb);
-               SUFFIX(go_quad_mul) (&qb, &qa, &qb);
-               res_r = SUFFIX(ldexp) (SUFFIX(go_quad_value) (&qb),
-                                      CLAMP (e1 + e2, G_MININT, G_MAXINT));
+               SUFFIX(go_quad_mul) (&qrr, &qa, &qb);
+               e = CLAMP (e1 + e2, G_MININT, G_MAXINT);
+               qrr.h = SUFFIX(ldexp) (qrr.h, e);
+               qrr.l = SUFFIX(ldexp) (qrr.l, e);
 
                SUFFIX(go_quad_log) (&qa, &qr);
                SUFFIX(go_quad_div) (&qa, &qa, &SUFFIX(go_quad_2pi));
                SUFFIX(mulmod1) (&qa, &qa, b->im);
                SUFFIX(mulmod1) (&qb, &qarg, b->re / 2);
                SUFFIX(go_quad_add) (&qa, &qa, &qb);
-               SUFFIX(go_quad_add) (&qa, &qa, &qa);
-               res_a = SUFFIX(go_quad_value) (&qa);
+               SUFFIX(go_quad_add) (&qra, &qa, &qa);
 
-               SUFFIX(go_complex_from_polar_pi) (dst, res_r, res_a);
+               SUFFIX(go_quad_sinpi) (&qa, &qra);
+               SUFFIX(go_quad_mul) (&qa, &qa, &qrr);
+               SUFFIX(go_quad_cospi) (&qb, &qra);
+               SUFFIX(go_quad_mul) (&qb, &qb, &qrr);
+
+               SUFFIX(go_complex_init) (dst,
+                                        SUFFIX(go_quad_value) (&qb),
+                                        SUFFIX(go_quad_value) (&qa));
 
                SUFFIX(go_quad_end) (state);
        }
diff --git a/goffice/math/go-quad.c b/goffice/math/go-quad.c
index af94e38..0b2f883 100644
--- a/goffice/math/go-quad.c
+++ b/goffice/math/go-quad.c
@@ -1044,6 +1044,52 @@ SUFFIX(reduce_pi_half) (QUAD *res, const QUAD *a, int *pk)
 }
 
 static void
+SUFFIX(reduce_half) (QUAD *res, const QUAD *a, int *pk)
+{
+       static const QUAD half = { 0.5, 0 };
+       int k = 0;
+       QUAD qxr = *a;
+
+       if (a->h < 0) {
+               QUAD aa;
+               aa.h = -a->h; aa.l = -a->l;
+               SUFFIX(reduce_half) (&qxr, &aa, &k);
+               qxr.h = -qxr.h; qxr.l = -qxr.l;
+               k = 4 - k;
+               if (qxr.h <= -0.25 && qxr.l == 0) {
+                       SUFFIX(go_quad_add) (&qxr, &qxr, &half);
+                       k += 3;
+               }
+       } else {
+               QUAD qdx;
+
+               /* Remove integer multiples of 2.  */
+               SUFFIX(go_quad_init) (&qdx, qxr.h - SUFFIX(fmod) (qxr.h, 2));
+               SUFFIX(go_quad_sub) (&qxr, &qxr, &qdx);
+
+               /* Again, just in case it was really big.  */
+               SUFFIX(go_quad_init) (&qdx, qxr.h - SUFFIX(fmod) (qxr.h, 2));
+               SUFFIX(go_quad_sub) (&qxr, &qxr, &qdx);
+
+               if (qxr.h >= 1) {
+                       SUFFIX(go_quad_sub) (&qxr, &qxr, &SUFFIX(go_quad_one));
+                       k += 2;
+               }
+               if (qxr.h >= 0.5) {
+                       SUFFIX(go_quad_sub) (&qxr, &qxr, &half);
+                       k++;
+               }
+               if (qxr.h > 0.25) {
+                       SUFFIX(go_quad_sub) (&qxr, &qxr, &half);
+                       k++;
+               }
+       }
+
+       *pk = (k & 3);
+       *res = qxr;
+}
+
+static void
 SUFFIX(do_sin) (QUAD *res, const QUAD *a, int k)
 {
        QUAD qr;
@@ -1081,6 +1127,31 @@ SUFFIX(do_sin) (QUAD *res, const QUAD *a, int k)
        *res = qr;
 }
 
+static void
+SUFFIX(do_sinpi) (QUAD *res, const QUAD *a, int k)
+{
+       QUAD qr;
+
+       if (a->h == 0)
+               SUFFIX(go_quad_init) (&qr, k & 1);
+       else if (a->h == 0.25 && a->l == 0)
+               SUFFIX(go_quad_div) (&qr,
+                                    &SUFFIX(go_quad_one),
+                                    &SUFFIX(go_quad_sqrt2));
+       else {
+               QUAD api;
+               SUFFIX(go_quad_mul) (&api, a, &SUFFIX(go_quad_pi));
+               SUFFIX(do_sin) (&qr, &api, k & 1);
+       }
+
+       if (k & 2) {
+               qr.h = 0 - qr.h;
+               qr.l = 0 - qr.l;
+       }
+
+       *res = qr;
+}
+
 /**
  * go_quad_sin: (skip)
  **/
@@ -1100,6 +1171,22 @@ SUFFIX(go_quad_sin) (QUAD *res, const QUAD *a)
 }
 
 /**
+ * go_quad_sinpi: (skip)
+ **/
+/**
+ * go_quad_sinpil: (skip)
+ **/
+void
+SUFFIX(go_quad_sinpi) (QUAD *res, const QUAD *a)
+{
+       int k;
+       QUAD a0;
+
+       SUFFIX(reduce_half) (&a0, a, &k);
+       SUFFIX(do_sinpi) (res, &a0, k);
+}
+
+/**
  * go_quad_asin: (skip)
  **/
 /**
@@ -1140,6 +1227,22 @@ SUFFIX(go_quad_cos) (QUAD *res, const QUAD *a)
 }
 
 /**
+ * go_quad_cospi: (skip)
+ **/
+/**
+ * go_quad_cospil: (skip)
+ **/
+void
+SUFFIX(go_quad_cospi) (QUAD *res, const QUAD *a)
+{
+       int k;
+       QUAD a0;
+
+       SUFFIX(reduce_half) (&a0, a, &k);
+       SUFFIX(do_sinpi) (res, &a0, k + 1);
+}
+
+/**
  * go_quad_acos: (skip)
  **/
 /**
diff --git a/goffice/math/go-quad.h b/goffice/math/go-quad.h
index 99a2607..2f7240f 100644
--- a/goffice/math/go-quad.h
+++ b/goffice/math/go-quad.h
@@ -30,8 +30,10 @@ void go_quad_log (GOQuad *res, const GOQuad *a);
 void go_quad_hypot (GOQuad *res, const GOQuad *a, const GOQuad *b);
 
 void go_quad_sin (GOQuad *res, const GOQuad *a);
+void go_quad_sinpi (GOQuad *res, const GOQuad *a);
 void go_quad_asin (GOQuad *res, const GOQuad *a);
 void go_quad_cos (GOQuad *res, const GOQuad *a);
+void go_quad_cospi (GOQuad *res, const GOQuad *a);
 void go_quad_acos (GOQuad *res, const GOQuad *a);
 void go_quad_atan2 (GOQuad *res, const GOQuad *y, const GOQuad *x);
 void go_quad_atan2pi (GOQuad *res, const GOQuad *y, const GOQuad *x);
@@ -77,8 +79,10 @@ void go_quad_logl (GOQuadl *res, const GOQuadl *a);
 void go_quad_hypotl (GOQuadl *res, const GOQuadl *a, const GOQuadl *b);
 
 void go_quad_sinl (GOQuadl *res, const GOQuadl *a);
+void go_quad_sinpil (GOQuadl *res, const GOQuadl *a);
 void go_quad_asinl (GOQuadl *res, const GOQuadl *a);
 void go_quad_cosl (GOQuadl *res, const GOQuadl *a);
+void go_quad_cospil (GOQuadl *res, const GOQuadl *a);
 void go_quad_acosl (GOQuadl *res, const GOQuadl *a);
 void go_quad_atan2l (GOQuadl *res, const GOQuadl *y, const GOQuadl *x);
 void go_quad_atan2pil (GOQuadl *res, const GOQuadl *y, const GOQuadl *x);
diff --git a/tests/test-quad.c b/tests/test-quad.c
index beed1b3..c33d416 100644
--- a/tests/test-quad.c
+++ b/tests/test-quad.c
@@ -292,6 +292,8 @@ floor_tests (void)
 #define TEST2(a_) do {                         \
        UNTEST1(a_,go_quad_sin,sin,"sin");      \
        UNTEST1(a_,go_quad_cos,cos,"cos");      \
+       UNTEST1(a_,go_quad_sinpi,go_sinpi,"sinpi");     \
+       UNTEST1(a_,go_quad_cospi,go_cospi,"cospi");     \
 } while (0)
 
 static void


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