[goffice] Quad: sinpi, cospi.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Quad: sinpi, cospi.
- Date: Thu, 19 Dec 2013 01:25:31 +0000 (UTC)
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]