[gnumeric] Add MODE.MULT



commit 21108970b10544713a339d160c285efbeba77ba8
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date:   Tue Jun 16 21:27:34 2015 -0600

    Add MODE.MULT
    
    2015-06-16  Andreas J. Guelzow <aguelzow pyrshep ca>
    
        * openoffice-read.c (oo_func_map_in): Add MODE.MULT
        * openoffice-write.c (odf_expr_func_handler): Export MODE.MULT
        with Microsoft prefix
    
    2015-06-16  Andreas J. Guelzow <aguelzow pyrshep ca>
    
        * functions.c (help_mode_mult): new
        (gnumeric_mode_mult_cmp): new
        (gnumeric_mode_mult_rm): new
        (gnumeric_mode_mult): new
        (stat_functions): connect the above
        * plugin.xml.in: add MODE.MULT

 NEWS                                  |    3 +-
 plugins/fn-stat/ChangeLog             |    9 +++
 plugins/fn-stat/functions.c           |  105 ++++++++++++++++++++++++++++++++-
 plugins/fn-stat/plugin.xml.in         |    1 +
 plugins/openoffice/ChangeLog          |    6 ++
 plugins/openoffice/openoffice-read.c  |    1 +
 plugins/openoffice/openoffice-write.c |    1 +
 src/collect.c                         |    2 +-
 src/collect.h                         |    4 +
 9 files changed, 129 insertions(+), 3 deletions(-)
---
diff --git a/NEWS b/NEWS
index d3d90bf..f7ca288 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,8 @@ Andreas:
        * Fix memory handling error on fuzzed sxc file. [#748535]
        * Improve import/export of page layout from/to ODF.
        * Improve function import to ODF. [#750627]
-       * Add CONFIDENCE.T, PERCENTILE.EXC, PERCENTRANK.EXC and QUARTILE.EXC.
+       * Add CONFIDENCE.T, MODE.MULT, PERCENTILE.EXC, PERCENTRANK.EXC
+       and QUARTILE.EXC.
 
 Jean:
        * Fix xlsx import of plot area manual layout. [#748016]
diff --git a/plugins/fn-stat/ChangeLog b/plugins/fn-stat/ChangeLog
index d2475e2..0fcc6a3 100644
--- a/plugins/fn-stat/ChangeLog
+++ b/plugins/fn-stat/ChangeLog
@@ -1,3 +1,12 @@
+2015-06-16  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+       * functions.c (help_mode_mult): new
+       (gnumeric_mode_mult_cmp): new
+       (gnumeric_mode_mult_rm): new
+       (gnumeric_mode_mult): new
+       (stat_functions): connect the above
+       * plugin.xml.in: add MODE.MULT
+
 2015-06-15  Andreas J. Guelzow <aguelzow pyrshep ca>
 
        * functions.c (help_percentrank_exc): new
diff --git a/plugins/fn-stat/functions.c b/plugins/fn-stat/functions.c
index 96eb246..55580a8 100644
--- a/plugins/fn-stat/functions.c
+++ b/plugins/fn-stat/functions.c
@@ -31,6 +31,7 @@
 #include <regression.h>
 #include <sheet.h>
 #include <collect.h>
+#include <gutils.h>
 #include <value.h>
 #include <expr.h>
 #include <expr-impl.h>
@@ -610,7 +611,7 @@ static GnmFuncHelp const help_mode[] = {
        { GNM_FUNC_HELP_DESCRIPTION, F_("If the data set does not contain any duplicates this function 
returns a #N/A error.")},
        { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
        { GNM_FUNC_HELP_EXAMPLES, "=MODE(11.4,17.3,11.4,3,25.9,40.1)" },
-       { GNM_FUNC_HELP_SEEALSO, "AVERAGE,MEDIAN"},
+       { GNM_FUNC_HELP_SEEALSO, "AVERAGE,MEDIAN,MODE.MULT"},
        { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Mode_(statistics)") },
        { GNM_FUNC_HELP_EXTREF, F_("wolfram:Mode.html") },
        { GNM_FUNC_HELP_END }
@@ -629,6 +630,104 @@ gnumeric_mode (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
 /***************************************************************************/
 
+static GnmFuncHelp const help_mode_mult[] = {
+       { GNM_FUNC_HELP_NAME, F_("MODE.MULT:most common numbers in the dataset")},
+       { GNM_FUNC_HELP_ARG, F_("number1:first value")},
+       { GNM_FUNC_HELP_ARG, F_("number2:second value")},
+       { GNM_FUNC_HELP_DESCRIPTION, F_("Strings and empty cells are simply ignored.")},
+       { GNM_FUNC_HELP_DESCRIPTION, F_("If the data set does not contain any duplicates this function 
returns a #N/A error.")},
+       { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
+       { GNM_FUNC_HELP_EXAMPLES, "=MODE.MULT(11.4,17.3,11.4,3,25.9,40.1)" },
+       { GNM_FUNC_HELP_SEEALSO, "AVERAGE,MEDIAN,MODE"},
+       { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Mode_(statistics)") },
+       { GNM_FUNC_HELP_EXTREF, F_("wolfram:Mode.html") },
+       { GNM_FUNC_HELP_END }
+};
+
+static gint
+gnumeric_mode_mult_cmp (gconstpointer a, gconstpointer b)
+{
+       return (((*((gnm_float *)a))<(*((gnm_float *)b))) ? -1 : 1);
+}
+
+static gboolean
+gnumeric_mode_mult_rm (gpointer key, gpointer value, gpointer user_data)
+{
+       return (*((int *)user_data) != *((int *)value));
+}
+
+static GnmValue *
+gnumeric_mode_mult (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
+{
+       GnmValue *error = NULL;
+       GnmValue *result;
+       gnm_float *vals;
+       int n;
+       gboolean constp;
+
+       vals = collect_floats (argc, argv, ei->pos, 
+                              COLLECT_IGNORE_STRINGS |
+                              COLLECT_IGNORE_BOOLS |
+                              COLLECT_IGNORE_BLANKS,
+                              &n, &error,
+                              NULL, &constp);
+       if (!vals)
+               return error;
+       
+       if (n <= 1)
+               result = value_new_error_NA (ei->pos);
+       else {
+               GHashTable *h;
+               int i;
+               int dups = 0;
+                       
+               h = g_hash_table_new_full ((GHashFunc)gnm_float_hash,
+                                          (GCompareFunc)gnm_float_equal,
+                                          NULL,
+                                          (GDestroyNotify)g_free);
+               for (i = 0; i < n; i++) {
+                       gpointer rval;
+                       gboolean found = g_hash_table_lookup_extended (h, &vals[i], NULL, &rval);
+                       int *pdups;
+                               
+                       if (found) {
+                               pdups = (int *)rval;
+                               (*pdups)++;
+                       } else {
+                               pdups = g_new (int, 1);
+                               *pdups = 1;
+                               g_hash_table_insert (h, (gpointer)(vals + i), pdups);
+                       }
+                               
+                       if (*pdups > dups)
+                               dups = *pdups;
+               }
+
+               if (dups <= 1)
+                       result = value_new_error_NA (ei->pos);
+               else {
+                       GList *keys, *l;
+                       
+                       g_hash_table_foreach_remove (h, gnumeric_mode_mult_rm, &dups);
+                       keys = g_hash_table_get_keys (h);
+
+                       keys = g_list_sort (keys, gnumeric_mode_mult_cmp);
+
+                       result = value_new_array (1,g_list_length (keys));
+                       i = 0;
+                       for (l = keys; l != NULL; l = l->next)
+                               value_array_set (result, 0, i++, value_new_float (*((gnm_float *)(l->data))));
+               }
+
+               g_hash_table_destroy (h);                       
+       }
+       
+       if (!constp) g_free (vals);
+
+       return result;
+}
+/***************************************************************************/
+
 static GnmFuncHelp const help_harmean[] = {
        { GNM_FUNC_HELP_NAME, F_("HARMEAN:harmonic mean")},
        { GNM_FUNC_HELP_ARG, F_("number1:first value")},
@@ -5394,6 +5493,10 @@ GnmFuncDescriptor const stat_functions[] = {
          help_mode, NULL, gnumeric_mode, NULL, NULL,
          GNM_FUNC_SIMPLE + GNM_FUNC_AUTO_FIRST,
          GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
+       { "mode.mult", NULL,
+         help_mode_mult, NULL, gnumeric_mode_mult, NULL, NULL,
+         GNM_FUNC_SIMPLE,
+         GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_NO_TESTSUITE},
        { "negbinomdist", "fff",
          help_negbinomdist, gnumeric_negbinomdist, NULL, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
diff --git a/plugins/fn-stat/plugin.xml.in b/plugins/fn-stat/plugin.xml.in
index da4bd2a..03ac774 100644
--- a/plugins/fn-stat/plugin.xml.in
+++ b/plugins/fn-stat/plugin.xml.in
@@ -73,6 +73,7 @@
                                <function name="min"/>
                                <function name="mina"/>
                                <function name="mode"/>
+                               <function name="mode.mult"/>
                                <function name="negbinomdist"/>
                                <function name="normdist"/>
                                <function name="norminv"/>
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index adcf3a1..b4a4698 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,9 @@
+2015-06-16  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+       * openoffice-read.c (oo_func_map_in): Add MODE.MULT
+       * openoffice-write.c (odf_expr_func_handler): Export MODE.MULT
+       with Microsoft prefix
+
 2015-06-15  Andreas J. Guelzow <aguelzow pyrshep ca>
 
        * openoffice-read.c (oo_func_map_in): Add PERCENTRANK.EXC and
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index 6037808..6d47625 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -13204,6 +13204,7 @@ oo_func_map_in (GnmConventions const *convs, Workbook *scope,
                { "HYPGEOM.DIST","HYPGEOMDIST" },
                { "LOGNORM.INV","LOGINV" },
                { "MODE.SNGL","MODE" },
+               { "MODE.MULT","MODE.MULT" },
                { "NORM.DIST","NORMDIST" },
                { "NORM.INV","NORMINV" },
                { "NORM.S.INV","NORMSINV" },
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index 62bb1a1..547458b 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -2462,6 +2462,7 @@ odf_expr_func_handler (GnmConventionsOut *out, GnmExprFunction const *func)
                { "MMULT","MMULT" },
                { "MOD","MOD" },
                { "MODE","MODE" },
+               { "MODE.MULT","COM.MICROSOFT.MODE.MULT" },
                { "MONTH","MONTH" },
                { "MROUND","MROUND" },
                { "MULTINOMIAL","MULTINOMIAL" },
diff --git a/src/collect.c b/src/collect.c
index 636d57d..8163ee2 100644
--- a/src/collect.c
+++ b/src/collect.c
@@ -427,7 +427,7 @@ callback_function_collect (GnmEvalPos const *ep, GnmValue const *value,
  * Evaluate a list of expressions and return the result as an array of
  * gnm_float.
  */
-static gnm_float *
+gnm_float *
 collect_floats (int argc, GnmExprConstPtr const *argv,
                GnmEvalPos const *ep, CollectFlags flags,
                int *n, GnmValue **error, GSList **info,
diff --git a/src/collect.h b/src/collect.h
index 4683a76..413f827 100644
--- a/src/collect.h
+++ b/src/collect.h
@@ -39,6 +39,10 @@ gnm_float *collect_floats_value (GnmValue const *val,
                                 GnmEvalPos const *ep,
                                 CollectFlags flags,
                                 int *n, GnmValue **error);
+gnm_float *collect_floats (int argc, GnmExprConstPtr const *argv,
+                          GnmEvalPos const *ep, CollectFlags flags,
+                          int *n, GnmValue **error, GSList **info,
+                          gboolean *constp);
 
 gnm_float *collect_floats_value_with_info (GnmValue const *val, GnmEvalPos const *ep,
                                CollectFlags flags, int *n, GSList **info,


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