genius r653 - in trunk: . src



Author: jirka
Date: Tue May 20 05:25:01 2008
New Revision: 653
URL: http://svn.gnome.org/viewvc/genius?rev=653&view=rev

Log:

Tue May 20 00:25:10 2008  Jiri (George) Lebl <jirka 5z com>

	* src/matrixw.[ch], matop.c, src/eval.c, src/funclib.c:  Optimize
	  matrix manipulation a bit.  Don't be overly conservative with
	  making things private.  And OMG we used Gauss-Jordan instead of
	  backaddition.  Also when the matrix is not rational, do pivotting
	  (use largest entry, not first nonzero one)

	* src/mpwrap.c: fix mpw_abs if called with same arguments for in and
	  out and add mpw_abs_sq for getting the absolute value squared,
	  which doesn't involve a sqrt

	* src/genius.c, src/gnome-genius.c, src/eval.[ch], src/matrixw.c: 
	  init the_zero during the startup

	* src/mpzextra.c: very minor optimizations

	* src/Makefile.am: fix BUILDDIR setup



Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/src/Makefile.am
   trunk/src/eval.c
   trunk/src/eval.h
   trunk/src/funclib.c
   trunk/src/genius.c
   trunk/src/gnome-genius.c
   trunk/src/matop.c
   trunk/src/matrixw.c
   trunk/src/matrixw.h
   trunk/src/mpwrap.c
   trunk/src/mpwrap.h
   trunk/src/mpzextra.c

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Tue May 20 05:25:01 2008
@@ -6,6 +6,9 @@
 * QuadraticFormula built in and more numerically stable
 * CHANGE: It's Fibonacci in correct spelling, short name is still fib
 * Calling internal functions is now slightly faster
+* Gaussian elimination is now faster, and more stable when nonrational
+  matrices are involved
+* Other minor optimizations
 * Fix crash related to returning custom functions from functions
 * Fix some memory leaks
 * Documentation updates

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Tue May 20 05:25:01 2008
@@ -13,7 +13,7 @@
 	-DG_LOG_DOMAIN=\"Genius\"				\
 	-DDATADIR=\""$(datadir)"\"				\
 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
-	-DBUILDDIR=\""$(abs_top_builddir)"\"			\
+	-DBUILDDIR=\""@abs_top_builddir@"\"			\
 	-I$(srcdir)						\
 	-I$(top_srcdir)						\
 	-I$(top_srcdir)/ve					\

Modified: trunk/src/eval.c
==============================================================================
--- trunk/src/eval.c	(original)
+++ trunk/src/eval.c	Tue May 20 05:25:01 2008
@@ -259,6 +259,13 @@
 	return 0;
 }
 
+void
+gel_init (void)
+{
+	if (the_zero == NULL)
+		the_zero = gel_makenum_ui (0);
+}
+
 mpw_ptr
 gel_find_pre_function_modulo (GelCtx *ctx)
 {
@@ -987,7 +994,7 @@
 		} else if(gel_matrixw_width(et->mat.matrix) == 1) {
 			int xx;
 			int h = gel_matrixw_height(et->mat.matrix);
-			gel_matrixw_make_private(et->mat.matrix);
+			gel_matrixw_make_private (et->mat.matrix, FALSE /* kill_type_caches */);
 			for(x=0;x<h;x++) {
 				gel_matrix_index(dest,i,di+x) =
 					gel_matrixw_get_index(et->mat.matrix,0,x);
@@ -1007,7 +1014,8 @@
 			int h = gel_matrixw_height(et->mat.matrix);
 			int w = gel_matrixw_width(et->mat.matrix);
 
-			gel_matrixw_make_private(et->mat.matrix);
+			gel_matrixw_make_private(et->mat.matrix,
+						 FALSE /* kill_type_caches */);
 
 			for(x=0;x<h;x++) {
 				GelETree *n;
@@ -1198,7 +1206,7 @@
 		/* never should be reached */
 	}
 
-	gel_matrixw_make_private (nm);
+	gel_matrixw_make_private (nm, FALSE /* kill_type_caches */);
 
 	m = gel_matrix_new();
 	gel_matrix_set_size(m, w, h, TRUE /* padding */);
@@ -1767,7 +1775,7 @@
 		node = l;
 	}
 
-	gel_matrixw_make_private(m);
+	gel_matrixw_make_private(m, TRUE /* kill_type_caches */);
 
 	for(j=0;j<gel_matrixw_height(m);j++) {
 		for(i=0;i<gel_matrixw_width(m);i++) {
@@ -1829,7 +1837,7 @@
 		return TRUE;
 	}
 
-	gel_matrixw_make_private(m);
+	gel_matrixw_make_private(m, TRUE /* kill_type_caches */);
 
 	for (i = 0; i < gel_matrixw_width (m); i++) {
 		GelETree *t = gel_matrixw_get_index(m,i,i);
@@ -1860,7 +1868,7 @@
 	int i,j;
 	GelMatrixW *m = l->mat.matrix;
 
-	gel_matrixw_make_private(m);
+	gel_matrixw_make_private(m, TRUE /* kill_type_caches */);
 
 	for(j=0;j<gel_matrixw_height(m);j++) {
 		for(i=0;i<gel_matrixw_width(m);i++) {
@@ -1927,7 +1935,7 @@
 		return TRUE;
 	}
 	l->mat.quoted = l->mat.quoted || r->mat.quoted;
-	gel_matrixw_make_private(m1);
+	gel_matrixw_make_private(m1, TRUE /* kill_type_caches */);
 	for(j=0;j<gel_matrixw_height(m1);j++) {
 		for(i=0;i<gel_matrixw_width(m1);i++) {
 			GelETree *t = gel_matrixw_get_index (m1, i, j);
@@ -2315,7 +2323,7 @@
 	int w,h;
 
 	/*make us a private copy!*/
-	gel_matrixw_make_private(m);
+	gel_matrixw_make_private(m, TRUE /* kill_type_caches */);
 
 	w = gel_matrixw_width (m);
 	h = gel_matrixw_height (m);
@@ -2394,11 +2402,9 @@
 static gboolean
 conjugate_transpose_matrix (GelCtx *ctx, GelETree *n, GelETree *l)
 {
-	if (gel_is_matrix_value_only_real (l->mat.matrix)) {
-		l->mat.matrix->tr = !(l->mat.matrix->tr);
-	} else {
-		gel_matrix_conjugate_transpose (l->mat.matrix);
-	}
+	/* handles real case nicely */
+	gel_matrix_conjugate_transpose (l->mat.matrix);
+
 	/*remove from arglist*/
 	n->op.args = NULL;
 	replacenode(n,l);
@@ -4408,7 +4414,7 @@
 			    t->type != USERTYPE_NODE) {
 				if ( ! pushed) {
 					/*make us a private copy!*/
-					gel_matrixw_make_private (m);
+					gel_matrixw_make_private (m, TRUE /* kill_type_caches */);
 
 					/* it will be a copy */
 					t = gel_matrixw_get_index (m, x, y);
@@ -6651,12 +6657,13 @@
 			}
 		}
 	} else if (n->type == MATRIX_NODE &&
-		   n->mat.matrix != NULL) {
+		   n->mat.matrix != NULL &&
+		   ! gel_is_matrix_value_only (n->mat.matrix)) {
 		int i,j;
 		int w,h;
 		w = gel_matrixw_width (n->mat.matrix);
 		h = gel_matrixw_height (n->mat.matrix);
-		gel_matrixw_make_private (n->mat.matrix);
+		gel_matrixw_make_private (n->mat.matrix, TRUE /* kill_type_caches */);
 		for (i = 0; i < w; i++) {
 			for(j = 0; j < h; j++) {
 				GelETree *t = gel_matrixw_get_index
@@ -7028,11 +7035,13 @@
 	} else if(n->type==MATRIX_NODE) {
 		int i,j;
 		int w,h;
-		if(!n->mat.matrix)
+		if(!n->mat.matrix ||
+		   gel_is_matrix_value_only (n->mat.matrix)) {
 			goto gather_comparisons_end;
+		}
 		w = gel_matrixw_width(n->mat.matrix);
 		h = gel_matrixw_height(n->mat.matrix);
-		gel_matrixw_make_private(n->mat.matrix);
+		gel_matrixw_make_private(n->mat.matrix, TRUE /* kill_type_caches */);
 		for(j=0;j<h;j++) {
 			for(i=0;i<w;i++) {
 				GelETree *t = gel_matrixw_get_index(n->mat.matrix,i,j);
@@ -7102,12 +7111,13 @@
 			}
 		}
 	} else if (n->type == MATRIX_NODE &&
-		   n->mat.matrix != NULL) {
+		   n->mat.matrix != NULL &&
+		   ! gel_is_matrix_value_only (n->mat.matrix)) {
 		int i,j;
 		int w,h;
 		w = gel_matrixw_width (n->mat.matrix);
 		h = gel_matrixw_height (n->mat.matrix);
-		gel_matrixw_make_private (n->mat.matrix);
+		gel_matrixw_make_private (n->mat.matrix, TRUE /* kill_type_caches */);
 		for(j = 0; j < h; j++) {
 			for (i = 0; i < w; i++) {
 				GelETree *t = gel_matrixw_get_index
@@ -7153,12 +7163,13 @@
 			args = args->any.next;
 		}
 	} else if (n->type == MATRIX_NODE &&
-		   n->mat.matrix != NULL) {
+		   n->mat.matrix != NULL &&
+		   ! gel_is_matrix_value_only (n->mat.matrix)) {
 		int i,j;
 		int w,h;
 		w = gel_matrixw_width (n->mat.matrix);
 		h = gel_matrixw_height (n->mat.matrix);
-		gel_matrixw_make_private (n->mat.matrix);
+		gel_matrixw_make_private (n->mat.matrix, TRUE /* kill_type_caches */);
 		for(j = 0; j < h; j++) {
 			for (i = 0; i < w; i++) {
 				GelETree *t = gel_matrixw_get_index
@@ -7212,12 +7223,13 @@
 			}
 		}
 	} else if (n->type == MATRIX_NODE &&
-		   n->mat.matrix != NULL) {
+		   n->mat.matrix != NULL &&
+		   ! gel_is_matrix_value_only (n->mat.matrix)) {
 		int i,j;
 		int w,h;
 		w = gel_matrixw_width (n->mat.matrix);
 		h = gel_matrixw_height (n->mat.matrix);
-		gel_matrixw_make_private (n->mat.matrix);
+		gel_matrixw_make_private (n->mat.matrix, TRUE /* kill_type_caches */);
 		for(j = 0; j < h; j++) {
 			for (i = 0; i < w; i++) {
 				GelETree *t = gel_matrixw_get_index
@@ -7460,10 +7472,12 @@
 	} else if(n->type==MATRIX_NODE) {
 		int i,j;
 		int w,h;
-		if(!n->mat.matrix) return;
+		if (n->mat.matrix == NULL ||
+		    gel_is_matrix_value_only (n->mat.matrix))
+			return;
 		w = gel_matrixw_width(n->mat.matrix);
 		h = gel_matrixw_height(n->mat.matrix);
-		gel_matrixw_make_private(n->mat.matrix);
+		gel_matrixw_make_private (n->mat.matrix, TRUE /* kill_type_caches */);
 		for(j=0;j<h;j++) {
 			for(i=0;i<w;i++) {
 				GelETree *t = gel_matrixw_get_index(n->mat.matrix,i,j);
@@ -7944,10 +7958,12 @@
 	} else if(n->type==MATRIX_NODE) {
 		int i,j;
 		int w,h;
-		if(!n->mat.matrix) return;
+		if (n->mat.matrix == NULL ||
+		    gel_is_matrix_value_only (n->mat.matrix))
+			return;
 		w = gel_matrixw_width(n->mat.matrix);
 		h = gel_matrixw_height(n->mat.matrix);
-		gel_matrixw_make_private(n->mat.matrix);
+		gel_matrixw_make_private (n->mat.matrix, TRUE /* kill_type_caches */);
 		for(j=0;j<h;j++) {
 			for(i=0;i<w;i++) {
 				GelETree *t = gel_matrixw_get_index(n->mat.matrix,i,j);

Modified: trunk/src/eval.h
==============================================================================
--- trunk/src/eval.h	(original)
+++ trunk/src/eval.h	Tue May 20 05:25:01 2008
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2007 Jiri (George) Lebl
+ * Copyright (C) 1997-2008 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -128,6 +128,8 @@
 	GelOperPrim prim[OP_TABLE_LEN];
 };
 
+void gel_init (void);
+
 /*functions for manipulating a tree*/
 GelETree * gel_makenum(mpw_t num);
 GelETree * gel_makenum_use(mpw_t num); /*don't create a new number*/

Modified: trunk/src/funclib.c
==============================================================================
--- trunk/src/funclib.c	(original)
+++ trunk/src/funclib.c	Tue May 20 05:25:01 2008
@@ -200,7 +200,7 @@
 
 	GET_NEW_NODE (n);
 	n->type = MATRIX_NODE;
-	n->mat.matrix = gel_matrixw_new_with_matrix (m);
+	n->mat.matrix = gel_matrixw_new_with_matrix_value_only_integer (m);
 	n->mat.quoted = FALSE;
 
 	return n;
@@ -560,7 +560,7 @@
 
 		GET_NEW_NODE (n);
 		n->type = MATRIX_NODE;
-		n->mat.matrix = gel_matrixw_new_with_matrix (m);
+		n->mat.matrix = gel_matrixw_new_with_matrix_value_only_real_nonrational (m);
 		n->mat.quoted = FALSE;
 
 		return n;
@@ -594,7 +594,7 @@
 
 		GET_NEW_NODE (n);
 		n->type = MATRIX_NODE;
-		n->mat.matrix = gel_matrixw_new_with_matrix (m);
+		n->mat.matrix = gel_matrixw_new_with_matrix_value_only_real_nonrational (m);
 		n->mat.quoted = FALSE;
 
 		return n;
@@ -666,7 +666,7 @@
 
 		GET_NEW_NODE (n);
 		n->type = MATRIX_NODE;
-		n->mat.matrix = gel_matrixw_new_with_matrix (m);
+		n->mat.matrix = gel_matrixw_new_with_matrix_value_only_integer (m);
 		n->mat.quoted = FALSE;
 
 		return n;
@@ -711,7 +711,7 @@
 
 		GET_NEW_NODE (n);
 		n->type = MATRIX_NODE;
-		n->mat.matrix = gel_matrixw_new_with_matrix (m);
+		n->mat.matrix = gel_matrixw_new_with_matrix_value_only_integer (m);
 		n->mat.quoted = FALSE;
 
 		return n;
@@ -3015,7 +3015,7 @@
 
 	GET_NEW_NODE (n);
 	n->type = MATRIX_NODE;
-	n->mat.matrix = gel_matrixw_new_with_matrix (nm);
+	n->mat.matrix = gel_matrixw_new_with_matrix_value_only_integer (nm);
 	if (a[0]->type == MATRIX_NODE)
 		n->mat.quoted = a[0]->mat.quoted;
 	else
@@ -3393,7 +3393,7 @@
 
 	GET_NEW_NODE (n);
 	n->type = MATRIX_NODE;
-	n->mat.matrix = gel_matrixw_new_with_matrix (nm);
+	n->mat.matrix = gel_matrixw_new_with_matrix_value_only_integer (nm);
 	n->mat.quoted = FALSE;
 
 	g_free (cols);
@@ -3508,7 +3508,7 @@
 
 	GET_NEW_NODE (n);
 	n->type = MATRIX_NODE;
-	n->mat.matrix = gel_matrixw_new_with_matrix (nm);
+	n->mat.matrix = gel_matrixw_new_with_matrix_value_only (nm);
 	n->mat.quoted = FALSE;
 
 	return n;
@@ -4264,7 +4264,7 @@
 	gel_matrixw_set_size (mn, size, 1);
 
 	rem = gel_matrixw_copy (pm);
-	gel_matrixw_make_private (rem);
+	gel_matrixw_make_private (rem, TRUE /* kill_type_caches */);
 
 	/* we know ql can't be zero */
 	ql = gel_matrixw_index (qm, sizeq-1, 0);
@@ -4487,7 +4487,7 @@
 
 	GET_NEW_NODE (n);
 	n->type = MATRIX_NODE;
-	n->mat.matrix = gel_matrixw_new_with_matrix (nm);
+	n->mat.matrix = gel_matrixw_new_with_matrix_value_only (nm);
 	n->mat.quoted = FALSE;
 
 	return n;
@@ -4916,7 +4916,7 @@
 
 	GET_NEW_NODE (n);
 	n->type = MATRIX_NODE;
-	n->mat.matrix = gel_matrixw_new_with_matrix (mm);
+	n->mat.matrix = gel_matrixw_new_with_matrix_value_only_integer (mm);
 	n->mat.quoted = FALSE;
 
 	return n;

Modified: trunk/src/genius.c
==============================================================================
--- trunk/src/genius.c	(original)
+++ trunk/src/genius.c	Tue May 20 05:25:01 2008
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2007 Jiri (George) Lebl
+ * Copyright (C) 1997-2008 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -440,6 +440,8 @@
 	  dictionary*/
 	d_singlecontext ();
 
+	gel_init ();
+
 	if ( ! (do_compile || do_gettext)) {
 		/*
 		 * Read main library

Modified: trunk/src/gnome-genius.c
==============================================================================
--- trunk/src/gnome-genius.c	(original)
+++ trunk/src/gnome-genius.c	Tue May 20 05:25:01 2008
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2007 Jiri (George) Lebl
+ * Copyright (C) 1997-2008 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -4085,6 +4085,8 @@
 	  dictionary*/
 	d_singlecontext ();
 
+	gel_init ();
+
 	gel_add_graph_functions ();
 
 	/*

Modified: trunk/src/matop.c
==============================================================================
--- trunk/src/matop.c	(original)
+++ trunk/src/matop.c	Tue May 20 05:25:01 2008
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2007 Jiri (George) Lebl
+ * Copyright (C) 1997-2008 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -201,7 +201,13 @@
 gel_matrix_conjugate_transpose (GelMatrixW *m)
 {
 	int i, j, w, h;
-	gel_matrixw_make_private (m);
+
+	if (gel_is_matrix_value_only_real (m)) {
+		m->tr = !m->tr;
+		return;
+	}
+
+	gel_matrixw_make_private (m, FALSE /* kill_type_caches */);
 	m->tr = !m->tr;
 	w = gel_matrixw_width (m);
 	h = gel_matrixw_height (m);
@@ -238,7 +244,7 @@
 	int i, j, k, w, h, m1w;
 	mpw_t tmp;
 	mpw_init(tmp);
-	gel_matrixw_make_private(res);
+	gel_matrixw_make_private(res, TRUE /* kill_type_caches */);
 
 	w = gel_matrixw_width (res);
 	h = gel_matrixw_height (res);
@@ -283,13 +289,15 @@
 	mpw_clear(tmp);
 }
 
+/* m must be made private before */
 static void
 swap_rows(GelMatrixW *m, int row, int row2)
 {
 	int i, w;
 	if(row==row2) return;
 	
-	gel_matrixw_make_private(m);
+	/* no need for this, only used within gauss and matrix is already private
+	gel_matrixw_make_private(m);*/
 	
 	w = gel_matrixw_width (m);
 	for (i = 0; i < w; i++) {
@@ -299,6 +307,7 @@
 	}
 }
 
+/* m must be made private before */
 static gboolean
 div_row (GelCtx *ctx, GelMatrixW *m, int row, mpw_t div)
 {
@@ -308,7 +317,8 @@
 	if (mpw_eql_ui (div, 1))
 		return TRUE;
 
-	gel_matrixw_make_private(m);
+	/* no need for this, only used within gauss and matrix is already private
+	gel_matrixw_make_private(m);*/
 	
 	w = gel_matrixw_width (m);
 	for (i = 0; i < w; i++) {
@@ -326,6 +336,7 @@
 	return ret;
 }
 
+/* m must be made private before */
 static gboolean
 mul_sub_row (GelCtx *ctx, GelMatrixW *m, int row, mpw_t mul, int row2)
 {
@@ -333,7 +344,8 @@
 	mpw_t tmp;
 	gboolean ret = TRUE;
 	
-	gel_matrixw_make_private(m);
+	/* no need for this, only used within gauss and matrix is already private
+	gel_matrixw_make_private(m);*/
 	
 	mpw_init(tmp);
 	w = gel_matrixw_width(m);
@@ -378,34 +390,84 @@
 	mpw_t tmp;
 	gboolean ret = TRUE;
 	gboolean made_private = FALSE;
+	gboolean matrix_rational = FALSE;
+	int *pivots = NULL;
+	int pivots_max = -1;
 	
 	if(detop)
 		mpw_set_ui(detop,1);
 
+	matrix_rational = gel_is_matrix_value_only_rational (m);
+
 	mpw_init(tmp);
 	d = 0;
 	w = gel_matrixw_width (m);
         h = gel_matrixw_height (m);
+
+	if (reduce) {
+		pivots = g_new0 (int, h);
+	}
+
 	for (i = 0; i < w && d < h; i++) {
-		for (j = d; j < h; j++) {
-			GelETree *t = gel_matrixw_get_index(m,i,j);
-			if (t != NULL &&
-			    ! mpw_zero_p (t->val.value))
-				break;
+		if (matrix_rational) {
+			for (j = d; j < h; j++) {
+				GelETree *t = gel_matrixw_get_index(m,i,j);
+				if (t != NULL &&
+				    ! mpw_zero_p (t->val.value))
+					break;
+			}
+		} else {
+			/* kind of a hack */
+			int bestj = h;
+			mpw_t best_abs_sq;
+			mpw_init (best_abs_sq);
+			GelETree *bestpiv = NULL;
+			for (j = d; j < h; j++) {
+				GelETree *t = gel_matrixw_get_index(m,i,j);
+				if (t != NULL &&
+				    ! mpw_zero_p (t->val.value)) {
+					if (bestpiv == NULL) {
+						bestpiv = t;
+						bestj = j;
+					} else {
+						mpw_abs_sq (tmp, t->val.value);
+						if (mpw_cmp (tmp, best_abs_sq) > 0) {
+							bestpiv = t;
+							bestj = j;
+						}
+					}
+				}
+			}
+			mpw_clear (best_abs_sq);
+
+			j = bestj;
 		}
 
 		if (j == h) {
 			ret = FALSE;
 			if(stopsing) {
 				mpw_clear(tmp);
+				g_free (pivots);
 				return FALSE;
 			}
 			continue;
 		}
 
 		if ( ! made_private) {
-			gel_matrixw_make_private(m);
+			gel_matrixw_make_private (m, TRUE /* kill_type_caches */);
+			if (simul)
+				gel_matrixw_make_private (simul, TRUE /* kill_type_caches */);
 			made_private = TRUE;
+
+			/* the matrix will be value only */
+			m->cached_value_only = 1;
+			m->value_only = 1;
+
+			if (matrix_rational) {
+				/* the matrix will be value only rational */
+				m->cached_value_only_rational = 1;
+				m->value_only_rational = 1;
+			}
 		}
 		
 		if (j > d) {
@@ -431,9 +493,10 @@
 					return FALSE;
 				}
 				if(simul) {
-					if ( !  mul_sub_row (ctx, simul, d, tmp, j) &&
+					if ( ! mul_sub_row (ctx, simul, d, tmp, j) &&
 					     stopsing) {
 						mpw_clear(tmp);
+						g_free (pivots);
 						return FALSE;
 					}
 				}
@@ -448,27 +511,11 @@
 		}
 
 		if(reduce) {
-			for(j=0;j<d;j++) {
-				GelETree *t = gel_matrixw_get_index(m,i,j);
-				if (t != NULL &&
-				    ! mpw_zero_p (t->val.value)) {
-					mpw_div(tmp,t->val.value,piv->val.value);
-					if ( ! mul_sub_row (ctx, m, d, tmp, j) &&
-					     stopsing) {
-						mpw_clear(tmp);
-						return FALSE;
-					}
-					if(simul) {
-						if ( !  mul_sub_row (ctx, simul, d, tmp, j) &&
-						     stopsing) {
-							mpw_clear(tmp);
-							return FALSE;
-						}
-					}
-				}
-			}
+			pivots[d] = i;
+			pivots_max = d;
 		}
 
+		/* make pivot 1 */
 		for (ii = i+1; ii < w; ii++) {
 			GelETree *t = gel_matrixw_get_index(m,ii,d);
 			if(t) {
@@ -481,6 +528,7 @@
 					    t != NULL &&
 					    t->type != VALUE_NODE) {
 						mpw_clear(tmp);
+						g_free (pivots);
 						return FALSE;
 					}
 				}
@@ -492,20 +540,50 @@
 			if ( ! div_row (ctx, simul, d, piv->val.value) &&
 			    stopsing) {
 				mpw_clear(tmp);
+				g_free (pivots);
 				return FALSE;
 			}
 		}
-
 		mpw_set_ui(piv->val.value,1);
 		d++;
 	}
 
+	if(reduce) {
+		for(d = pivots_max; d >= 0; d--) {
+			i = pivots[d];
+			for(j=0;j<d;j++) {
+				GelETree *t = gel_matrixw_get_index(m,i,j);
+				if (t != NULL &&
+				    ! mpw_zero_p (t->val.value)) {
+					/* subtle: must copy t->val.value,
+					 * else we wipe it out */
+					mpw_set (tmp, t->val.value);
+					if ( ! mul_sub_row (ctx, m, d, tmp, j) &&
+					     stopsing) {
+						mpw_clear(tmp);
+						g_free (pivots);
+						return FALSE;
+					}
+					if(simul) {
+						if ( ! mul_sub_row (ctx, simul, d, tmp, j) &&
+						     stopsing) {
+							mpw_clear(tmp);
+							g_free (pivots);
+							return FALSE;
+						}
+					}
+				}
+			}
+		}
+	}
+
 	if (detop && ctx->modulo != NULL) {
 		/* FIXME: this may fail!!! */
 		gel_mod_integer_rational (detop, ctx->modulo);
 	}
 	
 	mpw_clear(tmp);
+	g_free (pivots);
 	return ret;
 }
 

Modified: trunk/src/matrixw.c
==============================================================================
--- trunk/src/matrixw.c	(original)
+++ trunk/src/matrixw.c	Tue May 20 05:25:01 2008
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2007 Jiri (George) Lebl
+ * Copyright (C) 1997-2008 Jiri (George) Lebl
  *
  * Author: George Lebl
  *
@@ -45,7 +45,8 @@
 	GelMatrixWFreeList *next;
 };
 
-static void internal_make_private (GelMatrixW *m, int w, int h);
+static void internal_make_private (GelMatrixW *m, int w, int h,
+				   gboolean kill_type_caches);
 
 static GelMatrixWFreeList *free_matrices = NULL;
 
@@ -142,9 +143,6 @@
 	m->regw = m->m->width;
 	m->regh = m->m->height;
 	
-	if (the_zero == NULL)
-		the_zero = gel_makenum_ui (0);
-	
 	return m;
 }
 GelMatrixW *
@@ -159,7 +157,6 @@
 	m->m = mat;
 	m->m->use++;
 
-	/* clear caches as we're gonna mess with this matrix */
 	m->cached_value_only = 0;
 	m->cached_value_only_real = 0;
 	m->cached_value_only_rational = 0;
@@ -173,8 +170,100 @@
 	m->regw = m->m->width;
 	m->regh = m->m->height;
 	
-	if (the_zero == NULL)
-		the_zero = gel_makenum_ui (0);
+	return m;
+}
+
+GelMatrixW *
+gel_matrixw_new_with_matrix_value_only (GelMatrix *mat)
+{
+	GelMatrixW *m;
+	NEW_MATRIX (m);
+#ifdef MATRIX_DEBUG
+	/*debug*/printf ("%s\n", G_GNUC_PRETTY_FUNCTION);
+#endif
+	
+	m->m = mat;
+	m->m->use++;
+
+	m->cached_value_only = 1;
+	m->value_only = 1;
+	m->cached_value_only_real = 0;
+	m->cached_value_only_rational = 0;
+	m->cached_value_only_integer = 0;
+	m->cached_value_or_bool_only = 0;
+	m->rref = 0;
+	
+	m->tr = 0;
+	m->regx = NULL;
+	m->regy = NULL;
+	m->regw = m->m->width;
+	m->regh = m->m->height;
+	
+	return m;
+}
+
+GelMatrixW *
+gel_matrixw_new_with_matrix_value_only_integer (GelMatrix *mat)
+{
+	GelMatrixW *m;
+	NEW_MATRIX (m);
+#ifdef MATRIX_DEBUG
+	/*debug*/printf ("%s\n", G_GNUC_PRETTY_FUNCTION);
+#endif
+	
+	m->m = mat;
+	m->m->use++;
+
+	m->cached_value_only = 1;
+	m->value_only = 1;
+	m->cached_value_only_real = 1;
+	m->value_only_real = 1;
+	m->cached_value_only_rational = 1;
+	m->value_only_rational = 1;
+	m->cached_value_only_integer = 1;
+	m->value_only_integer = 1;
+	m->cached_value_or_bool_only = 1;
+	m->value_or_bool_only = 1;
+	m->rref = 0;
+	
+	m->tr = 0;
+	m->regx = NULL;
+	m->regy = NULL;
+	m->regw = m->m->width;
+	m->regh = m->m->height;
+	
+	return m;
+}
+
+GelMatrixW *
+gel_matrixw_new_with_matrix_value_only_real_nonrational (GelMatrix *mat)
+{
+	GelMatrixW *m;
+	NEW_MATRIX (m);
+#ifdef MATRIX_DEBUG
+	/*debug*/printf ("%s\n", G_GNUC_PRETTY_FUNCTION);
+#endif
+	
+	m->m = mat;
+	m->m->use++;
+
+	m->cached_value_only = 1;
+	m->value_only = 1;
+	m->cached_value_only_real = 1;
+	m->value_only_real = 1;
+	m->cached_value_only_rational = 1;
+	m->value_only_rational = 0;
+	m->cached_value_only_integer = 1;
+	m->value_only_integer = 0;
+	m->cached_value_or_bool_only = 1;
+	m->value_or_bool_only = 1;
+	m->rref = 0;
+	
+	m->tr = 0;
+	m->regx = NULL;
+	m->regy = NULL;
+	m->regw = m->m->width;
+	m->regh = m->m->height;
 	
 	return m;
 }
@@ -436,7 +525,9 @@
 	} else if (m->m->use > 1) {
 		/* since the use is greater than 1, we WILL get a copy of
 		 * this matrix at the right size */
-		internal_make_private (m, width, height);
+		/* it may seem we could leave caches alone, but changing size
+		 * could make those values different */
+		internal_make_private (m, width, height, TRUE /* kill_type_caches */);
 		g_assert (m->m->use == 1);
 	} else /* m->m->use == 1 */{
 		ensure_at_least_size (m, width, height);
@@ -463,7 +554,7 @@
 
 	if (width > m->regw || height > m->regh) {
 		/* FIXME: this may be a bit inefficent */
-		gel_matrixw_make_private (m);
+		gel_matrixw_make_private (m, TRUE /* kill_type_caches */);
 		make_us_a_copy (m, MAX (width, m->regw),MAX (height, m->regh));
 		ensure_at_least_size (m, width, height);
 	}
@@ -483,9 +574,11 @@
 #endif
 
 	if (m->tr)
-		internal_make_private (m, MAX(m->regh, y+1), MAX(m->regw, x+1));
+		internal_make_private (m, MAX(m->regh, y+1), MAX(m->regw, x+1),
+				       TRUE /* kill_type_caches */);
 	else
-		internal_make_private (m, MAX(m->regw, x+1), MAX(m->regh, y+1));
+		internal_make_private (m, MAX(m->regw, x+1), MAX(m->regh, y+1),
+				       TRUE /* kill_type_caches */);
 	gel_matrixw_set_at_least_size (m, x+1, y+1);
 	t = gel_matrixw_get_index (m, x, y);
 	if (t != NULL)
@@ -511,7 +604,8 @@
 			x = i % m->regh;
 			y = i / m->regh;
 		}
-		internal_make_private (m, MAX(m->regh, y+1), MAX(m->regw, x+1));
+		internal_make_private (m, MAX(m->regh, y+1), MAX(m->regw, x+1),
+				       TRUE /* kill_type_caches */);
 	} else {
 		if (m->regh == 1) {
 			x = i;
@@ -520,7 +614,8 @@
 			x = i % m->regw;
 			y = i / m->regw;
 		}
-		internal_make_private (m, MAX(m->regw, x+1), MAX(m->regh, y+1));
+		internal_make_private (m, MAX(m->regw, x+1), MAX(m->regh, y+1),
+				       TRUE /* kill_type_caches */);
 	}
 	gel_matrixw_set_at_least_size (m, x+1, y+1);
 	t = gel_matrixw_get_index (m, x, y);
@@ -663,7 +758,8 @@
 
 	/* FIXME: we will copy some nodes we don't need to copy
 	 * as we will free them just below */
-	internal_make_private (m, MAX (xmax+1, m->regw), MAX (ymax+1, m->regh));
+	internal_make_private (m, MAX (xmax+1, m->regw), MAX (ymax+1, m->regh),
+			       TRUE /* kill_type_caches */);
 	ensure_at_least_size (m, xmax+1, ymax+1);
 	/* assume that's what ensure/make_us_a_copy does */
 	g_assert (m->regx == NULL && m->regy == NULL);
@@ -726,7 +822,8 @@
 	xmax = getmax (destx, w);
 	ymax = getmax (desty, h);
 
-	internal_make_private (m, MAX (xmax+1, m->regw), MAX (ymax+1, m->regh));
+	internal_make_private (m, MAX (xmax+1, m->regw), MAX (ymax+1, m->regh),
+			       TRUE /* kill_type_caches */);
 	ensure_at_least_size (m, xmax+1, ymax+1);
 	/* assume that's what ensure/make_us_a_copy does */
 	g_assert (m->regx == NULL && m->regy == NULL);
@@ -899,18 +996,21 @@
 
 /*make private copy of the GelMatrix*/
 static void
-internal_make_private (GelMatrixW *m, int w, int h)
+internal_make_private (GelMatrixW *m, int w, int h, gboolean kill_type_caches)
 {
 #ifdef MATRIX_DEBUG
 	/*debug*/printf ("%s\n", G_GNUC_PRETTY_FUNCTION);
 #endif
 
-	/* clear caches as we're gonna mess with this matrix */
-	m->cached_value_only = 0;
-	m->cached_value_only_real = 0;
-	m->cached_value_only_rational = 0;
-	m->cached_value_only_integer = 0;
-	m->cached_value_or_bool_only = 0;
+	if (kill_type_caches) {
+		/* clear caches as we're gonna mess with this matrix */
+		m->cached_value_only = 0;
+		m->cached_value_only_real = 0;
+		m->cached_value_only_rational = 0;
+		m->cached_value_only_integer = 0;
+		m->cached_value_or_bool_only = 0;
+	}
+
 	m->rref = 0;
 
 #ifdef MATRIX_DEBUG
@@ -934,14 +1034,14 @@
 
 /*make private copy of the GelMatrix*/
 void
-gel_matrixw_make_private (GelMatrixW *m)
+gel_matrixw_make_private (GelMatrixW *m, gboolean kill_type_caches)
 {
 	g_return_if_fail(m != NULL);
 #ifdef MATRIX_DEBUG
 	/*debug*/printf ("%s\n", G_GNUC_PRETTY_FUNCTION);
 #endif
 
-	internal_make_private (m, m->regw, m->regh);
+	internal_make_private (m, m->regw, m->regh, kill_type_caches);
 }
 
 /*free a matrix*/
@@ -995,11 +1095,13 @@
 	if (m->tr) {
 		int i;
 		if (m->regw == 1) {
-			internal_make_private (m, m->regw, MAX (max+1, m->regh));
+			internal_make_private (m, m->regw, MAX (max+1, m->regh),
+					       TRUE /* kill_type_caches */);
 			ensure_at_least_size (m, m->regw, max+1);
 		} else {
 			int minw = (max / m->regh) + 1;
-			internal_make_private (m, MAX (minw, m->regw), m->regh);
+			internal_make_private (m, MAX (minw, m->regw), m->regh,
+					       TRUE /* kill_type_caches */);
 			ensure_at_least_size (m, minw, m->regh);
 		}
 		/* assume that's what ensure/make_us_a_copy does */
@@ -1032,11 +1134,13 @@
 	} else {
 		int i;
 		if (m->regh == 1) {
-			internal_make_private (m, MAX (max+1, m->regw), m->regh);
+			internal_make_private (m, MAX (max+1, m->regw), m->regh,
+					       TRUE /* kill_type_caches */);
 			ensure_at_least_size (m, max+1, m->regh);
 		} else {
 			int minh = (max / m->regw) + 1;
-			internal_make_private (m, m->regw, MAX (minh, m->regh));
+			internal_make_private (m, m->regw, MAX (minh, m->regh),
+					       TRUE /* kill_type_caches */);
 			ensure_at_least_size (m, m->regw, minh);
 		}
 		/* assume that's what ensure/make_us_a_copy does */
@@ -1086,7 +1190,8 @@
 		int minw = (max / m->regh) + 1;
 		int i;
 
-		internal_make_private (m, MAX (minw, m->regw), m->regh);
+		internal_make_private (m, MAX (minw, m->regw), m->regh,
+				       TRUE /* kill_type_caches */);
 		ensure_at_least_size (m, minw, m->regh);
 		/* assume that's what ensure/make_us_a_copy does */
 		g_assert (m->regx == NULL && m->regy == NULL);
@@ -1104,7 +1209,8 @@
 		int minh = (max / m->regw) + 1;
 		int i;
 
-		internal_make_private (m, m->regw, MAX (minh, m->regh));
+		internal_make_private (m, m->regw, MAX (minh, m->regh),
+				       TRUE /* kill_type_caches */);
 		ensure_at_least_size (m, m->regw, minh);
 		/* assume that's what ensure/make_us_a_copy does */
 		g_assert (m->regx == NULL && m->regy == NULL);

Modified: trunk/src/matrixw.h
==============================================================================
--- trunk/src/matrixw.h	(original)
+++ trunk/src/matrixw.h	Tue May 20 05:25:01 2008
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2007 Jiri (George) Lebl
+ * Copyright (C) 1997-2008 Jiri (George) Lebl
  *
  * Author: George Lebl
  *
@@ -54,6 +54,9 @@
 /*new matrix*/
 GelMatrixW *gel_matrixw_new(void);
 GelMatrixW *gel_matrixw_new_with_matrix(GelMatrix *mat);
+GelMatrixW *gel_matrixw_new_with_matrix_value_only (GelMatrix *mat);
+GelMatrixW *gel_matrixw_new_with_matrix_value_only_integer (GelMatrix *mat);
+GelMatrixW *gel_matrixw_new_with_matrix_value_only_real_nonrational (GelMatrix *mat);
 
 /*set size of a matrix*/
 void gel_matrixw_set_size(GelMatrixW *m, int width, int height);
@@ -93,7 +96,7 @@
 void gel_matrixw_free(GelMatrixW *m);
 
 /*make private copy of the GelMatrix*/
-void gel_matrixw_make_private(GelMatrixW *m);
+void gel_matrixw_make_private(GelMatrixW *m, gboolean kill_type_caches);
 
 extern GelETree *the_zero;
 

Modified: trunk/src/mpwrap.c
==============================================================================
--- trunk/src/mpwrap.c	(original)
+++ trunk/src/mpwrap.c	Tue May 20 05:25:01 2008
@@ -3380,7 +3380,6 @@
 	} else {
 		MpwRealNum t = {{NULL}};
 
-		MAKE_REAL(rop);
 		if (rop != op) {
 			MAKE_EMPTY(rop->r, op->r->type);
 		} else {
@@ -3396,6 +3395,40 @@
 		mpwl_free(&t,TRUE);
 
 		mpwl_sqrt(rop->r,rop->r);
+
+		MAKE_REAL (rop);
+	}
+}
+
+void
+mpw_abs_sq (mpw_ptr rop,mpw_ptr op)
+{
+	if (MPW_IS_REAL (op)) {
+		if(mpwl_sgn(op->r)<0)
+			mpw_neg(rop,op);
+		else
+			mpw_set(rop,op);
+
+		/* have to actually square now */
+		mpw_mul (rop, rop, rop);
+	} else {
+		MpwRealNum t = {{NULL}};
+
+		if (rop != op) {
+			MAKE_EMPTY(rop->r, op->r->type);
+		} else {
+			MAKE_COPY (rop->r);
+		}
+		
+		mpwl_init_type (&t, op->i->type);
+		
+		mpwl_mul(rop->r,op->r,op->r);
+		mpwl_mul(&t,op->i,op->i);
+		mpwl_add(rop->r,rop->r,&t);
+
+		mpwl_free(&t,TRUE);
+
+		MAKE_REAL (rop);
 	}
 }
 

Modified: trunk/src/mpwrap.h
==============================================================================
--- trunk/src/mpwrap.h	(original)
+++ trunk/src/mpwrap.h	Tue May 20 05:25:01 2008
@@ -151,6 +151,7 @@
 
 
 void mpw_abs(mpw_ptr rop,mpw_ptr op);
+void mpw_abs_sq(mpw_ptr rop,mpw_ptr op);
 
 int mpw_sgn(mpw_ptr op);
 

Modified: trunk/src/mpzextra.c
==============================================================================
--- trunk/src/mpzextra.c	(original)
+++ trunk/src/mpzextra.c	Tue May 20 05:25:01 2008
@@ -1,11 +1,13 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2003 George Lebl
+ * Copyright (C) 1997-2008 Jiri (George) Lebl
  *
- * Author: George Lebl
+ * Author: Jiri (George) Lebl
  *
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of Genius.
+ *
+ * Genius is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -14,9 +16,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the  Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -165,7 +165,7 @@
 	  if (evalnode_hook != NULL) {
 		  (*evalnode_hook)();
 	  }
-	  if (interrupted) {
+	  if G_UNLIKELY (interrupted) {
 		  is_prime = 0;
 		  break;
 	  }
@@ -243,7 +243,7 @@
 
 	if (evalnode_hook != NULL)
 		(*evalnode_hook)();
-	if (interrupted)
+	if G_UNLIKELY (interrupted)
 		return 0;
 
 	return mpz_millerrabin (n, miller_rabin_reps-1);
@@ -387,7 +387,7 @@
 		      i = 0;
 	      }
       }
-      if (interrupted) {
+      if G_UNLIKELY (interrupted) {
 	      mpz_set_ui (n, 1);
 	      continue;
       }
@@ -523,7 +523,7 @@
 
 	mpz_clear (n);
 
-	if (interrupted) {
+	if G_UNLIKELY (interrupted) {
 		mympz_factorization_free (fact);
 		return NULL;
 	}



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