Commit 38d08d9b authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

When requested, sort.

2008-07-23  Morten Welinder  <terra@gnome.org>

	* src/collect.c (collect_floats): When requested, sort.

2008-07-23  Morten Welinder  <terra@gnome.org>

	* functions.c: (gnumeric_small, gnumeric_large,
	gnumeric_percentile, gnumeric_quartile, gnumeric_trimmean): Use
	new COLLECT_SORT and simplify.
	(gnumeric_trimmean): Change to an argv function and simplify
	greatly.
	(gnumeric_rank, gnumeric_min, gnumeric_max, gnumeric_maxa,
	gnumeric_mina, gnumeric_percentrank): Use new
	COLLECT_ORDER_IRRELEVANT.


svn path=/trunk/; revision=16723
parent 0c254575
2008-07-23 Morten Welinder <terra@gnome.org>
* src/collect.c (collect_floats): When requested, sort.
2008-07-19 Jody Goldberg <jody@gnome.org>
* tools/win32/gnumeric.nsi.in : enclose the gnumeric path in quotes
too. [#542872]
* tools/win32/gnumeric.nsi.in : enclose the gnumeric path in
quotes too. [#542872]
2008-07-10 Morten Welinder <terra@gnome.org>
......
......@@ -17,6 +17,7 @@ Morten:
* Fix MATCH problem with singletons. [#540996]
* Fix DDB problems. [#541158]
* Make ssgrep a lot more grep-like.
* Unify functions that work on sorted ranges.
--------------------------------------------------------------------------
Gnumeric 1.9.1
......
2008-07-23 Morten Welinder <terra@gnome.org>
* functions.c: (gnumeric_small, gnumeric_large,
gnumeric_percentile, gnumeric_quartile, gnumeric_trimmean): Use
new COLLECT_SORT and simplify.
(gnumeric_trimmean): Change to an argv function and simplify
greatly.
(gnumeric_rank, gnumeric_min, gnumeric_max, gnumeric_maxa,
gnumeric_mina, gnumeric_percentrank): Use new
COLLECT_ORDER_IRRELEVANT.
2008-06-25 Jody Goldberg <jody@gnome.org>
* Release 1.9.1
......
......@@ -237,7 +237,8 @@ gnumeric_rank (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
xs = collect_floats_value (argv[1], ei->pos,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_ORDER_IRRELEVANT,
&n, &result);
order = argv[2] ? value_get_as_int (argv[2]) : 0;
......@@ -281,39 +282,32 @@ static GnmFuncHelp const help_trimmean[] = {
{ GNM_FUNC_HELP_END }
};
static int
range_trimmean (gnm_float const *xs, int n, gnm_float *res)
static GnmValue *
gnumeric_trimmean (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
{
gnm_float p;
int tc, c;
int c, tc, n;
GnmValue *result = NULL;
gnm_float *xs = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS |
COLLECT_SORT,
&n, &result);
gnm_float p = value_get_as_float (argv[1]);
gnm_float res;
if (n < 2)
return 1;
if (result)
return result;
p = xs[--n];
if (p < 0 || p > 1)
return 1;
return value_new_error_VALUE (ei->pos);
tc = gnm_fake_floor ((n * p) / 2);
tc = (int)gnm_fake_floor ((n * p) / 2);
c = n - 2 * tc;
if (c == 0)
return 1;
/* OK, so we ignore the constness here. Tough. */
qsort ((gnm_float *) xs, n, sizeof (xs[0]), (void *) &float_compare);
if (gnm_range_average (xs + tc, c, &res))
return value_new_error_VALUE (ei->pos);
return gnm_range_average (xs + tc, c, res);
}
static GnmValue *
gnumeric_trimmean (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
{
return float_range_function (argc, argv, ei,
range_trimmean,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
GNM_ERROR_VALUE);
return value_new_float (res);
}
/***************************************************************************/
......@@ -869,7 +863,8 @@ gnumeric_min (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
range_min0,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_ORDER_IRRELEVANT,
GNM_ERROR_VALUE);
}
......@@ -913,7 +908,8 @@ gnumeric_max (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
range_max0,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_ORDER_IRRELEVANT,
GNM_ERROR_VALUE);
}
......@@ -2481,10 +2477,11 @@ static GnmValue *
gnumeric_median (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
{
return float_range_function (argc, argv, ei,
(float_range_function_t)gnm_range_median_inter_nonconst,
gnm_range_median_inter_sorted,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_SORT,
GNM_ERROR_NUM);
}
......@@ -2628,20 +2625,25 @@ static GnmFuncHelp const help_large[] = {
static GnmValue *
gnumeric_large (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
{
int n_vals;
gnm_float val, k;
GnmValue *res = NULL;
gnm_float *vals = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_BOOLS | COLLECT_IGNORE_BLANKS,
&n_vals, &res);
int n;
GnmValue *res = NULL;
gnm_float *xs = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS |
COLLECT_SORT,
&n, &res);
gnm_float k = value_get_as_float (argv[1]);
if (res)
return res;
if (1. <= (k = value_get_as_float (argv[1])) &&
0 == gnm_range_min_k_nonconst (vals, n_vals, &val, n_vals - gnm_fake_ceil (k)))
res = value_new_float (val);
k = gnm_fake_ceil (k);
if (k >= 1 && k <= n)
res = value_new_float (xs[n - (int)k]);
else
res = value_new_error_NUM (ei->pos);
g_free (vals);
g_free (xs);
return res;
}
......@@ -2680,20 +2682,25 @@ static GnmFuncHelp const help_small[] = {
static GnmValue *
gnumeric_small (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
{
int n_vals;
gnm_float val, k;
GnmValue *res = NULL;
gnm_float *vals = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_BOOLS | COLLECT_IGNORE_BLANKS,
&n_vals, &res);
int n;
GnmValue *res = NULL;
gnm_float *xs = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS |
COLLECT_SORT,
&n, &res);
gnm_float k = value_get_as_float (argv[1]);
if (res)
return res;
if (1. <= (k = value_get_as_float (argv[1])) &&
0 == gnm_range_min_k_nonconst (vals, n_vals, &val, gnm_fake_ceil (k) - 1))
res = value_new_float (val);
k = gnm_fake_ceil (k);
if (k >= 1 && k <= n)
res = value_new_float (xs[(int)k - 1]);
else
res = value_new_error_NUM (ei->pos);
g_free (vals);
g_free (xs);
return res;
}
......@@ -3118,7 +3125,8 @@ gnumeric_maxa (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
gnm_range_max,
COLLECT_ZERO_STRINGS |
COLLECT_ZEROONE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_ORDER_IRRELEVANT,
GNM_ERROR_VALUE);
}
......@@ -3156,7 +3164,8 @@ gnumeric_mina (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
gnm_range_min,
COLLECT_ZERO_STRINGS |
COLLECT_ZEROONE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_ORDER_IRRELEVANT,
GNM_ERROR_VALUE);
}
......@@ -3371,7 +3380,8 @@ gnumeric_percentrank (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
data = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_ORDER_IRRELEVANT,
&n, &result);
x = value_get_as_float (argv[1]);
significance = argv[2] ? value_get_as_float (argv[2]) : 3;
......@@ -3472,13 +3482,14 @@ gnumeric_percentile (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
data = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_SORT,
&n, &result);
if (!result) {
gnm_float p = value_get_as_float (argv[1]);
gnm_float res;
if (gnm_range_fractile_inter_nonconst (data, n, &res, p))
if (gnm_range_fractile_inter_sorted (data, n, &res, p))
result = value_new_error_NUM (ei->pos);
else
result = value_new_float (res);
......@@ -3531,13 +3542,14 @@ gnumeric_quartile (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
data = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
COLLECT_IGNORE_BLANKS,
COLLECT_IGNORE_BLANKS |
COLLECT_SORT,
&n, &result);
if (!result) {
int q = value_get_as_int (argv[1]);
gnm_float q = gnm_fake_floor (value_get_as_float (argv[1]));
gnm_float res;
if (gnm_range_fractile_inter_nonconst (data, n, &res, q / 4.0))
if (gnm_range_fractile_inter_sorted (data, n, &res, q / 4.0))
result = value_new_error_NUM (ei->pos);
else
result = value_new_float (res);
......@@ -5935,8 +5947,8 @@ GnmFuncDescriptor const stat_functions[] = {
{ "trend", "A|AAb", N_("known_y's,known_x's,new_x's,const"),
help_trend, gnumeric_trend, NULL, NULL, NULL, NULL,
GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
{ "trimmean", NULL, N_("ref,fraction"),
help_trimmean, NULL, gnumeric_trimmean, NULL, NULL, NULL,
{ "trimmean", "rf", N_("ref,fraction"),
help_trimmean, gnumeric_trimmean, NULL, NULL, NULL, NULL,
GNM_FUNC_SIMPLE + GNM_FUNC_AUTO_FIRST,
GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
{ "ttest", "rrff", N_("array1,array2,tails,type"),
......
......@@ -19,9 +19,24 @@
#include "sheet.h"
#include "number-match.h"
#include <goffice/utils/go-glib-extras.h>
#include <stdlib.h>
/* ------------------------------------------------------------------------- */
static int
float_compare (const void *a_, const void *b_)
{
gnm_float const *a = a_;
gnm_float const *b = b_;
if (*a < *b)
return -1;
else if (*a == *b)
return 0;
else
return 1;
}
typedef struct {
guint alloc_count;
gnm_float *data;
......@@ -148,6 +163,7 @@ collect_floats (int argc, GnmExprConstPtr const *argv,
CellIterFlags iter_flags = CELL_ITER_ALL;
if (info) {
g_return_val_if_fail (!(flags & COLLECT_SORT), NULL);
flags |= COLLECT_INFO;
*info = NULL;
} else {
......@@ -182,9 +198,14 @@ collect_floats (int argc, GnmExprConstPtr const *argv,
cl.data = g_new (gnm_float, cl.alloc_count);
}
if (flags & COLLECT_SORT) {
qsort (cl.data, cl.count, sizeof (cl.data[0]), float_compare);
}
if (info)
*info = cl.info;
*n = cl.count;
return cl.data;
}
......
......@@ -20,6 +20,9 @@ typedef enum {
COLLECT_IGNORE_BLANKS = 0x1000,
COLLECT_IGNORE_SUBTOTAL = 0x2000,
COLLECT_SORT = 0x10000,
COLLECT_ORDER_IRRELEVANT = 0x20000,
/* Not for general usage. */
COLLECT_INFO = 0x1000000
} CollectFlags;
......
......@@ -474,32 +474,3 @@ gnm_range_mode (gnm_float const *xs, int n, gnm_float *res)
*res = mode;
return 0;
}
static gint
float_compare (gnm_float const *a, const gnm_float *b)
{
if (*a < *b)
return -1;
else if (*a == *b)
return 0;
else
return 1;
}
/* k-th smallest. Note: k is zero-based. */
/* This version may reorder data points. */
int
gnm_range_min_k_nonconst (gnm_float *xs, int n, gnm_float *res, int k)
{
if (k < 0 || k >= n)
return 1;
if (k == 0)
return gnm_range_min (xs, n, res);
if (k == n - 1)
return gnm_range_max (xs, n, res);
qsort (xs, n, sizeof (xs[0]), (int (*) (const void *, const void *))&float_compare);
*res = xs[k];
return 0;
}
......@@ -15,10 +15,9 @@ G_BEGIN_DECLS
# define gnm_range_max go_range_maxl
# define gnm_range_maxabs go_range_maxabsl
# define gnm_range_devsq go_range_devsql
# define gnm_range_fractile_inter go_range_fractile_interl
# define gnm_range_fractile_inter_nonconst go_range_fractile_inter_nonconstl
# define gnm_range_fractile_inter_sorted go_range_fractile_inter_sortedl
# define gnm_range_median_inter go_range_median_interl
# define gnm_range_median_inter_nonconst go_range_median_inter_nonconstl
# define gnm_range_median_inter_sorted go_range_median_inter_sortedl
#else
# define gnm_range_sum go_range_sum
# define gnm_range_sumsq go_range_sumsq
......@@ -27,10 +26,9 @@ G_BEGIN_DECLS
# define gnm_range_max go_range_max
# define gnm_range_maxabs go_range_maxabs
# define gnm_range_devsq go_range_devsq
# define gnm_range_fractile_inter go_range_fractile_inter
# define gnm_range_fractile_inter_nonconst go_range_fractile_inter_nonconst
# define gnm_range_fractile_inter_sorted go_range_fractile_inter_sorted
# define gnm_range_median_inter go_range_median_inter
# define gnm_range_median_inter_nonconst go_range_median_inter_nonconst
# define gnm_range_median_inter_sorted go_range_median_inter_sorted
#endif
int gnm_range_count (gnm_float const *xs, int n, gnm_float *res);
......@@ -63,8 +61,6 @@ int gnm_range_rsq_est (gnm_float const *xs, const gnm_float *ys, int n, gnm_floa
int gnm_range_mode (gnm_float const *xs, int n, gnm_float *res);
int gnm_range_min_k_nonconst (gnm_float *xs, int n, gnm_float *res, int k);
G_END_DECLS
#endif /* _GNM_RANGEFUNC_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment