[gnumeric] Complex: further switching to value api



commit d3a38c50ebb55b21e6467ed1fe094e9e55558512
Author: Morten Welinder <terra gnome org>
Date:   Fri Feb 12 23:03:54 2016 -0500

    Complex: further switching to value api

 plugins/fn-complex/functions.c |    5 +-
 plugins/fn-math/functions.c    |    6 +--
 src/sf-gamma.c                 |  110 +++++++++++++++------------------------
 src/sf-gamma.h                 |    4 +-
 4 files changed, 48 insertions(+), 77 deletions(-)
---
diff --git a/plugins/fn-complex/functions.c b/plugins/fn-complex/functions.c
index ac65297..34d6267 100644
--- a/plugins/fn-complex/functions.c
+++ b/plugins/fn-complex/functions.c
@@ -1120,7 +1120,7 @@ static GnmFuncHelp const help_imigamma[] = {
 static GnmValue *
 gnumeric_imigamma (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
-       gnm_complex res, a, z;
+       gnm_complex a, z;
        char imunit;
        gboolean lower = argv[2] ? value_get_as_checked_bool (argv[2]) : TRUE;
        gboolean reg = argv[3] ? value_get_as_checked_bool (argv[3]) : TRUE;
@@ -1130,8 +1130,7 @@ gnumeric_imigamma (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
        if (value_get_as_complex (argv[1], &z, &imunit))
                return value_new_error_NUM (ei->pos);
 
-       complex_igamma (&res, &a, &z, lower, reg);
-       return value_new_complex (&res, imunit);
+       return value_new_complexv (gnm_complex_igamma (a, z, lower, reg), imunit);
 }
 
 /***************************************************************************/
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index 595a16c..5c8f85a 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -1032,11 +1032,9 @@ gnumeric_igamma (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
        gboolean lower = argv[2] ? value_get_as_checked_bool (argv[2]) : TRUE;
        gboolean reg = argv[3] ? value_get_as_checked_bool (argv[3]) : TRUE;
        gboolean re = argv[4] ? value_get_as_checked_bool (argv[4]) : TRUE;
-       gnm_complex ig, ca, cz;
+       gnm_complex ig;
 
-       gnm_complex_init (&ca, a, 0);
-       gnm_complex_init (&cz, z, 0);
-       complex_igamma (&ig, &ca, &cz, lower, reg);
+       ig = gnm_complex_igamma (GNM_CREAL (a), GNM_CREAL (z), lower, reg);
 
        return value_new_float (re ? ig.re : ig.im);
 }
diff --git a/src/sf-gamma.c b/src/sf-gamma.c
index 0602168..cc601ed 100644
--- a/src/sf-gamma.c
+++ b/src/sf-gamma.c
@@ -1256,47 +1256,29 @@ gnm_complex_gamma (gnm_complex src)
                return GNM_CREAL (gnm_gamma (src.re));
        } else if (src.re < 0) {
                /* Gamma(z) = pi / (sin(pi*z) * Gamma(-z+1)) */
-               gnm_complex a, b;
-
-               a = gnm_complex_fact (GNM_CNEG (src));
-
-               gnm_complex_init (&b,
-                             M_PIgnum * gnm_fmod (src.re, 2),
-                             M_PIgnum * src.im);
+               gnm_complex b = GNM_CMAKE (M_PIgnum * gnm_fmod (src.re, 2),
+                                          M_PIgnum * src.im);
                /* Hmm... sin overflows when b.im is large.  */
-               gnm_complex_sin (&b, &b);
-
-               gnm_complex_mul (&a, &a, &b);
-
-               gnm_complex_init (&b, M_PIgnum, 0);
-
-               return GNM_CDIV (b, a);
+               return GNM_CDIV (GNM_CREAL (M_PIgnum),
+                                GNM_CMUL (gnm_complex_fact (GNM_CNEG (src)), GNM_CSIN (b)));
        } else {
-               gnm_complex zmh, zmhd2, zmhpg, f, f2, p, q, pq;
+               gnm_complex zmh, f, p, q;
                int i;
 
                i = G_N_ELEMENTS(lanczos_num) - 1;
-               gnm_complex_init (&p, lanczos_num[i], 0);
-               gnm_complex_init (&q, lanczos_denom[i], 0);
+               p = GNM_CREAL (lanczos_num[i]);
+               q = GNM_CREAL (lanczos_denom[i]);
                while (--i >= 0) {
-                       gnm_complex_mul (&p, &p, &src);
+                       p = GNM_CMUL (p, src);
                        p.re += lanczos_num[i];
-                       gnm_complex_mul (&q, &q, &src);
+                       q = GNM_CMUL (q, src);
                        q.re += lanczos_denom[i];
                }
-               gnm_complex_div (&pq, &p, &q);
 
-               gnm_complex_init (&zmh, src.re - 0.5, src.im);
-               gnm_complex_init (&zmhpg, zmh.re + lanczos_g, zmh.im);
-               gnm_complex_init (&zmhd2, zmh.re * 0.5, zmh.im * 0.5);
-               gnm_complex_pow (&f, &zmhpg, &zmhd2);
+               zmh = GNM_CMAKE (src.re - 0.5, src.im);
+               f = GNM_CPOW (GNM_CADD (zmh, GNM_CREAL (lanczos_g)), GNM_CSCALE (zmh, 0.5));
 
-               zmh.re = -zmh.re; zmh.im = -zmh.im;
-               gnm_complex_exp (&f2, &zmh);
-               gnm_complex_mul (&f2, &f, &f2);
-               gnm_complex_mul (&f2, &f2, &f);
-
-               return GNM_CMUL (f2, pq);
+               return GNM_CMUL4 (f, GNM_CEXP (GNM_CNEG (zmh)), f, GNM_CDIV (p, q));
        }
 }
 
@@ -1317,19 +1299,16 @@ gnm_complex_fact (gnm_complex src)
 /* ------------------------------------------------------------------------- */
 
 // D(a,z) := z^a * exp(-z) / Gamma (a + 1)
-static void
-complex_temme_D (gnm_complex *res, gnm_complex const *a, gnm_complex const *z)
+static gnm_complex 
+complex_temme_D (gnm_complex a, gnm_complex z)
 {
-       gnm_complex t, ez, fa;
+       gnm_complex t;
 
        // The idea here is to control intermediate sizes and to avoid
        // accuracy problems caused by exp and pow.  For now, do neither.
 
-       gnm_complex_pow (&t, z, a);
-       gnm_complex_exp (&ez, z);
-       gnm_complex_div (&t, &t, &ez);
-       fa = gnm_complex_fact (*a);
-       gnm_complex_div (res, &t, &fa);
+       t = GNM_CDIV (GNM_CPOW (z, a), GNM_CEXP (z));
+       return GNM_CDIV (t, gnm_complex_fact (a));
 }
 
 
@@ -1428,18 +1407,15 @@ igamma_lower_coefs (gnm_complex *ai, gnm_complex *bi, size_t i,
        gnm_complex const *z = args + 1;
 
        if (i == 1)
-               gnm_complex_real (ai, 1);
+               *ai = GNM_CREAL (1);
        else if (i & 1) {
-               gnm_complex f;
-               gnm_complex_real (&f, i >> 1);
-               gnm_complex_mul (ai, &f, z);
+               *ai = GNM_CSCALE (*z, i >> 1);
        } else {
-               gnm_complex f;
-               gnm_complex_init (&f, -(a->re + ((i >> 1) - 1)), -a->im);
-               gnm_complex_mul (ai, &f, z);
+               gnm_complex f = GNM_CMAKE (-(a->re + ((i >> 1) - 1)), -a->im);
+               *ai = GNM_CMUL (f, *z);
        }
 
-       gnm_complex_init (bi, a->re + (i - 1), a->im);
+       *bi = GNM_CMAKE (a->re + (i - 1), a->im);
 }
 
 static gboolean
@@ -1489,7 +1465,7 @@ igamma_upper_asymp (gnm_complex *dst, const gnm_complex *a, const gnm_complex *z
        gnm_complex_real (&s, 0);
 
        gnm_complex_init (&am1, a->re - 1, a->im);
-       complex_temme_D (&t, &am1, z);
+       t = complex_temme_D (am1, *z);
 
        for (i = 0; i < 100; i++) {
                gnm_complex api;
@@ -1547,73 +1523,71 @@ fixup_upper_real (gnm_complex *res, gnm_complex const *a, gnm_complex const *z)
        }
 }
 
-void
-complex_igamma (gnm_complex *dst, const gnm_complex *a, const gnm_complex *z,
-               gboolean lower, gboolean regularized)
+gnm_complex
+gnm_complex_igamma (gnm_complex a, gnm_complex z,
+                   gboolean lower, gboolean regularized)
 {
        gnm_complex res, ga;
        gboolean have_lower, have_regularized;
        gboolean have_ga = FALSE;
 
-       if (regularized && gnm_complex_real_p (a) &&
-           a->re <= 0 && a->re == gnm_floor (a->re)) {
+       if (regularized && gnm_complex_real_p (&a) &&
+           a.re <= 0 && a.re == gnm_floor (a.re)) {
                gnm_complex_real (&res, 0);
                have_lower = FALSE;
                have_regularized = TRUE;
                goto fixup;
        }
 
-       if (gnm_complex_real_p (a) && a->re >= 0 &&
-           gnm_complex_real_p (z) && z->re >= 0) {
-               gnm_complex_init (&res, pgamma (z->re, a->re, 1, lower, FALSE), 0);
+       if (gnm_complex_real_p (&a) && a.re >= 0 &&
+           gnm_complex_real_p (&z) && z.re >= 0) {
+               res = GNM_CREAL (pgamma (z.re, a.re, 1, lower, FALSE));
                have_lower = lower;
                have_regularized = TRUE;
                goto fixup;
        }
 
-       if (igamma_upper_asymp (&res, a, z)) {
+       if (igamma_upper_asymp (&res, &a, &z)) {
                have_lower = FALSE;
                have_regularized = TRUE;
-               fixup_upper_real (&res, a, z);
+               fixup_upper_real (&res, &a, &z);
                goto fixup;
        }
 
-       if (igamma_lower_cf (&res, a, z)) {
+       if (igamma_lower_cf (&res, &a, &z)) {
                have_lower = TRUE;
                have_regularized = FALSE;
                goto fixup;
        }
 
-       gnm_complex_init (dst, gnm_nan, gnm_nan);
-       return;
+       return GNM_CMAKE (gnm_nan, gnm_nan);
 
 fixup:
        // Fixup to the desired form as needed.  This is not ideal.
        // 1. Regularizing here is too late due to overflow.
        // 2. Upper/lower switch can have cancellation
        if (regularized != have_regularized) {
-               ga = gnm_complex_gamma (*a);
+               ga = gnm_complex_gamma (a);
                have_ga = TRUE;
 
                if (have_regularized)
-                       gnm_complex_mul (&res, &res, &ga);
+                       res = GNM_CMUL (res, ga);
                else
-                       gnm_complex_div (&res, &res, &ga);
+                       res = GNM_CDIV (res, ga);
                have_regularized = TRUE;
        }
 
        if (lower != have_lower) {
                if (have_regularized) {
-                       res.re = 1 - res.re;
-                       res.im = 0 - res.im;
+                       res = GNM_CMAKE (1 - res.re, 0 - res.im);
                } else {
                        if (!have_ga)
-                               ga = gnm_complex_gamma (*a);
-                       gnm_complex_sub (&res, &ga, &res);
+                               ga = gnm_complex_gamma (a);
+                       res = GNM_CSUB (ga, res);
                }
        }
 
-       *dst = res;
+       return res;
 }
 
 /* ------------------------------------------------------------------------- */
diff --git a/src/sf-gamma.h b/src/sf-gamma.h
index 0ea7e99..cb0c85e 100644
--- a/src/sf-gamma.h
+++ b/src/sf-gamma.h
@@ -12,8 +12,8 @@ gnm_float gnm_fact (gnm_float x);
 int       qfactf (gnm_float x, GnmQuad *mant, int *exp2);
 gnm_complex gnm_complex_gamma (gnm_complex src);
 gnm_complex gnm_complex_fact (gnm_complex src);
-void complex_igamma (gnm_complex *dst, gnm_complex const  *a, gnm_complex const *z,
-                    gboolean lower, gboolean regularized);
+gnm_complex gnm_complex_igamma (gnm_complex a, gnm_complex z,
+                               gboolean lower, gboolean regularized);
 
 gnm_float gnm_lbeta (gnm_float a, gnm_float b);
 gnm_float gnm_beta (gnm_float a, gnm_float b);


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