[gnumeric] Complex: more use of value api



commit 7a973eb4a0970899a3fb25c4c455f095f716a028
Author: Morten Welinder <terra gnome org>
Date:   Sat Feb 13 12:23:59 2016 -0500

    Complex: more use of value api

 plugins/fn-complex/functions.c   |    6 +-
 plugins/fn-complex/gsl-complex.c |    2 +-
 plugins/fn-tsa/functions.c       |   10 ++--
 src/complex.c                    |    6 +-
 src/complex.h                    |   14 +++++
 src/sf-gamma.c                   |  105 ++++++++++++++++----------------------
 6 files changed, 69 insertions(+), 74 deletions(-)
---
diff --git a/plugins/fn-complex/functions.c b/plugins/fn-complex/functions.c
index 34d6267..5e3cd08 100644
--- a/plugins/fn-complex/functions.c
+++ b/plugins/fn-complex/functions.c
@@ -66,7 +66,7 @@ value_new_complex (gnm_complex const *c, char imunit)
 {
        if (gnm_complex_invalid_p (c))
                return value_new_error_NUM (NULL);
-       else if (gnm_complex_real_p (c))
+       else if (GNM_CREALP (*c))
                return value_new_float (c->re);
        else
                return value_new_string_nocopy (gnm_complex_to_string (c, imunit));
@@ -1219,7 +1219,7 @@ gnumeric_improduct (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
        p.type = Improduct;
        p.imunit = 'j';
-       gnm_complex_real (&p.res, 1);
+       p.res = GNM_CREAL (1);
 
        v = function_iterate_argument_values
                (ei->pos, callback_function_imoper, &p,
@@ -1253,7 +1253,7 @@ gnumeric_imsum (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
        p.type = Imsum;
        p.imunit = 'j';
-       gnm_complex_real (&p.res, 0);
+       p.res = GNM_CREAL (0);
 
        v = function_iterate_argument_values
                (ei->pos, callback_function_imoper, &p,
diff --git a/plugins/fn-complex/gsl-complex.c b/plugins/fn-complex/gsl-complex.c
index b8e6bdb..3451b2c 100644
--- a/plugins/fn-complex/gsl-complex.c
+++ b/plugins/fn-complex/gsl-complex.c
@@ -79,7 +79,7 @@ gsl_complex_mul_imag (gnm_complex const *a, gnm_float y, gnm_complex *res)
 void
 gsl_complex_inverse (gnm_complex const *a, gnm_complex *res)
 {                               /* z=1/a */
-        gnm_float s = 1.0 / gnm_complex_mod (a);
+        gnm_float s = 1.0 / GNM_CABS (*a);
 
        gnm_complex_init (res, (GSL_REAL (a) * s) * s, -(GSL_IMAG (a) * s) * s);
 }
diff --git a/plugins/fn-tsa/functions.c b/plugins/fn-tsa/functions.c
index 25ad280..8984413 100644
--- a/plugins/fn-tsa/functions.c
+++ b/plugins/fn-tsa/functions.c
@@ -126,14 +126,12 @@ gnm_fourier_fft (gnm_complex const *in, int n, int skip, gnm_complex **fourier,
        for (i = 0; i < nhalf; i++) {
                gnm_complex dir, tmp;
 
-               gnm_complex_from_polar (&dir, 1, argstep * i);
-               gnm_complex_mul (&tmp, &fourier_2[i], &dir);
+               dir = GNM_CPOLAR (1, argstep * i);
+               tmp = GNM_CMUL (fourier_2[i], dir);
 
-               gnm_complex_add (&((*fourier)[i]), &fourier_1[i], &tmp);
-               gnm_complex_scale_real (&((*fourier)[i]), 0.5);
+               (*fourier)[i] = GNM_CSCALE (GNM_CADD (fourier_1[i], tmp), 0.5);
 
-               gnm_complex_sub (&((*fourier)[i + nhalf]), &fourier_1[i], &tmp);
-               gnm_complex_scale_real (&((*fourier)[i + nhalf]), 0.5);
+               (*fourier)[i + nhalf] = GNM_CSCALE (GNM_CSUB (fourier_1[i], tmp), 0.5);
        }
 
        g_free (fourier_1);
diff --git a/src/complex.c b/src/complex.c
index a9c040a..b14ec1c 100644
--- a/src/complex.c
+++ b/src/complex.c
@@ -124,7 +124,7 @@ gnm_complex_from_string (gnm_complex *dst, char const *src, char *imunit)
 
        /* Case: "42", "+42", "-42", ...  */
        if (*src == 0) {
-               gnm_complex_real (dst, x);
+               *dst = GNM_CREAL (x);
                *imunit = 'i';
                return 0;
        }
@@ -134,7 +134,7 @@ gnm_complex_from_string (gnm_complex *dst, char const *src, char *imunit)
                *imunit = *src++;
                EAT_SPACES (src);
                if (*src == 0) {
-                       gnm_complex_init (dst, 0, x);
+                       *dst = GNM_CMAKE (0, x);
                        return 0;
                } else
                        return -1;
@@ -161,7 +161,7 @@ gnm_complex_from_string (gnm_complex *dst, char const *src, char *imunit)
                *imunit = *src++;
                EAT_SPACES (src);
                if (*src == 0) {
-                       gnm_complex_init (dst, x, y);
+                       *dst = GNM_CMAKE (x, y);
                        return 0;
                }
        }
diff --git a/src/complex.h b/src/complex.h
index a831751..d13eb81 100644
--- a/src/complex.h
+++ b/src/complex.h
@@ -99,6 +99,20 @@ static inline gnm_complex GNM_CMAKE (gnm_float re, gnm_float im)
        return res;
 }
 #define GNM_CREAL(r) (GNM_CMAKE((r),0))
+#define GNM_CREALP(c) (GNM_CIM((c)) == 0)
+
+static inline gnm_complex GNM_CPOLAR (gnm_float mod, gnm_float angle)
+{
+       gnm_complex res;
+       gnm_complex_from_polar (&res, mod, angle);
+       return res;
+}
+static inline gnm_complex GNM_CPOLARPI (gnm_float mod, gnm_float angle)
+{
+       gnm_complex res;
+       gnm_complex_from_polar_pi (&res, mod, angle);
+       return res;
+}
 static inline gnm_float GNM_CARG (gnm_complex c) { return gnm_complex_angle (&c); }
 static inline gnm_float GNM_CARGPI (gnm_complex c) { return gnm_complex_angle_pi (&c); }
 static inline gnm_float GNM_CABS (gnm_complex c) { return gnm_complex_mod (&c); }
diff --git a/src/sf-gamma.c b/src/sf-gamma.c
index cc601ed..a5d6564 100644
--- a/src/sf-gamma.c
+++ b/src/sf-gamma.c
@@ -1252,7 +1252,7 @@ static const guint32 lanczos_denom[G_N_ELEMENTS(lanczos_num)] = {
 gnm_complex
 gnm_complex_gamma (gnm_complex src)
 {
-       if (gnm_complex_real_p (&src)) {
+       if (GNM_CREALP (src)) {
                return GNM_CREAL (gnm_gamma (src.re));
        } else if (src.re < 0) {
                /* Gamma(z) = pi / (sin(pi*z) * Gamma(-z+1)) */
@@ -1287,7 +1287,7 @@ gnm_complex_gamma (gnm_complex src)
 gnm_complex
 gnm_complex_fact (gnm_complex src)
 {
-       if (gnm_complex_real_p (&src)) {
+       if (GNM_CREALP (src)) {
                return GNM_CREAL (gnm_fact (src.re));
        } else {
                // This formula is valid for all arguments except zero
@@ -1324,10 +1324,8 @@ gnm_complex_continued_fraction (gnm_complex *dst, size_t N,
        size_t i;
        const gboolean debug_cf = FALSE;
 
-       gnm_complex_init (&A0, 1, 0);
-       gnm_complex_init (&A1, 0, 0);
-       gnm_complex_init (&B0, 0, 0);
-       gnm_complex_init (&B1, 1, 0);
+       A0 = B1 = GNM_CREAL (1);
+       A1 = B0 = GNM_CREAL (0);
 
        for (i = 1; i < N; i++) {
                gnm_complex ai, bi, t1, t2, c1, c2, A2, B2;
@@ -1337,15 +1335,15 @@ gnm_complex_continued_fraction (gnm_complex *dst, size_t N,
                cf (&ai, &bi, i, args);
 
                /* Update A. */
-               gnm_complex_mul (&t1, &bi, &A1);
-               gnm_complex_mul (&t2, &ai, &A0);
-               gnm_complex_add (&A2, &t1, &t2);
+               t1 = GNM_CMUL (bi, A1);
+               t2 = GNM_CMUL (ai, A0);
+               A2 = GNM_CADD (t1, t2);
                A0 = A1; A1 = A2;
 
                /* Update B. */
-               gnm_complex_mul (&t1, &bi, &B1);
-               gnm_complex_mul (&t2, &ai, &B0);
-               gnm_complex_add (&B2, &t1, &t2);
+               t1 = GNM_CMUL (bi, B1);
+               t2 = GNM_CMUL (ai, B0);
+               B2 = GNM_CADD (t1, t2);
                B0 = B1; B1 = B2;
 
                /* Rescale */
@@ -1362,20 +1360,20 @@ gnm_complex_continued_fraction (gnm_complex *dst, size_t N,
                                g_printerr ("rescale by 2^%d\n", -e);
 
                        s = ldexp (1, -e);
-                       A0.re *= s; A0.im *= s;
-                       A1.re *= s; A1.im *= s;
-                       B0.re *= s; B0.im *= s;
-                       B1.re *= s; B1.im *= s;
+                       A0 = GNM_CSCALE (A0, s);
+                       A1 = GNM_CSCALE (A1, s);
+                       B0 = GNM_CSCALE (B0, s);
+                       A1 = GNM_CSCALE (B1, s);
                }
 
                /* Check for convergence */
-               gnm_complex_mul (&t1, &A1, &B0);
-               gnm_complex_mul (&t2, &A0, &B1);
-               gnm_complex_sub (&c1, &t1, &t2);
+               t1 = GNM_CMUL (A1, B0);
+               t2 = GNM_CMUL (A0, B1);
+               c1 = GNM_CSUB (t1, t2);
 
-               gnm_complex_mul (&c2, &B0, &B1);
+               c2 = GNM_CMUL (B0, B1);
 
-               gnm_complex_div (&t1, &A1, &B1);
+               t1 = GNM_CDIV (A1, B1);
                if (debug_cf) {
                        g_printerr ("  a : %.20g + %.20g I\n", ai.re, ai.im);
                        g_printerr ("  b : %.20g + %.20g I\n", bi.re, bi.im);
@@ -1384,18 +1382,18 @@ gnm_complex_continued_fraction (gnm_complex *dst, size_t N,
                        g_printerr ("%3zd : %.20g + %.20g I\n", i, t1.re, t1.im);
                }
 
-               if (gnm_complex_mod (&c1) <= gnm_complex_mod (&c2) * (GNM_EPSILON /2))
+               if (GNM_CABS (c1) <= GNM_CABS (c2) * (GNM_EPSILON /2))
                        break;
        }
 
        if (i == N) {
                g_printerr ("continued fraction failed to converge.\n");
-               /* Make the failure obvious. */
-               dst->re = dst->im = gnm_nan;
+               // Make the failure obvious.
+               *dst = GNM_CMAKE (gnm_nan, gnm_nan);
                return FALSE;
        }
 
-       gnm_complex_div (dst, &A1, &B1);
+       *dst = GNM_CDIV (A1, B1);
        return TRUE;
 }
 
@@ -1422,18 +1420,13 @@ static gboolean
 igamma_lower_cf (gnm_complex *dst, const gnm_complex *a, const gnm_complex *z)
 {
        gnm_complex args[2] = { *a, *z };
-       gnm_complex f, mz, res;
+       gnm_complex res;
 
        if (!gnm_complex_continued_fraction (&res, 100, igamma_lower_coefs, args))
                return FALSE;
 
        // FIXME: The following should be handled without creating big numbers.
-
-               mz.re = -z->re, mz.im = -z->im;
-       gnm_complex_exp (&f, &mz);
-       gnm_complex_mul (&res, &res, &f);
-       gnm_complex_pow (&f, z, a);
-       gnm_complex_mul (dst, &res, &f);
+       *dst = GNM_CMUL3 (res, GNM_CEXP (GNM_CNEG (*z)), GNM_CPOW (*z, *a));
 
        return TRUE;
 }
@@ -1441,10 +1434,10 @@ igamma_lower_cf (gnm_complex *dst, const gnm_complex *a, const gnm_complex *z)
 static gboolean
 igamma_upper_asymp (gnm_complex *dst, const gnm_complex *a, const gnm_complex *z)
 {
-       gnm_float am = gnm_complex_mod (a);
-       gnm_float zm = gnm_complex_mod (z);
+       gnm_float am = GNM_CABS (*a);
+       gnm_float zm = GNM_CABS (*z);
        gnm_float n0;
-       gnm_complex s, t, am1;
+       gnm_complex s, t;
        gboolean debug = FALSE;
        size_t i;
 
@@ -1462,31 +1455,27 @@ igamma_upper_asymp (gnm_complex *dst, const gnm_complex *a, const gnm_complex *z
        if (2 * zm < GNM_MANT_DIG * M_LN2gnum)
                return FALSE;
 
-       gnm_complex_real (&s, 0);
+       s = GNM_CREAL (0);
 
-       gnm_complex_init (&am1, a->re - 1, a->im);
-       t = complex_temme_D (am1, *z);
+       t = complex_temme_D (GNM_CSUB (*a, GNM_CREAL (1)), *z);
 
        for (i = 0; i < 100; i++) {
-               gnm_complex api;
-
-               gnm_complex_add (&s, &s, &t);
+               s = GNM_CADD (s, t);
 
                if (debug) {
                        g_printerr ("%3zd: t=%.20g + %.20g * I\n", i, t.re, t.im);
                        g_printerr ("   : s=%.20g + %.20g * I\n", s.re, s.im);
                }
 
-               if (gnm_complex_mod (&t) <= gnm_complex_mod (&s) * GNM_EPSILON) {
+               if (GNM_CABS (t) <= GNM_CABS (s) * GNM_EPSILON) {
                        if (debug)
                                g_printerr ("igamma_upper_asymp converged.\n");
                        *dst = s;
                        return TRUE;
                }
 
-               gnm_complex_div (&t, &t, z);
-               gnm_complex_init (&api, a->re - (i + 1), a->im);
-               gnm_complex_mul (&t, &t, &api);
+               t = GNM_CDIV (t, *z);
+               t = GNM_CMUL (t, GNM_CSUB (*a, GNM_CREAL (i + 1)));
        }
 
        if (debug)
@@ -1502,24 +1491,18 @@ fixup_upper_real (gnm_complex *res, gnm_complex const *a, gnm_complex const *z)
        //
        // It appears that upper algorithms have trouble with negative real z
        // (for example, such z being outside the allowed domain) in some cases.
-       
 
-       if (gnm_complex_real_p (z) && z->re < 0 &&
-           gnm_complex_real_p (a) && a->re != gnm_floor (a->re)) {
+       if (GNM_CREALP (*z) && z->re < 0 &&
+           GNM_CREALP (*a) && a->re != gnm_floor (a->re)) {
                // Everything in the lower power series is real expect z^a
                // which is not.  So...
                // 1. Flip to lower gamma
                // 2. Assume modulus is correct
                // 3. Use exact angle for lower gamma
                // 4. Flip back to upper gamma
-               gnm_complex lres = *res;
-               lres.re = 1 - lres.re;
-
-               gnm_complex_from_polar_pi (res,
-                                          gnm_complex_mod (&lres),
-                                          a->re);
-               res->re = 1 - res->re;
-               res->im = 0 - res->im;
+               gnm_complex lres = GNM_CSUB (GNM_CREAL (1), *res);
+               *res = GNM_CPOLARPI (GNM_CABS (lres), a->re);
+               *res = GNM_CSUB (GNM_CREAL (1), *res);
        }
 }
 
@@ -1531,16 +1514,16 @@ gnm_complex_igamma (gnm_complex a, gnm_complex z,
        gboolean have_lower, have_regularized;
        gboolean have_ga = FALSE;
 
-       if (regularized && gnm_complex_real_p (&a) &&
+       if (regularized && GNM_CREALP (a) &&
            a.re <= 0 && a.re == gnm_floor (a.re)) {
-               gnm_complex_real (&res, 0);
+               res = GNM_CREAL (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) {
+       if (GNM_CREALP (a) && a.re >= 0 &&
+           GNM_CREALP (z) && z.re >= 0) {
                res = GNM_CREAL (pgamma (z.re, a.re, 1, lower, FALSE));
                have_lower = lower;
                have_regularized = TRUE;
@@ -1579,7 +1562,7 @@ fixup:
 
        if (lower != have_lower) {
                if (have_regularized) {
-                       res = GNM_CMAKE (1 - res.re, 0 - res.im);
+                       res = GNM_CSUB (GNM_CREAL (1), res);
                } else {
                        if (!have_ga)
                                ga = gnm_complex_gamma (a);


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