[goffice] Regression: check sign of R-squared as a sanity check.



commit a9ef640bb8273f209d92c996ee66b0b259f62a31
Author: Morten Welinder <terra gnome org>
Date:   Tue May 10 09:55:15 2011 -0400

    Regression: check sign of R-squared as a sanity check.

 ChangeLog                    |    6 ++++++
 NEWS                         |    1 +
 goffice/math/go-regression.c |   29 +++++++++++++++++++++++------
 3 files changed, 30 insertions(+), 6 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index af13161..ce4bd78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-05-10  Morten Welinder  <terra gnome org>
+
+	* goffice/math/go-regression.c (general_linear_regression): Always
+	compute stat information.  If we get negative R-squared, mark
+	result as bad.
+
 2011-05-06  Jean Brefort  <jean brefort normalesup org>
 
 	* goffice/utils/go-marker.c (go_marker_create_cairo_surface): don't
diff --git a/NEWS b/NEWS
index f74dbd8..59ffcfb 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ Jean:
 
 Morten:
 	* Plug leaks.
+	* Detect more cases of linear-regression gone bad.
 
 --------------------------------------------------------------------------
 goffice 0.8.14:
diff --git a/goffice/math/go-regression.c b/goffice/math/go-regression.c
index 0675a37..fc65f80 100644
--- a/goffice/math/go-regression.c
+++ b/goffice/math/go-regression.c
@@ -676,14 +676,20 @@ SUFFIX(general_linear_regression) (CONSTMATRIX xss, int xdim,
 	int i,j;
 	gboolean has_result;
 	void *state;
+	gboolean has_stat;
 
 	ZERO_VECTOR (result, xdim);
 
-	if (stat_)
-		memset (stat_, 0, sizeof (stat_));
+	has_stat = (stat_ != NULL);
+	if (!has_stat)
+		stat_ = SUFFIX(go_regression_stat_new)();
 
-	if (xdim > n)
-		return GO_REG_not_enough_data;
+	memset (stat_, 0, sizeof (stat_));
+
+	if (xdim > n) {
+		regerr = GO_REG_not_enough_data;
+		goto out;
+	}
 
 	state = SUFFIX(go_quad_start) ();
 
@@ -726,7 +732,7 @@ SUFFIX(general_linear_regression) (CONSTMATRIX xss, int xdim,
 		}
 	}
 
-	if (stat_ && has_result) {
+	if (has_result) {
 		GORegressionResult err2;
 		QUAD *inv = g_new (QUAD, xdim);
 		int err;
@@ -757,6 +763,14 @@ SUFFIX(general_linear_regression) (CONSTMATRIX xss, int xdim,
 		stat_->sqr_r = (stat_->ss_total == 0)
 			? 1
 			: 1 - stat_->ss_resid / stat_->ss_total;
+		if (stat_->sqr_r < 0) {
+			/*
+			 * This is an indication that something has gone wrong
+			 * numerically.
+			 */
+			regerr = GO_REG_near_singular_bad;
+		}
+
 		/* FIXME: we want to guard against division by zero.  */
 		stat_->adj_sqr_r = 1 - stat_->ss_resid * (n - 1) /
 			((n - xdim) * stat_->ss_total);
@@ -803,7 +817,7 @@ SUFFIX(general_linear_regression) (CONSTMATRIX xss, int xdim,
 				g_printerr ("inv[%d]=%" FORMAT_g "\n",
 					    k,
 					    SUFFIX(go_quad_value) (&inv[k]));
-				//regerr = GO_REG_near_singular_bad;
+				regerr = GO_REG_near_singular_bad;
 			}
 			{
 				QUAD p;
@@ -845,6 +859,9 @@ SUFFIX(general_linear_regression) (CONSTMATRIX xss, int xdim,
 	g_free (qresult);
 	FREE_MATRIX (Q, xdim, n);
 	FREE_MATRIX (R, xdim, xdim);
+out:
+	if (!has_stat)
+		SUFFIX(go_regression_stat_destroy) (stat_);
 #endif
 
 	return regerr;



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