[gnumeric] AGM: New function.



commit 57977759be3136f2e9a2026b5c673ed2fc00fc64
Author: Morten Welinder <terra gnome org>
Date:   Sat Jan 9 14:01:49 2016 -0500

    AGM: New function.

 NEWS                                           |    1 +
 doc/C/func.defs                                |    9 +++++
 doc/C/functions.xml                            |   33 +++++++++++++++++
 plugins/fn-math/functions.c                    |   28 +++++++++++++-
 plugins/fn-math/plugin.xml.in                  |    1 +
 samples/burkardt.gnumeric                      |  Bin 0 -> 31314 bytes
 samples/burkhardt.gnumeric                     |  Bin 30093 -> 0 bytes
 src/mathfunc.c                                 |   47 ++++++++++++++++++++++++
 src/mathfunc.h                                 |    1 +
 test/ChangeLog                                 |    7 +++-
 test/Makefile.am                               |    2 +-
 test/{t1012-burkhardt.pl => t1012-burkardt.pl} |    2 +-
 tools/ChangeLog                                |    4 ++
 tools/process-burkardt.c                       |   14 ++++++--
 14 files changed, 141 insertions(+), 8 deletions(-)
---
diff --git a/NEWS b/NEWS
index 1d51e25..55b7db8 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ Morten:
          [#760043] [#760103] [#760102] [#760101] [#760105] [#760106]
          [#760104] [#760229] [#760231] [#760232]
        * Fix R.DBINOM extreme-value case.  [#760230]
+       * New function AGM.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.26
diff --git a/doc/C/func.defs b/doc/C/func.defs
index 92dc7a5..18d6b88 100644
--- a/doc/C/func.defs
+++ b/doc/C/func.defs
@@ -3208,6 +3208,15 @@ The depreciation coefficient used is:
 @SEEALSO=COTH,TANH
 
 @CATEGORY=Mathematics
+ FUNCTION=AGM
+ SHORTDESC=the arithmetic-geometric mean
+ SYNTAX=AGM(a,b)
+ ARGUMENTDESCRIPTION=@{a}: value
+ {b}: value
+ DESCRIPTION=AGM computes the arithmetic-geometric mean of the two values.
+ SEEALSO=AVERAGE,GEOMEAN
+
+ CATEGORY=Mathematics
 @FUNCTION=ARABIC
 @SHORTDESC=the Roman numeral @{roman} as number
 @SYNTAX=ARABIC(roman)
diff --git a/doc/C/functions.xml b/doc/C/functions.xml
index a92939a..45263b2 100644
--- a/doc/C/functions.xml
+++ b/doc/C/functions.xml
@@ -10367,6 +10367,39 @@
       </para>
       </refsect1>
     </refentry>
+    <refentry id="gnumeric-function-AGM">
+      <refmeta>
+        <refentrytitle>
+          <function>AGM</function>
+        </refentrytitle>
+      </refmeta>
+      <refnamediv>
+        <refname>
+          <function>AGM</function>
+        </refname>
+        <refpurpose>
+        the arithmetic-geometric mean
+      </refpurpose>
+      </refnamediv>
+      <refsynopsisdiv>
+        <synopsis><function>AGM</function>(<parameter>a</parameter>,<parameter>b</parameter>)</synopsis>
+      </refsynopsisdiv>
+      <refsect1>
+        <title>Arguments</title>
+        <para><parameter>a</parameter>: value</para>
+        <para><parameter>b</parameter>: value</para>
+      </refsect1>
+      <refsect1>
+        <title>Description</title>
+        <para><function>AGM</function> computes the arithmetic-geometric mean of the two values.</para>
+      </refsect1>
+      <refsect1>
+        <title>See also</title>
+        <para><link linkend="gnumeric-function-AVERAGE"><function>AVERAGE</function></link>,
+        <link linkend="gnumeric-function-GEOMEAN"><function>GEOMEAN</function></link>.
+      </para>
+      </refsect1>
+    </refentry>
     <refentry id="gnumeric-function-ARABIC">
       <refmeta>
         <refentrytitle>
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index cf0a83a..7533739 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -450,6 +450,27 @@ gnumeric_atan2 (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 
        return value_new_float (gnm_atan2 (y, x));
 }
+/***************************************************************************/
+
+static GnmFuncHelp const help_agm[] = {
+       { GNM_FUNC_HELP_NAME, F_("AGM:the arithmetic-geometric mean") },
+       { GNM_FUNC_HELP_ARG, F_("a:value")},
+       { GNM_FUNC_HELP_ARG, F_("b:value")},
+       { GNM_FUNC_HELP_DESCRIPTION, F_("AGM computes the arithmetic-geometric mean of the two values.")},
+       { GNM_FUNC_HELP_EXAMPLES, "=AGM(1,4)" },
+       { GNM_FUNC_HELP_EXAMPLES, "=AGM(0.5,1)" },
+       { GNM_FUNC_HELP_SEEALSO, "AVERAGE,GEOMEAN"},
+       { GNM_FUNC_HELP_END}
+};
+
+static GnmValue *
+gnumeric_agm (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
+{
+       gnm_float a = value_get_as_float (argv[0]);
+       gnm_float b = value_get_as_float (argv[1]);
+
+       return value_new_float (agm (a, b));
+}
 
 /***************************************************************************/
 
@@ -3288,12 +3309,15 @@ GnmFuncDescriptor const math_functions[] = {
        { "acosh",   "f",     help_acosh,
          gnumeric_acosh, NULL, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
-       { "acot",     "f",     help_acot,
+       { "acot",    "f",     help_acot,
          gnumeric_acot, NULL, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
-       { "acoth",     "f",     help_acoth,
+       { "acoth",   "f",     help_acoth,
          gnumeric_acoth, NULL, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
+       { "agm",     "ff",    help_agm,
+         gnumeric_agm, NULL, NULL, NULL,
+         GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
        { "arabic",       "S",             help_arabic,
          gnumeric_arabic, NULL, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
diff --git a/plugins/fn-math/plugin.xml.in b/plugins/fn-math/plugin.xml.in
index 4180f9b..50f3075 100644
--- a/plugins/fn-math/plugin.xml.in
+++ b/plugins/fn-math/plugin.xml.in
@@ -16,6 +16,7 @@
                                <function name="acosh"/>
                                <function name="acot"/>
                                <function name="acoth"/>
+                               <function name="agm"/>
                                <function name="arabic"/>
                                <function name="asin"/>
                                <function name="asinh"/>
diff --git a/samples/burkardt.gnumeric b/samples/burkardt.gnumeric
new file mode 100644
index 0000000..c3fd4f4
Binary files /dev/null and b/samples/burkardt.gnumeric differ
diff --git a/src/mathfunc.c b/src/mathfunc.c
index bb7c598..50fabe8 100644
--- a/src/mathfunc.c
+++ b/src/mathfunc.c
@@ -4965,6 +4965,53 @@ expmx2h (gnm_float x)
 /* ------------------------------------------------------------------------- */
 
 /**
+ * agm:
+ * @a: a number
+ * @b: a number
+ *
+ * Returns: The arithmetic-geometric mean of @a and @b.
+ */
+gnm_float
+agm (gnm_float a, gnm_float b)
+{
+       gnm_float ab = a * b;
+       gnm_float scale = 1;
+       int i;
+
+       if (a < 0 || b < 0 || gnm_isnan (ab))
+               return gnm_nan;
+
+       if (a == gnm_pinf || b == gnm_pinf)
+               return gnm_pinf;
+       if (a == 0 || b == 0)
+               return 0;
+
+       if (ab == 0 || ab == gnm_pinf) {
+               // Underflow or overflow
+               int ea, eb;
+               (void)gnm_frexp (a, &ea);
+               (void)gnm_frexp (b, &eb);
+               scale = gnm_ldexp (1, -(ea + eb) / 2);
+               a *= scale;
+               b *= scale;
+       }
+
+       for (i = 1; i < 20; i++) {
+               gnm_float am = (a + b) / 2;
+               gnm_float gm = gnm_sqrt (a * b);
+               a = am;
+               b = gm;
+               if (gnm_abs (a - b) < a * GNM_EPSILON)
+                       break;
+       }
+       if (i == 20)
+               g_warning ("AGM failed to converge.");
+
+       return a / scale;
+}
+
+
+/**
  * pow1p:
  * @x: a number
  * @y: a number
diff --git a/src/mathfunc.h b/src/mathfunc.h
index b1122f8..173cc0d 100644
--- a/src/mathfunc.h
+++ b/src/mathfunc.h
@@ -37,6 +37,7 @@ gnm_float logspace_sub (gnm_float logx, gnm_float logy);
 gnm_float gnm_owent (gnm_float h, gnm_float a);
 gnm_float gnm_logcf (gnm_float x, gnm_float i, gnm_float d);
 gnm_float expmx2h (gnm_float x);
+gnm_float agm(gnm_float a, gnm_float b);
 
 /* "d": density.  */
 /* "p": distribution function.  */
diff --git a/test/ChangeLog b/test/ChangeLog
index 77dd6e1..91bb2ef 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,6 +1,11 @@
+2016-01-09  Morten Welinder  <terra gnome org>
+
+       * t1012-burkardt.pl: Rename from t1012-burkhardt.pl
+
 2015-04-12  Andreas J. Guelzow <aguelzow pyrshep ca>
 
-       * ods-ext-schema.patch: replace gnm:style with gnm:am-suffix and gnm:pm-suffix
+       * ods-ext-schema.patch: replace gnm:style with gnm:am-suffix and
+       gnm:pm-suffix
 
 2015-12-28  Morten Welinder <terra gnome org>
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 9efafd1..4301d03 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -38,7 +38,7 @@ TESTS =       t1000-statfuns.pl                       \
        t1009-lookfuns.pl                       \
        t1010-bitwise.pl                        \
        t1011-yalta2008.pl                      \
-       t1012-burkhardt.pl                      \
+       t1012-burkardt.pl                       \
        t1013-crlibm.pl                         \
        t1100-chitest.pl                        \
        t1101-ftest.pl                          \
diff --git a/test/t1012-burkhardt.pl b/test/t1012-burkardt.pl
similarity index 89%
rename from test/t1012-burkhardt.pl
rename to test/t1012-burkardt.pl
index 12eb1f7..a7248c4 100755
--- a/test/t1012-burkhardt.pl
+++ b/test/t1012-burkardt.pl
@@ -5,6 +5,6 @@ use strict;
 use lib ($0 =~ m|^(.*/)| ? $1 : ".");
 use GnumericTest;
 
-my $file = "burkhardt.gnumeric";
+my $file = "burkardt.gnumeric";
 &message ("Check that $file evaluates correctly.");
 &test_sheet_calc ("$samples/$file", "D1", sub { $_ > 11.5 });
diff --git a/tools/ChangeLog b/tools/ChangeLog
index 956bca3..d31d3b3 100644
--- a/tools/ChangeLog
+++ b/tools/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-09  Morten Welinder  <terra gnome org>
+
+       * process-burkardt.c: Add agm.  Fix bit-rot.
+
 2015-12-28  Morten Welinder <terra gnome org>
 
        * Release 1.12.26
diff --git a/tools/process-burkardt.c b/tools/process-burkardt.c
index bf56c9d..e79951b 100644
--- a/tools/process-burkardt.c
+++ b/tools/process-burkardt.c
@@ -18,6 +18,7 @@ typedef enum {
        GT_DD_D,
        GT_DDD_D,
        GT_DI_D,
+       GT_I_D,
        GT_ID_D,
        GT_IDI_D,
        GT_IID_D,
@@ -63,6 +64,10 @@ test_func (const char *func_name,
                        generator (&n_data, &xd[0], &xi[1], &yd);
                        types = "DI:D";
                        break;
+               case GT_I_D:
+                       generator (&n_data, &xi[0], &yd);
+                       types = "I:D";
+                       break;
                case GT_ID_D:
                        generator (&n_data, &xi[0], &xd[1], &yd);
                        types = "ID:D";
@@ -192,6 +197,7 @@ main (int argc, char **argv)
 
        test_func ("acos", arccos_values, GT_D_D, NULL);
        test_func ("acosh", arccosh_values, GT_D_D, NULL);
+       test_func ("agm", agm_values, GT_DD_D, NULL);
        test_func ("asin", arcsin_values, GT_D_D, NULL);
        test_func ("asinh", arcsinh_values, GT_D_D, NULL);
        test_func ("atan", arctan_values, GT_D_D, NULL);
@@ -233,8 +239,9 @@ main (int argc, char **argv)
 
        test_func ("r.pf", f_cdf_values, GT_IID_D, "312");
        // f_noncentral_cdf_values ( int *n_data, int *n1, int *n2, double *lambda,
-       test_func ("fact", factorial_values, GT_I_I, NULL);
-       test_func ("factdouble", factorial2_values, GT_I_I, NULL);
+       test_func ("fact", i4_factorial_values, GT_I_I, NULL);
+       test_func ("fact", r8_factorial_values, GT_I_D, NULL);
+       test_func ("factdouble", i4_factorial2_values, GT_I_I, NULL);
        // factorial_rising_values ( int *n_data, int *m, int *n, int *fmn )
        // fresnel_cos_values ( int *n_data, double *x, double *fx )
        // fresnel_sin_values ( int *n_data, double *x, double *fx )
@@ -305,7 +312,8 @@ main (int argc, char **argv)
        // partition_distinct_count_values ( int *n_data, int *n, int *c )
        test_func ("nt_phi", phi_values, GT_I_I, NULL);
        if (do_slow) test_func ("nt_pi", pi_values, GT_I_I, NULL);
-       test_func ("pochhammer", pochhammer_values, GT_DD_D, NULL);
+       test_func ("pochhammer", i4_rise_values, GT_II_I, NULL);
+       test_func ("pochhammer", r8_rise_values, GT_DI_D, NULL);
        test_func ("r.ppois", poisson_cdf_values, GT_DI_D, "21");
        // polylogarithm_values ( int *n_data, int *n, double *z, double *fx )
        // prandtl_values ( int *n_data, double *tc, double *p, double *pr )


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