[goffice] Fixed flawed exponential fit in graphs for small values. [#633735]



commit e1d5d12da829a672a77664ac027984805af13e2a
Author: Jean Brefort <jean brefort normalesup org>
Date:   Mon Nov 1 21:07:30 2010 +0100

    Fixed flawed exponential fit in graphs for small values. [#633735]

 ChangeLog                        |   11 ++++++
 NEWS                             |    1 +
 goffice/math/go-regression.c     |   67 ++++++++++++++++++++++++++++++++++++++
 goffice/math/go-regression.h     |   12 ++++++-
 plugins/reg_linear/gog-exp-reg.c |   24 +++++++-------
 5 files changed, 102 insertions(+), 13 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 3899d50..f761862 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2010-11-01  Jean Brefort  <jean brefort normalesup org>
+
+	* goffice/math/go-regression.c (go_exponential_regression_as_log): new
+	regression utility returning the logarithms of the coefficients instead of
+	the coefficients to avoid roundint to 0 or infinite.
+	* goffice/math/go-regression.h: ditto.
+	* plugins/reg_linear/gog-exp-reg.c
+	(gog_exp_reg_curve_get_value_at), (gog_exp_reg_curve_get_equation),
+	(gog_exp_reg_curve_class_init): use go_exponential_regression_as_log.
+	[#633735]
+
 2010-10-26  Jean Brefort  <jean brefort normalesup org>
 
 	* goffice/utils/go-pattern.c (go_pattern_create_cairo_pattern): enclose
diff --git a/NEWS b/NEWS
index 67937d0..2675ca9 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ Jean:
 	* Fixed sorting with accentuated characters. [#631504]
 	* Allow filled plots to be displayed behind the grids. [#632310]
 	* Fixed patterns with cairo-1.10.
+	* Fixed flawed exponential fit in graphs for small values. [#633735]
 
 Morten:
 	* Fix GOImage-vs-cairo lifecycle issue.
diff --git a/goffice/math/go-regression.c b/goffice/math/go-regression.c
index 385394e..4ca70f1 100644
--- a/goffice/math/go-regression.c
+++ b/goffice/math/go-regression.c
@@ -1160,6 +1160,73 @@ SUFFIX(go_exponential_regression) (MATRIX xss, int dim,
 }
 
 /**
+ * go_exponential_regression_as_log:
+ * @xss: x-vectors (i.e. independent data)
+ * @dim: number of x-vectors
+ * @ys: y-vector (dependent data)
+ * @n: number of data points
+ * @affine: if %TRUE, a non-one multiplier is allowed
+ * @res: output place for constant[0] and root1[1], root2[2],... There will be dim+1 results.
+ * @stat_ : non-NULL storage for additional results.
+ *
+ * Performs one-dimensional linear regressions on the input points as 
+ * go_exponential_regression, but returns the logarithm of the coefficients instead
+ * or the coefficients themselves.
+ * Fits to "y = b * exp (m1*x1) * ... * exp (md*xd) " or equivalently to
+ * "ln y = ln b + x1 * m1 + ... + xd * md".
+ *
+ * Returns: #GORegressionResult as above.
+ **/
+GORegressionResult
+SUFFIX(go_exponential_regression_as_log) (MATRIX xss, int dim,
+				   const DOUBLE *ys, int n,
+				   gboolean affine,
+				   DOUBLE *res,
+				   SUFFIX(go_regression_stat_t) *stat_)
+{
+	DOUBLE *log_ys;
+	GORegressionResult result;
+	int i;
+
+	g_return_val_if_fail (dim >= 1, GO_REG_invalid_dimensions);
+	g_return_val_if_fail (n >= 1, GO_REG_invalid_dimensions);
+
+	log_ys = g_new (DOUBLE, n);
+	for (i = 0; i < n; i++)
+		if (ys[i] > 0)
+			log_ys[i] = SUFFIX(log) (ys[i]);
+		else {
+			result = GO_REG_invalid_data;
+			goto out;
+		}
+
+	if (affine) {
+		int i;
+		DOUBLE **xss2 = g_new (DOUBLE *, dim + 1);
+
+		xss2[0] = g_new (DOUBLE, n);
+		for (i = 0; i < n; i++)
+			xss2[0][i] = 1;
+		memcpy (xss2 + 1, xss, dim * sizeof (DOUBLE *));
+
+		result = SUFFIX(general_linear_regression)
+			(xss2, dim + 1, log_ys,
+			 n, res, stat_, affine);
+		g_free (xss2[0]);
+		g_free (xss2);
+	} else {
+		res[0] = 0;
+		result = SUFFIX(general_linear_regression)
+			(xss, dim, log_ys, n,
+			 res + 1, stat_, affine);
+	}
+
+ out:
+	g_free (log_ys);
+	return result;
+}
+ 
+/**
  * go_power_regression:
  * @xss: x-vectors (i.e. independent data)
  * @dim: number of x-vectors
diff --git a/goffice/math/go-regression.h b/goffice/math/go-regression.h
index 573085d..ea80650 100644
--- a/goffice/math/go-regression.h
+++ b/goffice/math/go-regression.h
@@ -48,6 +48,11 @@ GORegressionResult 	 go_exponential_regression 	(double **xss, int dim,
 							 gboolean affine,
 							 double *res,
 							 go_regression_stat_t *stat_);
+GORegressionResult 	 go_exponential_regression_as_log 	(double **xss, int dim,
+							 const double *ys, int n,
+							 gboolean affine,
+							 double *res,
+							 go_regression_stat_t *stat_);
 GORegressionResult 	 go_power_regression 	(double **xss, int dim,
 							 const double *ys, int n,
 							 gboolean affine,
@@ -129,7 +134,12 @@ GORegressionResult    go_linear_regressionl   	(long double **xss, int dim,
 						 gboolean affine,
 						 long double *res,
 						 go_regression_stat_tl *stat_);
-GORegressionResult    go_exponential_regressionl(long double **xss, int dim,
+GORegressionResult    go_exponential_regressionl	(long double **xss, int dim,
+						 const long double *ys, int n,
+						 gboolean affine,
+						 long double *res,
+						 go_regression_stat_tl *stat_);
+GORegressionResult    go_exponential_regression_as_logl	(long double **xss, int dim,
 						 const long double *ys, int n,
 						 gboolean affine,
 						 long double *res,
diff --git a/plugins/reg_linear/gog-exp-reg.c b/plugins/reg_linear/gog-exp-reg.c
index 1227037..ead1298 100644
--- a/plugins/reg_linear/gog-exp-reg.c
+++ b/plugins/reg_linear/gog-exp-reg.c
@@ -30,7 +30,7 @@
 static double
 gog_exp_reg_curve_get_value_at (GogRegCurve *curve, double x)
 {
-	return curve->a[0] * pow (curve->a[1], x);
+	return exp (curve->a[0] + curve->a[1] * x);
 }
 
 static gchar const*
@@ -39,17 +39,17 @@ gog_exp_reg_curve_get_equation (GogRegCurve *curve)
 	if (!curve->equation) {
 		GogLinRegCurve *lin = GOG_LIN_REG_CURVE (curve);
 		if (lin->affine)
-			curve->equation = (curve->a[0] < 1.)?
-				((curve->a[1] < 1.)?
-					g_strdup_printf ("ln(y) = \xE2\x88\x92%gx \xE2\x88\x92 %g", -log (curve->a[1]), -log (curve->a[0])):
-					g_strdup_printf ("ln(y) = %gx \xE2\x88\x92% g", log (curve->a[1]), -log (curve->a[0]))):
-				((curve->a[1] < 1.)?
-					g_strdup_printf ("ln(y) = \xE2\x88\x92%gx + %g", -log (curve->a[1]), log (curve->a[0])):
-					g_strdup_printf ("ln(y) = %gx + %g", log (curve->a[1]), log (curve->a[0])));
+			curve->equation = (curve->a[0] < 0.)?
+				((curve->a[1] < 0.)?
+					g_strdup_printf ("ln(y) = \xE2\x88\x92%gx \xE2\x88\x92 %g", -curve->a[1], -curve->a[0]):
+					g_strdup_printf ("ln(y) = %gx \xE2\x88\x92% g", curve->a[1], -curve->a[0])):
+				((curve->a[1] < 0.)?
+					g_strdup_printf ("ln(y) = \xE2\x88\x92%gx + %g", -curve->a[1], curve->a[0]):
+					g_strdup_printf ("ln(y) = %gx + %g", curve->a[1], curve->a[0]));
 		else
-			curve->equation = (curve->a[1] < 1.)?
-				g_strdup_printf ("ln(y) = \xE2\x88\x92%gx", -log (curve->a[1])):
-				g_strdup_printf ("ln(y) = %gx", log (curve->a[1]));
+			curve->equation = (curve->a[1] < 0.)?
+				g_strdup_printf ("ln(y) = \xE2\x88\x92%gx", -curve->a[1]):
+				g_strdup_printf ("ln(y) = %gx", curve->a[1]);
 	}
 	return curve->equation;
 }
@@ -69,7 +69,7 @@ gog_exp_reg_curve_class_init (GogRegCurveClass *reg_curve_klass)
 	GogLinRegCurveClass *lin_reg_klass = (GogLinRegCurveClass *) reg_curve_klass;
 	GogObjectClass *gog_object_klass = (GogObjectClass *) reg_curve_klass;
 
-	lin_reg_klass->lin_reg_func = go_exponential_regression;
+	lin_reg_klass->lin_reg_func = go_exponential_regression_as_log;
 
 	reg_curve_klass->get_value_at = gog_exp_reg_curve_get_value_at;
 	reg_curve_klass->get_equation = gog_exp_reg_curve_get_equation;



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