[gnumeric] Non-linar solver: fix crash.



commit cbb505d7d91c6b690dcfaa0dae29a1f51a218af6
Author: Morten Welinder <terra gnome org>
Date:   Fri Jul 27 17:20:20 2012 -0400

    Non-linar solver: fix crash.

 NEWS                          |    1 +
 plugins/nlsolve/ChangeLog     |    5 +++++
 plugins/nlsolve/gnm-nlsolve.c |   14 ++++++++++----
 src/rangefunc.c               |    6 ++++++
 4 files changed, 22 insertions(+), 4 deletions(-)
---
diff --git a/NEWS b/NEWS
index af2a9dd..49ae6f2 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ Morten:
 	* Fix xls read crash.  [#679992]
 	* Reduce code duplication for dependents.
 	* Make cells regular dependents.
+	* Fix non-linear solver crash.  [#680719]
 
 --------------------------------------------------------------------------
 Gnumeric 1.11.5
diff --git a/plugins/nlsolve/ChangeLog b/plugins/nlsolve/ChangeLog
index 3d25675..c1e4425 100644
--- a/plugins/nlsolve/ChangeLog
+++ b/plugins/nlsolve/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-27  Morten Welinder  <terra gnome org>
+
+	* gnm-nlsolve.c (rosenbrock_iter): Fix crash and marginally
+	improve precision.
+
 2012-07-15  Morten Welinder <terra gnome org>
 
 	* Release 1.11.5
diff --git a/plugins/nlsolve/gnm-nlsolve.c b/plugins/nlsolve/gnm-nlsolve.c
index 5879bab..ac061ed 100644
--- a/plugins/nlsolve/gnm-nlsolve.c
+++ b/plugins/nlsolve/gnm-nlsolve.c
@@ -536,10 +536,16 @@ rosenbrock_iter (GnmNlsolve *nl)
 				}
                 }
 
-                div = sqrt (t[0]);
-                for (i = 0; i < n; i++) {
-			nl->xi[0][i] = A[0][i] / div;
-			g_assert (gnm_finite (nl->xi[0][i]));
+		gnm_range_hypot (dx, n, &div);
+		if (div != 0) {
+			for (i = 0; i < n; i++) {
+				nl->xi[0][i] = A[0][i] / div;
+				if (!gnm_finite (nl->xi[0][i])) {
+					g_printerr ("%g %g %g\n",
+						    div, A[0][i], nl->xi[0][i]);
+					g_assert (gnm_finite (nl->xi[0][i]));
+				}
+			}
 		}
 
 		/* ---------------------------------------- */
diff --git a/src/rangefunc.c b/src/rangefunc.c
index 4d7e708..2a36a72 100644
--- a/src/rangefunc.c
+++ b/src/rangefunc.c
@@ -26,6 +26,12 @@ gnm_range_count (G_GNUC_UNUSED gnm_float const *xs, int n, gnm_float *res)
 int
 gnm_range_hypot (gnm_float const *xs, int n, gnm_float *res)
 {
+	/* Drop outside zeros because the n<=2 cases are more accurate.  */
+	while (n > 0 && xs[0] == 0)
+		xs++, n--;
+	while (n > 0 && xs[n - 1] == 0)
+		n--;
+
 	switch (n) {
 	case 0: *res = 0; return 0;
 	case 1: *res = gnm_abs (xs[0]); return 0;



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