[gnumeric] Fix some interpolation and periodogram issues.



commit aa8dd105ee02ae20ef7ecb4688e89c5c554f5693
Author: Jean Brefort <jean brefort normalesup org>
Date:   Sat Aug 21 12:41:34 2010 +0200

    Fix some interpolation and periodogram issues.

 NEWS                       |    3 +
 plugins/fn-tsa/ChangeLog   |    6 ++
 plugins/fn-tsa/functions.c |  187 +++++++++++++-------------------------------
 tools/win32/ChangeLog      |    6 ++
 tools/win32/moduleset.in   |    8 ++
 5 files changed, 78 insertions(+), 132 deletions(-)
---
diff --git a/NEWS b/NEWS
index 6beb52c..062cc71 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,9 @@ Andreas:
 	* Fix percentage style import from ODF. [#627517]
 	* Fix INTERPOLATION documentation. [#627461]
 
+Jean:
+	* Fix some interpolation and periodogram issues.
+
 --------------------------------------------------------------------------
 Gnumeric 1.10.9
 
diff --git a/plugins/fn-tsa/ChangeLog b/plugins/fn-tsa/ChangeLog
index 2c17c7e..b8cc72b 100644
--- a/plugins/fn-tsa/ChangeLog
+++ b/plugins/fn-tsa/ChangeLog
@@ -1,3 +1,9 @@
+2010-08-21  Jean Brefort  <jean brefort normalesup org>
+
+	* functions.c (linear_averaging), (staircase_averaging),
+	(spline_averaging), (gnumeric_interpolation),
+	(gnumeric_periodogram): fixed some interpolation issues.
+
 2010-08-20 Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* functions.c (help_interpolation): clarify the description
diff --git a/plugins/fn-tsa/functions.c b/plugins/fn-tsa/functions.c
index 3883d2e..d26ae4b 100644
--- a/plugins/fn-tsa/functions.c
+++ b/plugins/fn-tsa/functions.c
@@ -204,15 +204,15 @@ linear_averaging (const gnm_float *absc, const gnm_float *ord, int nb_knots,
 {
 	int i, j, k, jmax = nb_knots - 1;
 	gnm_float slope, *res, x0, x1;
-	if (nb_knots < 2 || !gnm_range_increasing (targets, nb_targets))
+	if (nb_knots < 2 || !gnm_range_increasing (targets, nb_targets + 1))
 		return NULL;
-	res = g_new (gnm_float, nb_targets - 1);
+	res = g_new (gnm_float, nb_targets);
 	j = 1;
 	while (j < jmax && targets[0] > absc[j])
 		j++;
 	k = j - 1;
 	slope = (ord[j] - ord[k]) / (absc[j] - absc[k]) / 2.;
-	for (i = 1; i < nb_targets; i++) {
+	for (i = 1; i <= nb_targets; i++) {
 		if (targets[i] < absc[j] || j == jmax) {
 			x0 = targets[i - 1] - absc[k];
 			x1 = targets[i] - absc[k];
@@ -290,13 +290,13 @@ staircase_averaging (const gnm_float *absc, const gnm_float *ord, int nb_knots,
 {
 	int i, j, jmax = nb_knots - 1;
 	gnm_float *res;
-	if (!gnm_range_increasing (targets, nb_targets))
+	if (!gnm_range_increasing (targets, nb_targets + 1))
 		return NULL;
-	res = g_new (gnm_float, nb_targets - 1);
+	res = g_new (gnm_float, nb_targets);
 	j = 1;
 	while (j <= jmax && targets[0] >= absc[j])
 		j++;
-	for (i = 1; i < nb_targets; i++) {
+	for (i = 1; i <= nb_targets; i++) {
 		if (targets[i] < absc[j] || j > jmax) {
 			res[i - 1] = ord[j - 1];
 			continue;
@@ -344,14 +344,14 @@ spline_averaging (const gnm_float *absc, const gnm_float *ord, int nb_knots,
 	gnm_float *res;
 	int i, imax;
 	GnmCSpline *sp;
-	if (!gnm_range_increasing (targets, nb_targets))
+	if (!gnm_range_increasing (targets, nb_targets + 1))
 		return NULL;
 	sp = gnm_cspline_init (absc, ord, nb_knots,
 			       GO_CSPLINE_NATURAL, 0., 0.);
 	if (!sp)
 		return NULL;
-	res = gnm_cspline_get_integrals (sp, targets, nb_targets);
-	imax = nb_targets - 1;
+	res = gnm_cspline_get_integrals (sp, targets, nb_targets + 1);
+	imax = nb_targets;
 	for (i = 0; i < imax; i++)
 		res[i] /= targets[i + 1] - targets[i];
 	gnm_cspline_destroy (sp);
@@ -360,8 +360,8 @@ spline_averaging (const gnm_float *absc, const gnm_float *ord, int nb_knots,
 
 /*******Interpolation procedure********/
 
-#define INTERPPROC(x) gnm_float* (*x) (const gnm_float*, const gnm_float*, \
-				       int, const gnm_float*, int)
+typedef  gnm_float* (*INTERPPROC) (const gnm_float*, const gnm_float*,
+				       int, const gnm_float*, int);
 
 /******************************************************************************/
 /*                    INTERPOLATION FUNCTION                               */
@@ -385,111 +385,26 @@ static GnmFuncHelp const help_interpolation[] = {
 	{ GNM_FUNC_HELP_END }
 };
 
-typedef struct {
-	guint		alloc_count;
-	guint		count;
-	guint		data_count;
-	gnm_float	*data;
-	guint		values_allocated;
-	guint		values_count;
-	GnmValue	**values;
-} collect_floats_t;
-
-static GnmValue *
-callback_function_collect (GnmEvalPos const *ep, GnmValue const *value,
-			   void *closure)
-{
-	gnm_float x;
-	GnmValue *val = NULL;
-	collect_floats_t *cl = (collect_floats_t *) closure;
-
-	if (value == NULL) {
-		cl->count++;
-		return NULL;
-	} else switch (value->type) {
-		case VALUE_EMPTY:
-			cl->count++;
-			return NULL;
-
-		case VALUE_ERROR:
-			val = value_dup (value);
-			break;
-
-		case VALUE_FLOAT:
-			x = value_get_as_float (value);
-			if (cl->data_count == cl->alloc_count) {
-				cl->alloc_count *= 2;
-				cl->data = g_realloc (cl->data, cl->alloc_count * sizeof (gnm_float));
-			}
-
-			cl->data[cl->data_count++] = x;
-			break;
-
-		default:
-			val = value_new_error_VALUE (ep);
-		}
-
-	while (cl->count >= cl->values_allocated) {
-		cl->values_allocated *= 2;
-		cl->values = g_realloc (cl->values, cl->values_allocated * sizeof (GnmValue*));
-	}
-	while (cl->count > cl->values_count)
-		cl->values[cl->values_count++] = value_new_error_NA (ep);
-	cl->values[cl->values_count++] = val;
-	cl->count++;
-
-	return NULL;
-}
-
-static gnm_float *
-_collect_floats (int argc, GnmExprConstPtr const *argv,
-		 GnmEvalPos const *ep, int *n, int *max, GnmValue ***values)
-{
-	collect_floats_t cl;
-	CellIterFlags iter_flags = CELL_ITER_ALL;
-
-	cl.alloc_count = 20;
-	cl.data = g_new (gnm_float, cl.alloc_count);
-	cl.count = cl.data_count = cl.values_count = 0;
-	cl.values_allocated = 20;
-	cl.values = g_new (GnmValue*, cl.values_allocated);
-
-	function_iterate_argument_values
-		(ep, &callback_function_collect, &cl,
-		 argc, argv,
-		 FALSE, iter_flags);
-
-	*n = cl.data_count;
-	*values = cl.values;
-	*max = cl.values_count;
-	return cl.data;
-}
-
 static GnmValue *
 gnumeric_interpolation (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
 	gnm_float *vals0, *vals1, *vals2, *fres;
-	int n0, n1, n2, nb;
+	int n0, n1, n2;
 	int interp;
 	GnmValue *error = NULL;
 	GnmValue *res;
-	GnmValue **values;
 	CollectFlags flags;
 	GnmEvalPos const * const ep = ei->pos;
 	GnmValue const * const PtInterpolation = argv[2];
-	int	r, i;
+	unsigned r, i;
 	GSList *missing0 = NULL;
 	GSList *missing1 = NULL;
-	INTERPPROC(interpproc) = NULL;
+	GSList *missing2 = NULL;
+	INTERPPROC interpproc = NULL;
 
 	int const cols = value_area_get_width (PtInterpolation, ep);
 	int const rows = value_area_get_height (PtInterpolation, ep);
 
-	/* Collect related variables */
-	GnmExpr expr_val;
-	GnmExprConstPtr argv_[1] = { &expr_val };
-	/* end of collect related variables */
-
 	if (rows == 0 || cols != 1) {
 		res = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
 		return res;
@@ -517,9 +432,9 @@ gnumeric_interpolation (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 	flags |= COLLECT_IGNORE_ERRORS;
 
 	/* start collecting targets */
-	gnm_expr_constant_init (&expr_val.constant, argv[2]);
-	vals2 = _collect_floats (1, argv_, ei->pos, &n2, &nb, &values);
-
+	vals2 = collect_floats_value_with_info (argv[2], ei->pos, flags,
+						&n2, &missing2, &error);
+	                                        
 	if (argv[3]) {
 		interp = (int) gnm_floor (value_get_as_float (argv[3]));
 		if (interp < 0 || interp > INTERPOLATION_SPLINE_AVG) {
@@ -527,8 +442,6 @@ gnumeric_interpolation (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 			g_slist_free (missing1);
 			g_free (vals0);
 			g_free (vals1);
-			for (i = 0; i < nb; i++)
-				value_release (values[i]);
 			return value_new_error_VALUE (ei->pos);
 		}
 	} else
@@ -559,9 +472,9 @@ gnumeric_interpolation (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 	}
 
 	if (n0 != n1 || n0 == 0 || n2 <= 0) {
+		g_slist_free (missing0);
+		g_slist_free (missing1);
 		res = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
-		for (i = 0; i < nb; i++)
-			value_release (values[i]);
 	} else {
 		if (missing0 || missing1) {
 			GSList *missing = gnm_slist_sort_merge (missing0, missing1);
@@ -579,37 +492,34 @@ gnumeric_interpolation (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 		   an error is returned */
 		if (!gnm_range_increasing (vals0, n0) || n2==0) {
 			res = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
-			for (i = 0; i < nb; i++)
-				value_release (values[i]);
-			g_free (values);
+			g_slist_free (missing2);
 			g_free (vals0);
 			g_free (vals1);
 			g_free (vals2);
 			return res;
 		}
-		res = value_new_array_non_init (1 , nb);
+		res = value_new_array_non_init (1 , n2);
 		i = 0;
 
-		res->v_array.vals[0] = g_new (GnmValue *, nb);
+		res->v_array.vals[0] = g_new (GnmValue *, n2);
 
 		fres = interpproc (vals0, vals1, n0, vals2, n2);
+		missing0 = missing2;
 		if (fres) {
 			i = 0;
-			for( r = 0 ; r < nb; ++r)
-				if (values[r])
-					res->v_array.vals[0][r] = values[r];
-				else {
+			for( r = 0 ; r < n2; ++r)
+				if (missing0 && r == GPOINTER_TO_UINT (missing0->data)) {
+					missing0 = missing0->next;
+					res->v_array.vals[0][r] = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
+				} else
 					res->v_array.vals[0][r] = value_new_float (fres[i++]);
-				}
 			g_free (fres);
 		} else {
-			for( r = 0 ; r < nb; ++r)
+			for( r = 0 ; r < n2; ++r)
 				res->v_array.vals[0][r] = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
-			for (i = 0; i < nb; i++)
-				value_release (values[i]);
 		}
 	}
-	g_free (values);
+	g_slist_free (missing2);
 	g_free (vals0);
 	g_free (vals1);
 	g_free (vals2);
@@ -701,10 +611,16 @@ gnumeric_periodogram (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 		filter = FILTER_NONE;
 
 	if (argv[2]) {
-		gnm_float *interpolated, start, incr;
+		gnm_float *interpolated, *new_ord, start, incr;
+		int n2;
 		INTERPPROC(interpproc) = NULL;
 		absc = collect_floats_value_with_info (argv[2], ei->pos, flags,
 						       &n1, &missing1, &error);
+		if (n1 == 1) {
+			g_slist_free (missing1);
+			g_free (absc);
+			goto no_absc;
+		}
 		if (error) {
 			g_slist_free (missing0);
 			g_slist_free (missing1);
@@ -740,9 +656,10 @@ gnumeric_periodogram (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 				g_warning ("This should not happen. n0=%d n1=%d\n",
 					   n0, n1);
 		}
+		n0 = n1 = MIN (n0, n1);
 		/* here we test if there is abscissas are always increasing, if not,
 		   an error is returned */
-		if (!gnm_range_increasing (absc, n0) || n0 == 0) {
+		if (n0 < 2 || !gnm_range_increasing (absc, n0) || n0 == 0) {
 			g_free (absc);
 			g_free (ord);
 			return value_new_error_std (ei->pos, GNM_ERROR_VALUE);
@@ -768,29 +685,32 @@ gnumeric_periodogram (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 		case INTERPOLATION_LINEAR:
 			interpproc = linear_interpolation;
 			start = absc[0];
+			n2 = n1;
 			break;
 		case INTERPOLATION_LINEAR_AVG:
 			interpproc = linear_averaging;
 			start = absc[0] - incr / 2.;
-			n1++;
+			n2 = n1 + 1;
 			break;
 		case INTERPOLATION_STAIRCASE:
 			interpproc = staircase_interpolation;
 			start = absc[0];
+			n2 = n1;
 			break;
 		case INTERPOLATION_STAIRCASE_AVG:
-			interpproc = linear_averaging;
+			interpproc = staircase_averaging;
 			start = absc[0] - incr / 2.;
-			n1++;
+			n2 = n1 + 1;
 			break;
 		case INTERPOLATION_SPLINE:
 			interpproc = spline_interpolation;
 			start = absc[0];
+			n2 = n1;
 			break;
 		case INTERPOLATION_SPLINE_AVG:
-			interpproc = linear_averaging;
+			interpproc = spline_averaging;
 			start = absc[0] - incr / 2.;
-			n1++;
+			n2 = n1 + 1;
 			break;
 		default:
 			g_free (absc);
@@ -798,17 +718,19 @@ gnumeric_periodogram (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 			return value_new_error_std (ei->pos, GNM_ERROR_NA);
 		}
 		interpolated = g_new (gnm_float, n1);
-		for (i = 0; i < n1; i++)
+		for (i = 0; i < n2; i++)
 			interpolated[i] = start + i * incr;
+		new_ord = interpproc (absc, ord, n0, interpolated, n1);
 		g_free (ord);
-		ord = interpproc (absc, ord, n0, interpolated, n1);
+		ord = new_ord;
 		if (ord == NULL) {
 			g_free (absc);
 			g_free (interpolated);
 			return value_new_error_std (ei->pos, GNM_ERROR_NA);
 		}
-		n0 = nb;
+		n0 = n1;
 	} else {
+no_absc:
 		/* we have no interpolation to apply, so just take the values */
 		if (missing0) {
 			gnm_strip_missing (ord, &n0, missing0);
@@ -843,8 +765,9 @@ gnumeric_periodogram (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 
 	/* Transform and return the result */
 	in = g_new0 (complex_t, nb);
-	for (i = 0; i < n0; i++)
+	for (i = 0; i < n0; i++){
 		in[i].re = ord[i];
+	}
 	g_free (ord);
 	gnm_fourier_fft (in, nb, 1, &out, FALSE);
 	g_free (in);
diff --git a/tools/win32/ChangeLog b/tools/win32/ChangeLog
index 3cacd83..a6da129 100644
--- a/tools/win32/ChangeLog
+++ b/tools/win32/ChangeLog
@@ -1,3 +1,9 @@
+2010-08-21  Jean Brefort  <jean brefort normalesup org>
+
+	reviewed by: <delete if not using a buddy>
+
+	* moduleset.in:
+
 2010-08-18  Morten Welinder <terra gnome org>
 
 	* jhbuildrc.py: Compile goffice without long-double support.
diff --git a/tools/win32/moduleset.in b/tools/win32/moduleset.in
index e4923d4..bee1016 100644
--- a/tools/win32/moduleset.in
+++ b/tools/win32/moduleset.in
@@ -351,6 +351,13 @@
 	</dependencies>
     </autotools>
 
+    <autotools id="librsvg">
+	<branch repo="gnome.org" module="sources/librsvg/2.26/librsvg-2.26.3.tar.bz2" version="2.26.3"/>
+	<dependencies>
+	    <dep package="gtk+"/>
+	</dependencies>
+    </autotools>
+
     <autotools id="goffice">
 	<branch/>
 	<dependencies>
@@ -359,6 +366,7 @@
 	    <dep package="pcre"/>
 	    <dep package="libxml2"/>
 	    <dep package="pango"/>
+	    <dep package="librsvg"/> <!-- not really true for now but we need it -->
 	    <!-- <dep package="lasem"/> -->
 	</dependencies>
     </autotools>



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