[gnumeric] SMALL, LARGE: It's an error to ask for the 0.9th element



commit 3c38f06f2cf690fca4b91dc09026545173e64794
Author: Morten Welinder <terra gnome org>
Date:   Wed Mar 9 13:00:55 2022 -0500

    SMALL, LARGE: It's an error to ask for the 0.9th element
    
    For numbers larger than 1, we round up.  That's XL semantics for you.

 NEWS                        |  1 +
 plugins/fn-stat/ChangeLog   |  5 +++++
 plugins/fn-stat/functions.c | 30 ++++++++++++++++++++++--------
 3 files changed, 28 insertions(+), 8 deletions(-)
---
diff --git a/NEWS b/NEWS
index 6297a065b..7a65890c4 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,7 @@ Morten:
        * Fix leak.
        * Fix old problem saving column widths.  [#619]
        * Set default number of sheets to 1.
+       * Fix edge error case for SMALL and LARGE.  [#620]
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.51
diff --git a/plugins/fn-stat/ChangeLog b/plugins/fn-stat/ChangeLog
index 2864b2086..15f2a817f 100644
--- a/plugins/fn-stat/ChangeLog
+++ b/plugins/fn-stat/ChangeLog
@@ -1,3 +1,8 @@
+2022-03-09  Morten Welinder  <terra gnome org>
+
+       * functions.c (gnumeric_small, gnumeric_large): Fix strange edge
+       error case.
+
 2022-01-20  Morten Welinder <terra gnome org>
 
        * Release 1.12.51
diff --git a/plugins/fn-stat/functions.c b/plugins/fn-stat/functions.c
index f98b63ce9..403c55a1c 100644
--- a/plugins/fn-stat/functions.c
+++ b/plugins/fn-stat/functions.c
@@ -2374,6 +2374,22 @@ static GnmFuncHelp const help_large[] = {
        { GNM_FUNC_HELP_END }
 };
 
+static int
+gnm_kth (gnm_float k)
+{
+       if (k < 1)
+               // This just makes us get an error unless we're very
+               // close to 1.
+               k = gnm_fake_floor (k);
+       else
+               k = gnm_fake_ceil (k);
+
+       if (k < 1 || k >= INT_MAX)
+               return 0;
+       else
+               return (int)k;
+}
+
 static GnmValue *
 gnumeric_large (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
@@ -2385,13 +2401,12 @@ gnumeric_large (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
                                              COLLECT_IGNORE_BLANKS |
                                              COLLECT_SORT,
                                              &n, &res);
-       gnm_float k = value_get_as_float (argv[1]);
+       int ki = gnm_kth (value_get_as_float (argv[1]));
        if (res)
                return res;
 
-       k = gnm_fake_ceil (k);
-       if (k >= 1 && k <= n)
-               res = value_new_float (xs[n - (int)k]);
+       if (ki >= 1 && ki <= n)
+               res = value_new_float (xs[n - ki]);
        else
                res = value_new_error_NUM (ei->pos);
 
@@ -2429,13 +2444,12 @@ gnumeric_small (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
                                              COLLECT_IGNORE_BLANKS |
                                              COLLECT_SORT,
                                              &n, &res);
-       gnm_float k = value_get_as_float (argv[1]);
+       int ki = gnm_kth (value_get_as_float (argv[1]));
        if (res)
                return res;
 
-       k = gnm_fake_ceil (k);
-       if (k >= 1 && k <= n)
-               res = value_new_float (xs[(int)k - 1]);
+       if (ki >= 1 && ki <= n)
+               res = value_new_float (xs[ki - 1]);
        else
                res = value_new_error_NUM (ei->pos);
 


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