r1806 - in branches/vendor/mathomatic

stsp at dslinux.in-berlin.de stsp at dslinux.in-berlin.de
Sun Jun 24 13:58:32 CEST 2007


Author: stsp
Date: 2007-06-24 13:58:26 +0200 (Sun, 24 Jun 2007)
New Revision: 1806

Log:
Update mathomatic to version 12.7.3 on vendor branch.


Added: branches/vendor/mathomatic/INSTALL.txt

Modified: branches/vendor/mathomatic/README.txt
===================================================================
--- branches/vendor/mathomatic/README.txt	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/README.txt	2007-06-24 11:58:26 UTC (rev 1806)
@@ -2,38 +2,52 @@
                                        by
                                George Gesslein II
 
-This archive contains the C source code for Mathomatic, the automatic algebraic
-manipulator.  It should compile and run correctly under Unix, GNU/Linux, Mac
-OS-X, and CygWin, without any modifications.
+This archive contains the C source code and documentation for Mathomatic, the
+automatic algebraic manipulator.  It should compile and run correctly under
+Unix, GNU/Linux, Mac OS-X, and CygWin for MS-Windows, without any
+modifications.
 
 Mathomatic is a portable, general purpose CAS (Computer Algebra System) that
-can automatically solve, simplify, combine, and compare algebraic equations,
-perform complex and polynomial arithmetic, etc.  It does some calculus and is
-very easy to use.
+can symbolically solve, simplify, combine, and compare algebraic equations,
+perform complex number and polynomial arithmetic, etc.  It does some calculus
+and is very easy to use.
 
-To compile, just type "make" at a shell prompt.  This will compile the C source
-code to create the executable file named "mathomatic".  To run Mathomatic, type
-"./mathomatic" at the shell prompt.
+All software and documentation in this archive is copyrighted and made
+available under the GNU Lesser GPL version 2.1 (see file "COPYING").
 
-To test most functionality, type "make test".
+                                  Compilation
+                                  -----------
 
-To install, you have to be the super-user, then type "make install".
+To compile Mathomatic without readline support, just type "make" at a shell
+prompt.  This will compile the C source code to create the executable file
+named "mathomatic".  To run Mathomatic, type "./mathomatic" at the shell
+prompt.
 
-To add "readline" editing and history of all Mathomatic input, type:
+To test most functionality, type:
 
+	make test
+
+To recompile with readline editing and history of all Mathomatic input, type:
+
 	make clean
 	make READLINE=1
 
 This allows you to use the cursor keys to recall and edit previous expressions.
 
+                                  Installation
+                                  ------------
+
 A typical installation is done by typing the following at the shell prompt:
 
 	make READLINE=1
 	make test
 	sudo make install
 
-To uninstall from the system, type:
+This will compile, test, and install the Mathomatic executable and docs in
+"/usr/local" in less than a minute.
 
+To completely remove Mathomatic from the system, type:
+
 	sudo make uninstall
 
 To compile the secure version, with no file I/O or shelling out, type:
@@ -43,28 +57,32 @@
 This will silently create the executable "mathomatic_secure", which can safely
 be used as a telnet application or CGI program.
 
-This software is copyrighted and made available under the GNU Lesser GPL (see
-file "COPYING").
+There are quite a few math goodies in this archive, besides the main Mathomatic
+program:
 
-There are quite a few math goodies in the source archive, besides the main
-Mathomatic program:
-
-  The file "changes.txt" is the version history of Mathomatic.
-  The directory "doc" contains the HTML Mathomatic documentation.
+  The directory "doc" contains the Mathomatic documentation in HTML.
   The directory "tests" contains test scripts and other interesting scripts.
   The directory "primes" contains the Mathomatic Prime Number Tools.
   The directory "lib" contains the hooks and test for the Mathomatic library.
-  The directory "fact" contains factorial functions in various languages.
+  The directory "factorial" contains factorial functions in various languages.
+  The file "complex_lib.c" is a generic, floating point complex number library.
 
 For quick help while running Mathomatic, use the "help" command.  To read the
-documentation, point your web browser to the "doc" directory.
+documentation, point your web browser to the file "doc/index.html" or
+"/usr/local/share/doc/mathomatic/html/index.html" if you ran "make install".
+When copying the Mathomatic documentation, please copy the entire documentation
+directory, and not selected files from it.
 
-For the latest source code and information, go to the Mathomatic website:
+For the latest source code, documentation, and information, go to the
+Mathomatic website: http://www.mathomatic.org
 
-	http://www.mathomatic.org
+Author email: gesslein at panix.com
 
-Author e-mail: gesslein at panix.com
+Please consider sending the author an email.  Any email with the subject
+"mathomatic" will make it through the spam filter.
 
+Don't forget to donate to the author if you make money off of Mathomatic.
+
 Author postal address:
 
 	George Gesslein II
@@ -72,40 +90,69 @@
 	Groton, New York 13073
 	USA
 
-The file "tasks.txt" contains a number of good ideas to implement, when someone
-is kind enough to allow me to do something.
+Please report any bugs you find to the author.  Thanks go to Jochen Plumeyer
+for hosting the Mathomatic web site.
 
 
              Compile-Time Defines for the Mathomatic Source Code
              ---------------------------------------------------
 
 To compile Mathomatic for UNIX, GNU/Linux, Mac OS-X, or any POSIX compliant OS,
-define "UNIX".  To compile Mathomatic for a generic system, simply compile with
-no defines.  To compile for Microsoft Win32 using CygWin, define "CYGWIN".
+define "UNIX" (see "makefile").  To compile Mathomatic for a generic system,
+simply compile with no defines.  To compile for Microsoft Win32 using CygWin,
+define "CYGWIN" (see "makefile.cygwin").
 
 Define "READLINE" and include the readline libraries at link time to use
 readline mode.  This will allow easy command line editing and history.
 
-Define "BASICS" to remove some commands (nintegrate and code generation) that
-aren't required for basic functionality.  This is useful for creating a
-stripped down version.  Code size is reduced with this option.
-
 Define "SILENT" to remove all helpful messages and debugging code.  This is
 useful when using Mathomatic as a symbolic math library.  Code size is reduced
 with this option.
 
 Define "LIBRARY" when using as a symbolic math library.  "SILENT" is
-automatically defined when this is defined.  All standard input and output is
-disabled and the code will function as a library.  See the directory "lib" for
-the library hooks and test.  Some commands are omitted with this option.
+automatically defined when this is defined.  Most standard input and output is
+disabled and the code will function as a library.  See the directory "lib" and
+the file "makefile.lib" for the library hooks and test.  The following commands
+are omitted with this option: calculate, code, divide, edit, nintegrate,
+optimize, pause, quit, roots, and tally.
 
 Define "SECURE" to disable file reading and writing and shell escape.  This is
 useful when making Mathomatic available to the public through telnet or CGI
-programs.  It is also useful when making ROMable code.  Code size is reduced
-with this option.  Some insecure commands are omitted with this option.
+programs.  It is also useful when making ROMable code.  All insecure commands
+are omitted with this option.  See "compile.secure", which is the secure
+Mathomatic build script.
 
 Define "TIMEOUT_SECONDS" to set the maximum number of seconds Mathomatic may
 run.  Upon timeout, Mathomatic properly exits.  This is useful when making
 Mathomatic a CGI program, so it won't overload the server.
 
 Define "I18N" to enable internationalization.
+
+
+                         Mathomatic C source code files
+                         ------------------------------
+
+  am.h - the main include file for Mathomatic, contains tunable parameters
+  complex.h - floating point complex number arithmetic function prototypes
+  externs.h - global variable extern definitions
+  proto.h - global function prototypes
+
+  am.c - many necessary routines
+  cmds.c - code for commands that don't belong anywhere else
+  complex.c - floating point complex number routines
+  complex_lib.c - general floating point complex number arithmetic library
+  diff.c - differentiation routines and commands
+  factor.c - symbolic factorizing routines
+  factor_int.c - floating point constant factorizing routines
+  gcd.c - floating point Greatest Common Divisor code
+  globals.c - global variable and array definitions
+  help.c - command table, help command code, and parsing routines
+  integrate.c - integration routines and commands
+  list.c - expression and equation display routines
+  main.c - startup code for Mathomatic
+  parse.c - expression parsing routines
+  poly.c - simplifying and polynomial routines
+  simplify.c - simplifying routines
+  solve.c - solve routines
+  super.c - group and combine denominators
+  unfactor.c - unfactorizing (expanding) routines

Modified: branches/vendor/mathomatic/VERSION
===================================================================
--- branches/vendor/mathomatic/VERSION	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/VERSION	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1 +1 @@
-12.5.16
+12.7.3

Modified: branches/vendor/mathomatic/am.c
===================================================================
--- branches/vendor/mathomatic/am.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/am.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
- * Miscellaneous algebraic manipulator routines.
+ * Miscellaneous routines for Mathomatic.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -57,7 +57,8 @@
 int
 init_mem()
 {
-	if ((scratch = (token_type *) malloc((n_tokens + 10) * sizeof(token_type))) == NULL
+	if ((scratch = (token_type *) malloc(((n_tokens * 3) / 2) * sizeof(token_type))) == NULL
+	    || (tes = (token_type *) malloc(n_tokens * sizeof(token_type))) == NULL
 	    || (tlhs = (token_type *) malloc(n_tokens * sizeof(token_type))) == NULL
 	    || (trhs = (token_type *) malloc(n_tokens * sizeof(token_type))) == NULL) {
 		return false;
@@ -78,7 +79,7 @@
 	partial_flag = true;
 	symb_flag = false;
 	sign_flag = false;
-	in_calc_cmd = false;
+	approximate_roots = false;
 
 	zero_token.level = 1;
 	zero_token.kind = CONSTANT;
@@ -168,7 +169,7 @@
 }
 
 /*
- * Allocate or reuse an equation space.
+ * Allocate or reuse an empty equation space.
  *
  * Returns new equation space number or -1 on error.
  */
@@ -223,6 +224,18 @@
 }
 
 /*
+ * Copy equation number "src" to equation number "dest".
+ */
+copy_espace(src, dest)
+int	src, dest;
+{
+	blt(lhs[dest], lhs[src], n_lhs[src] * sizeof(token_type));
+	n_lhs[dest] = n_lhs[src];
+	blt(rhs[dest], rhs[src], n_rhs[src] * sizeof(token_type));
+	n_rhs[dest] = n_rhs[src];
+}
+
+/*
  * Return true if equation number "i" is solved for a normal variable.
  */
 int
@@ -282,7 +295,7 @@
 int		*np;		/* pointer to equation side length */
 token_type	*expression;	/* expression pointer */
 int		len;		/* expression length */
-long		v;
+long		v;		/* variable to substitute with expression */
 {
 	int	j, k;
 	int	level;
@@ -330,7 +343,7 @@
 }
 
 /*
- * This is called when the max expression size has been exceeded.
+ * This is called when the maximum expression size has been exceeded.
  *
  * There is no return.
  */
@@ -351,11 +364,11 @@
 {
 	int	i;
 
-	if (*cp == '\0')
+	if (*cp == '\0') {
 		i = cur_equation;
-	else {
+	} else {
 		i = decstrtol(cp, &cp) - 1;
-		if (extra_garbage(cp))
+		if (extra_characters(cp))
 			return -1;
 	}
 	if (not_defined(i)) {
@@ -367,12 +380,12 @@
 /*
  * Parse an expression with equation space pull if the line starts with "#".
  *
- * Return true if successful.
+ * Returns the new string position or NULL on error.
  */
-int
+char	*
 parse_expr(equation, np, cp)
-token_type	*equation;	/* where the parsed expression is stored */
-int		*np;		/* pointer to parsed expression length */
+token_type	*equation;	/* where the parsed expression is stored (equation side) */
+int		*np;		/* pointer to the returned parsed expression length */
 char		*cp;		/* string to parse */
 {
 	int	i;
@@ -381,14 +394,23 @@
 	cp1 = skip_space(cp);
 	if (*cp1 == '#') {
 		cp1++;
-		i = decstrtol(cp1, &cp2) - 1;
+		switch (*cp1) {
+		case '+':
+		case '-':
+			i = decstrtol(cp1, &cp2);
+			i = cur_equation + i;
+			break;
+		default:
+			i = decstrtol(cp1, &cp2) - 1;
+			break;
+		}
 		if (cp1 == cp2 || *cp2) {
 			error(_("Error parsing equation space number."));
-			return false;
+			return NULL;
 		}
 		if (i < 0 || i >= n_equations || n_lhs[i] <= 0) {
 			error(_("Equation not defined."));
-			return false;
+			return NULL;
 		}
 		if (n_rhs[i]) {
 			blt(equation, rhs[i], n_rhs[i] * sizeof(token_type));
@@ -397,12 +419,11 @@
 			blt(equation, lhs[i], n_lhs[i] * sizeof(token_type));
 			*np = n_lhs[i];
 		}
-		return true;
+		list_proc(equation, *np, false);
+		fprintf(gfp, "\n");
+		return cp2;
 	}
-	cp = parse_section(equation, np, cp);
-	if (cp)
-		return true;
-	return false;
+	return parse_section(equation, np, cp);
 }
 
 /*
@@ -413,10 +434,10 @@
  */
 int
 get_expr(equation, np)
-token_type	*equation;
-int		*np;
+token_type	*equation;	/* where the parsed expression is stored (equation side) */
+int		*np;		/* pointer to the returned parsed expression length */
 {
-	char	buf[10000];
+	char	buf[DEFAULT_N_TOKENS];
 	char	*cp;
 
 	for (;;) {
@@ -426,8 +447,10 @@
 		if (!case_sensitive_flag) {
 			str_tolower(cp);
 		}
-		if (parse_expr(equation, np, cp))
+		cp = parse_expr(equation, np, cp);
+		if (cp && !extra_characters(cp)) {
 			break;
+		}
 	}
 	return(*np > 0);
 }
@@ -439,24 +462,25 @@
  */
 int
 prompt_var(vp)
-long	*vp;
+long	*vp;	/* pointer to the returned variable */
 {
 	char	buf[MAX_CMD_LEN];
 	char	*cp;
 
-prompt_again:
-	my_strlcpy(prompt_str, _("Enter variable: "), sizeof(prompt_str));
-	if ((cp = get_string(buf, sizeof(buf))) == NULL) {
-		return false;
+	for (;;) {
+		my_strlcpy(prompt_str, _("Enter variable: "), sizeof(prompt_str));
+		if ((cp = get_string(buf, sizeof(buf))) == NULL) {
+			return false;
+		}
+		if (*cp == '\0') {
+			return false;
+		}
+		cp = parse_var2(vp, cp);
+		if (cp == NULL || extra_characters(cp)) {
+			continue;
+		}
+		return true;
 	}
-	cp = parse_var2(vp, cp);
-	if (cp == NULL)
-		return false;
-	if (*cp) {
-		error(_("Only one variable may be specified."));
-		goto prompt_again;
-	}
-	return true;
 }
 
 /*
@@ -478,7 +502,9 @@
 }
 
 /*
- * Return true and display a message if current equation is undefined.
+ * Verify that a current equation or expression is loaded.
+ *
+ * Return true and display a message if current equation space is empty.
  */
 int
 current_not_defined()
@@ -519,7 +545,7 @@
 	}
 	input_column = strlen(prompt_str);
 #if	READLINE
-	if (!html_flag) {
+	if (readline_enabled) {
 		cp = readline(prompt_str);
 		if (cp == NULL)
 			exit_program(0);
@@ -571,21 +597,27 @@
 
 /*
  * Store or display the result of a command.
+ *
+ * Return true if successful.
  */
+int
 return_result(en)
-int	en;	/* equation number */
+int	en;	/* equation space number */
 {
 #if	LIBRARY
 	if (gfp == stdout) {
+		if (display2d) {
+			make_fractions_and_group(en);
+		}
 		if (factor_int_flag) {
-			factor_int(lhs[en], &n_lhs[en]);
-			factor_int(rhs[en], &n_rhs[en]);
+			factor_int_sub(en);
 		}
+		free(result_str);
 		result_str = list_equation(en, false);
-		return;
+		return(result_str != NULL);
 	}
 #endif
-	list_sub(en);
+	return list_sub(en);
 }
 
 /*
@@ -615,7 +647,7 @@
 
 	*cpp = skip_space(*cpp);
 #if	LIBRARY		/* only allow a single equation number when using as a library */
-	if (isascii(**cpp) && isdigit(**cpp)) {
+	if (isdigit(**cpp)) {
 		i = decstrtol(*cpp, cpp) - 1;
 	} else {
 		i = cur_equation;
@@ -632,7 +664,7 @@
 		*ip = 0;
 		*jp = n_equations - 1;
 	} else {
-		if (isascii(**cpp) && isdigit(**cpp)) {
+		if (isdigit(**cpp)) {
 			*ip = strtol(*cpp, cpp, 10) - 1;
 		} else {
 			*ip = cur_equation;
@@ -650,7 +682,7 @@
 			return true;
 		}
 		(*cpp)++;
-		if (isascii(**cpp) && isdigit(**cpp)) {
+		if (isdigit(**cpp)) {
 			*jp = strtol(*cpp, cpp, 10) - 1;
 		} else {
 			*jp = cur_equation;
@@ -681,17 +713,19 @@
  * on a command line.
  *
  * Returns false if OK.
- * Returns true if non-space characters were encountered
+ * Returns true if any non-space characters were encountered
  * and an error message was printed.
  */
 int
-extra_garbage(cp)
+extra_characters(cp)
 char	*cp;	/* command line */
 {
-	cp = skip_space(cp);
-	if (*cp) {
-		error(_("Extra characters on command line."));
-		return true;
+	if (cp) {
+		cp = skip_space(cp);
+		if (*cp) {
+			error(_("Extra characters encountered."));
+			return true;
+		}
 	}
 	return false;
 }
@@ -707,7 +741,7 @@
 	if (!get_range(cpp, ip, jp)) {
 		return false;
 	}
-	if (extra_garbage(*cpp)) {
+	if (extra_characters(*cpp)) {
 		return false;
 	}
 	return true;
@@ -720,14 +754,14 @@
 skip_space(cp)
 char	*cp;	/* character pointer */
 {
-	while (*cp && isascii(*cp) && isspace(*cp))
+	while (*cp && isspace(*cp))
 		cp++;
 	return cp;
 }
 
 /*
  * Enhanced decimal strtol().
- * Allows and skips trailing spaces.
+ * Skips trailing spaces.
  */
 long
 decstrtol(cp, cpp)
@@ -757,8 +791,7 @@
 	}
 	cp = skip_space(cp);
 	if (*cp == '=') {
-		cp++;
-		cp = skip_space(cp);
+		cp = skip_space(cp + 1);
 	}
 	return(cp);
 }
@@ -767,6 +800,8 @@
  * Compare strings up to the first space.
  * Must be an exact match.
  * Compare is alphabetic case insensitive.
+ *
+ * Returns zero on match, non-zero if different.
  */
 int
 strcmp_tospace(cp1, cp2)
@@ -774,9 +809,9 @@
 {
 	char	*cp1a, *cp2a;
 
-	for (cp1a = cp1; *cp1a && (!isascii(*cp1a) || !isspace(*cp1a)); cp1a++)
+	for (cp1a = cp1; *cp1a && !isspace(*cp1a); cp1a++)
 		;
-	for (cp2a = cp2; *cp2a && (!isascii(*cp2a) || !isspace(*cp2a)); cp2a++)
+	for (cp2a = cp2; *cp2a && !isspace(*cp2a); cp2a++)
 		;
 	return strncasecmp(cp1, cp2, max(cp1a - cp1, cp2a - cp2));
 }
@@ -785,7 +820,7 @@
  * Return the number of "level" additive type operators.
  */
 int
-level_plus(p1, n1, level)
+level_plus_count(p1, n1, level)
 token_type	*p1;	/* expression pointer */
 int		n1;	/* expression length */
 int		level;	/* parentheses level number */
@@ -810,14 +845,11 @@
  * Return the number of level 1 additive type operators.
  */
 int
-level1_plus(p1, n1)
+level1_plus_count(p1, n1)
 token_type	*p1;	/* expression pointer */
 int		n1;	/* expression length */
 {
-	int	level;
-
-	level = min_level(p1, n1);
-	return level_plus(p1, n1, level);
+	return level_plus_count(p1, n1, min_level(p1, n1));
 }
 
 /*
@@ -841,6 +873,41 @@
 }
 
 /*
+ * Set *vp if single variable expression.
+ *
+ * Return true if expression contains no variables.
+ */
+int
+no_vars(source, n, vp)
+token_type	*source;	/* expression pointer */
+int		n;		/* expression length */
+long		*vp;		/* variable pointer */
+{
+	int	j;
+	int	found = false;
+
+	if (*vp) {
+		return(var_count(source, n) == 0);
+	}
+	for (j = 0; j < n; j += 2) {
+		if (source[j].kind == VARIABLE) {
+			if ((source[j].token.variable & VAR_MASK) <= SIGN)
+				continue;
+			if (*vp) {
+				if (*vp != source[j].token.variable) {
+					*vp = 0;
+					break;
+				}
+			} else {
+				found = true;
+				*vp = source[j].token.variable;
+			}
+		}
+	}
+	return(!found);
+}
+
+/*
  * Return true if expression contains infinity or nan.
  */
 int

Modified: branches/vendor/mathomatic/am.h
===================================================================
--- branches/vendor/mathomatic/am.h	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/am.h	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,13 +1,13 @@
 /*
  * Main include file for Mathomatic.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #define	true	1
 #define	false	0
 
-#if	LIBRARY		/* define this when using Mathomatic as a symbolic math library */
+#if	LIBRARY
 #define	SILENT	1
 #endif
 
@@ -23,18 +23,15 @@
 #define	isfinite(d)	finite(d)
 #endif
 
-#undef	PI
-#define	PI	3.141592653589793238
-#define	E	2.718281828459045235
-
 #define	ARR_CNT(a)	(sizeof(a)/sizeof(a[0]))	/* returns the number of elements in an array */
 
-#define	MAX_K_INTEGER	1.0e14				/* 14 digits for doubles */
+#define	MAX_K_INTEGER	1.0e14				/* maximum representable integer, 14 digits for doubles */
+#define	MAX_PRECISION	16				/* maximum useful display precision (number of digits) */
 
 #define	blt(dst, src, cnt)	memmove((char *) (dst), (char *) (src), (size_t) (cnt))	/* memory copy function */
 #define always_positive(power)	(fmod((double) (power), 2.0) == 0.0)	/* true if all real numbers raised to "power" result in positive, real numbers */
 
-#if	I18N	/* internationalization */
+#if	I18N	/* internationalization, translators needed! */
 #define _(str)		gettext(str)
 #else
 #define _(str)		str
@@ -64,19 +61,22 @@
 
 /*
  * The following defines the default maximum mathematical expression size.
+ * Expression arrays are allocated with this size by default.
+ * It is linearly related to the actual memory usage of Mathomatic.
  * This should be made much smaller for Palmtops or embedded systems.
+ * Do not set to less than 100.
  */
 #define	DEFAULT_N_TOKENS	30000
 
-#define	DIVISOR_SIZE	(DEFAULT_N_TOKENS / 2)	/* A nice maximum divisor size. */
+#define	DIVISOR_SIZE	(DEFAULT_N_TOKENS / 2)	/* a nice maximum divisor size */
 
-#define	MAX_VAR_NAMES	8000			/* Maximum number of long variable names. Keep this under (VAR_MASK - VAR_OFFSET). */
-#define	MAX_VAR_LEN	1000			/* Maximum size of long variable names */
+#define	MAX_VAR_NAMES	8000			/* maximum number of long variable names, keep this under (VAR_MASK - VAR_OFFSET) */
+#define	MAX_VAR_LEN	100			/* maximum size of long variable names */
 
-#define	MAX_VARS	500			/* Maximum number of unique variables handled in each equation */
+#define	MAX_VARS	500			/* maximum number of unique variables handled in each equation */
 
 #define	VAR_OFFSET	'A'			/* makes space for predefined variables */
-#define	VAR_MASK	0x3fffL			/* mask for bits containing the variable name */
+#define	VAR_MASK	0x3fffL			/* mask for bits containing a reference to the variable name */
 #define	VAR_SHIFT	14			/* number of bits set in VAR_MASK */
 #define	SUBSCRIPT_MASK	63			/* mask for variable subscript after shifting VAR_SHIFT */
 #define	MAX_SUBSCRIPT	(SUBSCRIPT_MASK - 1)	/* maximum variable subscript */
@@ -92,18 +92,15 @@
 typedef union {
 	double	constant;	/* internal storage for mathematical constants */
 	long	variable;	/* internal storage for mathematical variables */
-/* predefined variables follow (order is important) */
+/* predefined special variables follow (order is important) */
 #define	V_NULL		0L	/* null variable (display nothing) */
-#define	V_E		1L	/* the constant "e" */
+#define	V_E		1L	/* the constant "e" or "e#" */
 #define	V_PI		2L	/* the constant "pi" */
-#define	IMAGINARY	3L	/* the imaginary constant "i#" */
-#define	SIGN		4L	/* the "sign" variable */
+#define	IMAGINARY	3L	/* the imaginary constant "i" or "i#" */
+#define	SIGN		4L	/* for "sign" variables */
 #define	MATCH_ANY	5L	/* match any variable (wild-card variable) */
-#define	V_ANSWER	6L	/* the "answer" variable */
-#define V_TEMP		7L	/* the "temp" variable */
-#define	V_INTEGER	8L	/* the "integer" variable */
-	int	operatr;	/* internal storage for operators */
-/* valid operators follow */
+	int	operatr;	/* internal storage for mathematical operators */
+/* valid operators follow (order doesn't matter) */
 #define	PLUS		1	/* a + b */
 #define	MINUS		2	/* a - b */
 #define	TIMES		3	/* a * b */

Modified: branches/vendor/mathomatic/changes.txt
===================================================================
--- branches/vendor/mathomatic/changes.txt	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/changes.txt	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,222 +1,152 @@
                          VERSION HISTORY OF MATHOMATIC
-
+                         -----------------------------
                   Latest changes are at the end of this file.
                This file may be obtained at "www.mathomatic.org".
+                  All changes were made by George Gesslein II.
                --------------------------------------------------
 
-CHANGES MADE TO MATHOMATIC V12.5.0:
+CHANGES MADE TO MATHOMATIC V12.6.0:
 
-Corrected color and html mode routines.
+8/08/06 - Add "makefile.lib", the Mathomatic symbolic math library makefile.
 
-get_expr() now has equation space pull.
-You may now enter a "#" followed by an equation space number when prompted for an expression.
+8/09/06 - "replace constants" command now approximates constants with roots.
 
-Ported nintegrate command to non-equations.  No more commands to port.
+8/09/06 - Tweak code command.
 
-"make install" works better and installs the "tests" directory.
+8/12/06 - Fixed a floating point accuracy issue recently introduced.
 
-Made redirected output ignore screen_columns.
+8/13/06 - Properly fixed the above accuracy issue.
 
-Added "-q" option (quiet mode, don't display prompts).
+CHANGES MADE TO MATHOMATIC V12.6.1:
 
-The Mathomatic man page was improved.
+8/20/06 - Fixed many very minor bugs.  Added variable display precision.
 
-CHANGES MADE TO MATHOMATIC V12.5.1:
+8/21/06 - Display single digit primes when using "matho-primes pal".
 
-Fixed sum and product command docs and code.
+8/24/06 - Increase display precision from 12 to 14 decimal digits.
 
-Split off "am.c" into "solve.c" and "am.c".
+CHANGES MADE TO MATHOMATIC V12.6.2:
 
-Added "tests/trig.in".  (trig functions!)
+8/27/06 - Added some tiny python programs: "fact/factorial" and "primes/mult".
 
-The list command now displays the equation numbers,
-but not when exporting or saving.
+8/31/06 - Add alternate command name "display" to flist command.
 
-Added "tests/hypertrig.in".
+9/04/06 - Improve eliminate command by allowing "eliminate all all ..." to
+          eliminate all variables two or more times.
 
-Allow limit command to work with non-equations.
+CHANGES MADE TO MATHOMATIC V12.6.3:
 
-An optional step parameter was added to the sum and product commands.
+9/06/06 - Remove "doc/notes.html", it is not my best work.
 
-Minor documentation updates.
+9/08/06 - Improve the Mathomatic manuals.
 
-Corrected makefiles to install everything in /usr/local.
+9/09/06 - Fix sign bug for negative factorials (gamma function).
+          "-1.5!" now evaluates to -3.544907701811 instead of 3.544907701811.
 
-CHANGES MADE TO MATHOMATIC V12.5.2:
+9/10/06 - Rename "fact" directory to "factorial".
 
-Ported matho-primes, matho-twin, and matho-pascal to long doubles.
-"make test" added in "primes" directory.
+CHANGES MADE TO MATHOMATIC V12.6.4:
 
-Alphabetic case sensitive mode set by default.
+10/01/06 - Improve user interface of solve command.
 
-Added "list maxima" option.  "list export" is now for other programs.
+10/01/06 - Add alternate command syntax for sum and product commands.
+           "sum x = 0 to 10" works the same as "sum x 0 10".
 
-Code cleanup.
+10/08/06 - Add "-r" option, which disables readline input processing.
 
-CHANGES MADE TO MATHOMATIC V12.5.3:
+10/08/06 - Corrected "tests/cubic.in" and fixed incomplete simplification
+           in complex root calculation.
 
-Removed parsing of "infinity" and fixed parsing of "inf".
+10/10/06 - Got rid of the special "temp" variable.
 
-Removed matho-around.  Use GNU "seq | factor" instead.
+10/11/06 - Got rid of the special "answer" and "integer" variables.
+           They are now normal variables.
 
-Allow "#+"number and "#-"number at main prompt, to select relative equation numbers.
+CHANGES MADE TO MATHOMATIC V12.6.5:
 
-Removed all primes (') support from variable names.
-This is for compatibility with other math programs.
+10/14/06 - Fix optimize command.  Now works 100% properly for "tests/cubic.in".
 
-Added version command.
+10/16/06 - Made HTML division lines look better using "&mdash;".
 
-Added "-v" option.
+10/17/06 - Made list_equation() and list_expression() more efficient by
+           converting the strcat(3)s to strcpy(3)s with a macro.
 
-Split off super.c into super.c and poly.c.
-All polynomial routines are now in poly.c.
+CHANGES MADE TO MATHOMATIC V12.6.6:
 
-Improved roots command and put it in tests.
+10/27/06 - Tune-up of the Mathomatic HTML documentation.
 
-Fixed bug simplifying "a = (e# + (e#*i#))^(pi + (pi*i#))".
+10/28/06 - Add a warning when complex root approximation is done.
 
-CHANGES MADE TO MATHOMATIC V12.5.4:
+10/30/06 - Add another global temporary expression space to make the calculate command
+           iteration terminate on convergence and make the limit command copy to a new
+           equation space.
 
-Added "doc/manpage.html", which is the man page for Mathomatic
-generated with "groff -Thtml -man".
+11/02/06 - Improve help command by displaying alternate command names.
 
-Made sure all HTML files have the extension ".html".
+CHANGES MADE TO MATHOMATIC V12.6.7:
 
-Made sure we can allocate at least 1 equation space on startup.
+11/10/06 - Add "set autocalc" option.
 
-Made entering things like "#1 a" succeed at entering a single variable expression.
-Previously it gave an error.
+12/08/06 - Fix limit command so it fails instead of giving wrong answers.
 
-Fix-ups to the symbolic math library.
+CHANGES MADE TO MATHOMATIC V12.6.8:
 
-Increased power of limit command.
-A limit expression with infinity in it is assumed to be infinity.
+12/16/06 - Add "set special_variable_character" option.
 
-CHANGES MADE TO MATHOMATIC V12.5.5:
+12/26/06 - Comment makefiles and add "INSTALL.txt" for first-time users.
 
-Fixed compatibility problem with "list export" and "list maxima".
-Constants are now parenthesized when exporting.
+12/31/06 - Add "primes/primorial" Python program.
 
-Added "tests/conversions.in".
+CHANGES MADE TO MATHOMATIC V12.6.9:
 
-Made "code integer" command work with more languages than C and Java.
+2/10/07 - "make install" wasn't working - fixed.
 
-Added "code python" command option.
+CHANGES MADE TO MATHOMATIC V12.6.10:
 
-Added "fact/fact.c" and "fact/fact.py", which are factorial functions.
+2/24/07 - Allow calculating large powers of complex numbers at the prompt, like (i#+1)^99.
 
-Completed "help geometry" page.
+3/06/07 - Display which color mode is in effect on startup of Mathomatic.
 
-CHANGES MADE TO MATHOMATIC V12.5.6:
+3/08/07 - Some minor interface improvements to the taylor command.
 
-Code cleanup and commenting.  Minor reduction in code size.
+CHANGES MADE TO MATHOMATIC V12.6.11:
 
-Changed all occurrences of "mathomatic.com" to "mathomatic.org".
+Code cleanup and documentation touch-ups.
 
-Minor updates to the Mathomatic Command Reference.
+3/31/07 - Corrected limit command for infinity limits.
 
-Added some useful warnings to the gcc compile and caught and fixed some errors.
+4/3/07 - Updated root "README.txt" and created "tests/limits.in".
 
-Split off "factor.c" into "factor_int.c" and "factor.c".
+CHANGES MADE TO MATHOMATIC V12.6.12:
 
-CHANGES MADE TO MATHOMATIC V12.5.7:
+Code cleanup and documentation touch-ups.
 
-Doubled the default max expression size.  Display current size on startup.
+4/16/07 - Remove GPL preamble in "primes/*.c", so everything is LGPL.
 
-Made solve_sub() return -1 for an identity.
+4/26/07 - Allow entering "e#" and "i#" as "e" and "i".  Display "e", "i", and "pi" as "e#", "i#", and "pi#".
 
-Speedup of the simplify command.
+CHANGES MADE TO MATHOMATIC V12.7.0:
 
-CHANGES MADE TO MATHOMATIC V12.5.8:
+4/30/07 - Require a space between command and command line, so variables don't get confused with commands.  This is a bug fix.
 
-A number of minor fixups.
+5/5/07 - Added a directory named "hard_stuff".
 
-Code cleanup.  Code size reduced.
+5/10/07 - Fixed error in "tests/finance.in".
 
-CHANGES MADE TO MATHOMATIC V12.5.9:
+CHANGES MADE TO MATHOMATIC V12.7.1:
 
-Bug fix for nintegrate command.  Result was correct but not fully reduced.
+Documentation and command output improvements and corrections.
 
-Added "twin" option to "primes/matho-primes", removed "primes/matho-twin".
+5/28/07 - Added order parameter to extrema command, which specifies the number of derivatives to take.
 
-Automatically determine the variable if none is specified
-with the derivative and taylor commands.
+6/2/07 - Renamed flist command to "display".
 
-Increased the maximum variable length to 1000 characters.
+CHANGES MADE TO MATHOMATIC V12.7.2:
 
-Cleaned up "main.c".
+Improve documentation.  Wikipedia taught me how to make good documents by watching others and practicing!
 
-CHANGES MADE TO MATHOMATIC V12.5.10:
+6/12/07 - Added display of maximum memory usage to version command.
 
-"matho-primes pal" wasn't working, fixed.
+6/13/07 - Allow read command in the Mathomatic library and fixed memory leak with it.
 
-Improved the "Equation not defined" error message for new users.
-
-Worked on matho-primes program.
-
-Automatically determine the variable if none is specified
-with the extrema command.
-
-Code cleanup.
-
-Helped simplification of complex exponentials.
-
-Parse things like "2 2" as "2*2", instead of giving a syntax error.
-The default operator is always times.
-
-CHANGES MADE TO MATHOMATIC V12.5.11:
-
-A bunch of very minor changes and improvements.
-
-Code cleanup.
-
-Documentation improvements.
-
-Updated command description text in help command.
-
-Converted many functions to inline that are only used once and should be inline.
-
-CHANGES MADE TO MATHOMATIC V12.5.12:
-
-Improved matho-primes by making primes buffer variable size.
-
-Added "set factor_integers" option.
-
-Removed "simplify poly" option, it was rarely useful.
-
-Code cleanup, commenting, and speed optimization.
-
-Improved simplification, added the fixed problem ("tests/linear.in") to the tests.
-
-CHANGES MADE TO MATHOMATIC V12.5.13:
-
-A number of minor changes.
-
-Fixes and improvements to the Mathomatic Command Reference.
-
-Upgraded clear and set commands to accept more than one argument.
-
-Gave real and imaginary commands a useful argument.
-
-Fixed a sloppiness in command line parsing in function get_range().
-
-Code cleanup.
-
-CHANGES MADE TO MATHOMATIC V12.5.14:
-
-Excess variables cleanup of taylor command.
-
-Changed argument of push command from an equation number to an equation number range.
-
-Added easy selection of equation spaces, just type the number at the prompt.
-
-Allow flist command when Mathomatic is compiled as a library.
-
-CHANGES MADE TO MATHOMATIC V12.5.15:
-
-Allow curly brackets ("{}") as parentheses.
-
-Allow all taylor command input on the command line.
-Add taylor command to tests.
-
-Added -u option (Unbuffered mode).  Previously output was always unbuffered.
+6/14/07 - Added echo command.

Modified: branches/vendor/mathomatic/cmds.c
===================================================================
--- branches/vendor/mathomatic/cmds.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/cmds.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
- * Algebraic manipulator commands.
+ * Mathomatic commands that don't belong anywhere else.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -9,17 +9,18 @@
 #define	OPT_MIN_SIZE	7	/* Minimum size of repeated expressions to find in optimize command. */
 
 static int	sum_product();
-static int	find_more();
-static int	opt_es();
 static int	complex_func();
 static int	elim_sub();
+#if	!LIBRARY
 static int	edit_sub();
+static int	find_more();
+static int	opt_es();
 
 /* Global variables for the optimize command. */
 static int	opt_en[N_EQUATIONS];
 static int	last_temp_var = 0;
+#endif
 
-#if	!LIBRARY
 /*
  * The version command.
  */
@@ -27,15 +28,15 @@
 version_cmd(cp)
 char	*cp;	/* the command line argument */
 {
-	if (extra_garbage(cp)) {
-		/* if anything on the command line, fail */
-		return false;
-	}
+#if	LIBRARY
+	free(result_str);
+	result_str = strdup(VERSION);
+#endif
 	return version_report();
 }
 
 /*
- * Report version number and compile flags.
+ * Report version number, compile flags, and memory usage.
  */
 int
 version_report()
@@ -53,12 +54,12 @@
 #if	READLINE
 	fprintf(gfp, "READLINE ");
 #endif
-#if	BASICS
-	fprintf(gfp, "BASICS ");
-#endif
 #if	SILENT
 	fprintf(gfp, "SILENT ");
 #endif
+#if	LIBRARY
+	fprintf(gfp, "LIBRARY ");
+#endif
 #if	SECURE
 	fprintf(gfp, "SECURE ");
 #endif
@@ -68,12 +69,48 @@
 #if	I18N
 	fprintf(gfp, "I18N ");
 #endif
-	fprintf(gfp, "\n");
+	fprintf(gfp, _("\nMaximum memory usage: %lld kilobytes\n"), (long long) (N_EQUATIONS + 3LL) * n_tokens * sizeof(token_type) * 2LL / 1000LL);
 	return true;
 }
-#endif
 
 /*
+ * The solve command.
+ */
+int
+solve_cmd(cp)
+char	*cp;
+{
+	int	i;
+	char	buf[MAX_CMD_LEN];
+
+	i = cur_equation;
+	if (i < 0 || i >= n_equations || n_lhs[i] <= 0 || n_rhs[i] <= 0) {
+		error(_("No current equation."));
+		return false;
+	}
+	if (*cp == '\0') {
+		my_strlcpy(prompt_str, _("Enter variable or 0: "), sizeof(prompt_str));
+		if ((cp = get_string(buf, sizeof(buf))) == NULL) {
+			return false;
+		}
+		if (!case_sensitive_flag) {
+			str_tolower(cp);
+		}
+	}
+	i = next_espace();
+	if ((cp = parse_equation(i, cp)) != NULL) {
+		if (n_lhs[i] && n_rhs[i]) {
+			error(_("Invalid argument."));
+		} else if (!extra_characters(cp) && solve(i, cur_equation)) {
+			return return_result(cur_equation);
+		}
+	}
+	n_lhs[i] = 0;
+	n_rhs[i] = 0;
+	return false;
+}
+
+/*
  * The sum command.
  */
 int
@@ -101,7 +138,7 @@
 char	*cp;		/* the command line */
 int	product_flag;	/* true for product, otherwise sum */
 {
-	int		i, j;
+	int		i;
 	long		v = 0;
 	double		start, end, step = 1.0;
 	int		result_en;
@@ -123,37 +160,31 @@
 		source = lhs[cur_equation];
 		dest = lhs[result_en];
 	}
-	if (*cp == '\0') {
-		for (j = 0; j < ns; j += 2) {
-			if (source[j].kind == VARIABLE) {
-				if ((source[j].token.variable & VAR_MASK) <= SIGN)
-					continue;
-				if (v) {
-					if (v != source[j].token.variable) {
-						v = 0;
-						break;
-					}
-				} else {
-					v = source[j].token.variable;
-				}
-			}
-		}
-		if (v == 0) {
-			if (!prompt_var(&v))
-				return false;
-		}
-	} else {
+	if (*cp) {
 		cp = parse_var2(&v, cp);
 		if (cp == NULL) {
 			return false;
 		}
 	}
+	if (no_vars(source, ns, &v)) {
+		error(_("Current expression contains no variables."));
+		return false;
+	}
+	if (v == 0) {
+		if (!prompt_var(&v)) {
+			return false;
+		}
+	}
 	if (!found_var(source, ns, v)) {
 		error(_("Variable not found."));
 		return false;
 	}
 	if (*cp) {
-		cp1 = cp;
+		if (*cp == '=') {
+			cp1 = skip_space(cp + 1);
+		} else {
+			cp1 = cp;
+		}
 	} else {
 		list_var(v, 0);
 		snprintf(prompt_str, sizeof(prompt_str), "%s = ", var_str);
@@ -166,6 +197,9 @@
 		return false;
 	}
 	cp = skip_space(cp);
+	if (strcmp_tospace(cp, "to") == 0) {
+		cp = skip_param(cp);
+	}
 	if (*cp) {
 		cp1 = cp;
 	} else {
@@ -187,11 +221,11 @@
 			return false;
 		}
 	}
-	if (extra_garbage(cp))
+	if (extra_characters(cp))
 		return false;
 	count_down = (end < start);
 	if (fmod(fabs(start - end) / step, 1.0)) {
-		printf(_("Warning: end value not reached.\n"));
+		error(_("Warning: end value not reached."));
 	}
 	if (product_flag) {
 		dest[0] = one_token;
@@ -236,41 +270,39 @@
 	} else {
 		n_lhs[result_en] = n;
 	}
-	return_result(result_en);
-	return true;
+	return return_result(result_en);
 }
 
-#if	!BASICS && !LIBRARY
+#if	!LIBRARY
 /*
  * This function is for the "optimize" command.
- * It finds and substitutes all occurrences of "en"
- * in "equation".
+ * It finds and substitutes all occurrences of the RHS of "en" in "equation".
  * It should be called repeatedly until it returns false.
  */
 static int
 find_more(equation, np, en)
-token_type	*equation;
-int		*np;		/* length of "equation" */
-int		en;		/* equation number */
+token_type	*equation;	/* expression pointer */
+int		*np;		/* pointer to length of expression */
+int		en;		/* equation space number */
 {
 	int	i, j, k;
 	int	level;
 	int	diff_sign;
-	int	found_se;
-	long	v;
+	int	found_se;	/* found sub-expression flag */
 
-	found_se = true;
-	for (level = 1; found_se; level++) {
+	if (!solved_equation(en)) {
+		return false;
+	}
+	for (level = 1, found_se = true; found_se; level++) {
 		for (i = 1, found_se = false; i < *np; i = j + 2) {
-			for (j = i; j < *np && equation[j].level > level; j += 2)
+			for (j = i; j < *np && equation[j].level >= level; j += 2)
 				;
 			if (j == i) {
 				continue;
 			}
 			found_se = true;
 			k = i - 1;
-			if ((j - k) >= OPT_MIN_SIZE && se_compare(&equation[k], j - k, rhs[en], n_rhs[en], &diff_sign)) {
-				v = lhs[en][0].token.variable;
+			if (se_compare(&equation[k], j - k, rhs[en], n_rhs[en], &diff_sign)) {
 				if (diff_sign) {
 					blt(&equation[i+2], &equation[j], (*np - j) * sizeof(token_type));
 					*np -= (j - (i + 2));
@@ -289,7 +321,7 @@
 				}
 				equation[k].level = level;
 				equation[k].kind = VARIABLE;
-				equation[k].token.variable = v;
+				equation[k].token.variable = lhs[en][0].token.variable;
 				return true;
 			}
 		}
@@ -299,8 +331,7 @@
 
 /*
  * This function is for the "optimize" command.
- * It finds and replaces all repeated expressions in
- * "equation" with temporary variables.
+ * It finds and replaces all repeated expressions in "equation" with temporary variables.
  * It also creates a new equation for each temporary variable.
  * It should be called repeatedly until it returns false.
  */
@@ -309,15 +340,14 @@
 token_type	*equation;
 int		*np;
 {
-	int	i, j, k;
-	int	i1, i2, jj1, k1;
+	int	i, j, k, i1, i2, jj1, k1;
 	int	level, level1;
 	int	diff_sign;
-	int	found_se, found_se1;
+	int	found_se, found_se1;	/* found sub-expression flags */
 	long	v;
+	char	temp_buf[50];
 
-	found_se = true;
-	for (level = 1; found_se; level++) {
+	for (level = 1, found_se = true; found_se; level++) {
 		for (i = 1, found_se = false; i < *np; i = j + 2) {
 			for (j = i; j < *np && equation[j].level > level; j += 2)
 				;
@@ -343,11 +373,14 @@
 					k1 = i1 - 1;
 					if ((jj1 - k1) >= OPT_MIN_SIZE
 					    && se_compare(&equation[k], j - k, &equation[k1], jj1 - k1, &diff_sign)) {
-						if (last_temp_var > MAX_SUBSCRIPT) {
+						snprintf(temp_buf, sizeof(temp_buf), "temp%d", last_temp_var);
+						if (parse_var(&v, temp_buf) == NULL) {
+							return false;	/* can't create "temp" variable */
+						}
+						last_temp_var++;
+						if (last_temp_var < 0) {
 							last_temp_var = 0;
 						}
-						v = V_TEMP + (((long) last_temp_var) << VAR_SHIFT);
-						last_temp_var++;
 						i2 = next_espace();
 						lhs[i2][0].level = 1;
 						lhs[i2][0].kind = VARIABLE;
@@ -403,31 +436,47 @@
 optimize_cmd(cp)
 char	*cp;
 {
-	int	i, j, k;
+	int	i, j, k, i1;
 	int	start, stop;
-	int	i1;
 	int	rv = false;
-	int	flag;
+	int	start_en;
 
 	if (!get_range_eol(&cp, &start, &stop)) {
 		return false;
 	}
+	opt_en[0] = -1;
+	start_en = 0;
 	for (i = start; i <= stop; i++) {
+		simp_sub(i);
+	}
+	for (i = start; i <= stop; i++) {
+		for (j = start; j <= stop; j++) {
+			if (i != j) {
+				while (find_more(rhs[i], &n_rhs[i], j)) {
+					rv = true;
+				}
+			}
+		}
+	}
+	for (i = start; i <= stop; i++) {
 		if (n_lhs[i] == 0)
 			continue;
-		opt_en[0] = -1;
-		simp_sub(i);
-		flag = false;
+		for (j = 0; opt_en[j] >= 0; j++) {
+			simp_sub(opt_en[j]);
+			while (find_more(lhs[i], &n_lhs[i], opt_en[j]))
+				;
+			while (find_more(rhs[i], &n_rhs[i], opt_en[j]))
+				;
+		}
 		while (opt_es(lhs[i], &n_lhs[i])) {
-			flag = true;
+			rv = true;
 		}
 		while (opt_es(rhs[i], &n_rhs[i])) {
-			flag = true;
+			rv = true;
 		}
-		if (flag) {
-			rv = true;
-			for (i1 = 0; opt_en[i1] >= 0; i1++) {
-				for (j = 0; opt_en[j] >= 0; j++) {
+		if (rv) {
+			for (i1 = start_en; opt_en[i1] >= 0; i1++) {
+				for (j = start_en; opt_en[j] >= 0; j++) {
 					for (k = j + 1; opt_en[k] >= 0; k++) {
 						while (find_more(rhs[opt_en[k]], &n_rhs[opt_en[k]], opt_en[j]))
 							;
@@ -438,8 +487,8 @@
 				while (opt_es(rhs[opt_en[i1]], &n_rhs[opt_en[i1]]))
 					;
 			}
-			for (j = 0; opt_en[j] >= 0; j++) {
-				list_sub(opt_en[j]);
+			for (; opt_en[start_en] >= 0; start_en++) {
+				list_sub(opt_en[start_en]);
 			}
 			list_sub(i);
 		}
@@ -465,7 +514,10 @@
 		return false;
 	}
 	for (; i <= j; i++) {
-		push_en(i);
+		if (!push_en(i)) {
+			error(_("Push failed."));
+			return false;
+		}
 	}
 	debug_string(0, _("Expression(s) pushed.  Press the UP key to access."));
 	return true;
@@ -473,13 +525,21 @@
 
 /*
  * Push an equation space into the readline history.
+ *
+ * Return true if successful.
  */
+int
 push_en(en)
 int	en;	/* equation space number */
 {
-	high_prec = true;
-	add_history(list_equation(en, false));
-	high_prec = false;
+	if (readline_enabled) {
+		high_prec = true;
+		add_history(list_equation(en, false));
+		high_prec = false;
+		return true;
+	} else {
+		return false;
+	}
 }
 #endif
 
@@ -514,6 +574,16 @@
  */
 output_options()
 {
+	if (!autosolve) {
+		fprintf(gfp, "no ");
+	}
+	fprintf(gfp, "autosolve\n");
+
+	if (!autocalc) {
+		fprintf(gfp, "no ");
+	}
+	fprintf(gfp, "autocalc\n");
+
 #if	!SILENT
 	fprintf(gfp, "debug_level = %d\n", debug_level);
 #endif
@@ -533,7 +603,7 @@
 	}
 	fprintf(gfp, "bold_colors\n");
 
-	if (!groupall) {
+	if (!display2d) {
 		fprintf(gfp, "no ");
 	}
 	fprintf(gfp, "display2d\n");
@@ -557,6 +627,8 @@
 		fprintf(gfp, "no ");
 	}
 	fprintf(gfp, "factor_integers\n");
+
+	fprintf(gfp, "special_variable_character = %c\n", special_variable_character);
 }
 
 /*
@@ -583,7 +655,9 @@
 set_options(cp)
 char	*cp;
 {
+	int	i;
 	int	negate;
+	char	*cp1;
 
 next_option:
 	cp = skip_space(cp);
@@ -610,28 +684,54 @@
 		if (negate) {
 			debug_level = 0;
 		} else {
-			if (*cp == '\0') {
-				error(_("Please specify a debug level number."));
+			i = decstrtol(cp, &cp1);
+			if (cp == cp1) {
+				error(_("Please specify the debug level number."));
 				return false;
 			}
-			debug_level = decstrtol(cp, &cp);
+			cp = cp1;
+			debug_level = i;
 		}
 		goto next_option;
 	}
 #endif
+	if (strncasecmp(cp, "special", 7) == 0) {
+		cp = skip_param(cp);
+		if (negate) {
+			special_variable_character = '\0';
+		} else {
+			if (*cp == '\0' || cp[1]) {
+				error(_("Please specify a single character."));
+				return false;
+			}
+			special_variable_character = *cp;
+		}
+		return true;
+	}
 	if (strncasecmp(cp, "columns", 7) == 0) {
 		cp = skip_param(cp);
 		if (negate) {
 			screen_columns = 0;
 		} else {
-			if (*cp == '\0') {
+			if ((i = decstrtol(cp, &cp1)) < 0 || cp == cp1) {
 				error(_("Please specify how wide the screen is in columns."));
 				return false;
 			}
-			screen_columns = decstrtol(cp, &cp);
+			cp = cp1;
+			screen_columns = i;
 		}
 		goto next_option;
 	}
+	if (strncasecmp(cp, "autosolve", 9) == 0) {
+		cp = skip_param(cp);
+		autosolve = !negate;
+		goto next_option;
+	}
+	if (strncasecmp(cp, "autocalc", 8) == 0) {
+		cp = skip_param(cp);
+		autocalc = !negate;
+		goto next_option;
+	}
 	if (strncasecmp(cp, "case", 4) == 0) {
 		cp = skip_param(cp);
 		case_sensitive_flag = !negate;
@@ -639,7 +739,7 @@
 	}
 	if (strncasecmp(cp, "display2d", 9) == 0) {
 		cp = skip_param(cp);
-		groupall = !negate;
+		display2d = !negate;
 		goto next_option;
 	}
 	if (strncasecmp(cp, "preserve", 8) == 0) {
@@ -679,6 +779,17 @@
 }
 
 /*
+ * The echo command.
+ */
+int
+echo_cmd(cp)
+char	*cp;
+{
+	fprintf(gfp, "%s\n", cp);
+	return true;
+}
+
+/*
  * The pause command.
  */
 int
@@ -689,7 +800,7 @@
 	char	buf[MAX_CMD_LEN];
 
 	if (*cp == '\0') {
-		cp = _("Please Press Enter");
+		cp = _("Please press Enter");
 	}
 	snprintf(prompt_str, sizeof(prompt_str), " ==== %s ==== ", cp);
 	if ((cp1 = get_string(buf, sizeof(buf))) == NULL) {
@@ -698,6 +809,9 @@
 	if (strncasecmp(cp1, "quit", 4) == 0) {
 		return false;
 	}
+	if (strncasecmp(cp1, "exit", 4) == 0) {
+		return false;
+	}
 	return true;
 }
 
@@ -726,10 +840,7 @@
 	for (i1 = i; i1 <= j; i1++) {
 		if (exists[i1]) {
 			k = next_espace();
-			blt(lhs[k], lhs[i1], n_lhs[i1] * sizeof(token_type));
-			n_lhs[k] = n_lhs[i1];
-			blt(rhs[k], rhs[i1], n_rhs[i1] * sizeof(token_type));
-			n_rhs[k] = n_rhs[i1];
+			copy_espace(i1, k);
 			return_result(k);
 		}
 	}
@@ -774,7 +885,7 @@
 		if (cp == NULL) {
 			return false;
 		}
-		if (extra_garbage(cp))
+		if (extra_characters(cp))
 			return false;
 	}
 	simp_loop(source, nps);
@@ -785,14 +896,10 @@
 	partial_flag = true;
 	n1 = 1;
 	dest[0] = zero_token;
-	has_imag = false;
-	has_real = false;
-	k = 0;
-	for (beg = k; beg < *nps; beg = k, k++) {
+	has_imag = has_real = false;
+	for (beg = k = 0; beg < *nps; beg = k, k++) {
 		found_imag = false;
-		for (;; k++) {
-			if (k >= *nps)
-				break;
+		for (; k < *nps; k++) {
 			if (source[k].level == 1 && source[k].kind == OPERATOR
 			    && (source[k].token.operatr == PLUS || source[k].token.operatr == MINUS)) {
 				break;
@@ -824,8 +931,7 @@
 	}
 	*np = n1;
 	cur_equation = j;
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }
 
 /*
@@ -859,13 +965,14 @@
 	int	i;
 	double	count;
 
-	if (extra_garbage(cp))
+	if (extra_characters(cp))
 		return false;
 	trhs[0] = zero_token;
 	n_trhs = 1;
 	for (count = 0.0;; count++) {
 		fprintf(gfp, _("Running total = "));
 		list_proc(trhs, n_trhs, false);
+		fprintf(gfp, "\n");
 		if (count > 0.0) {
 			/* calculate and display the average */
 			blt(tlhs, trhs, n_trhs * sizeof(token_type));
@@ -885,10 +992,10 @@
 			tlhs[n_tlhs].token.constant = count;
 			n_tlhs++;
 			calc_simp(tlhs, &n_tlhs);
-			fprintf(gfp, _(", average = "));
+			fprintf(gfp, _("Average = "));
 			list_proc(tlhs, n_tlhs, false);
+			fprintf(gfp, "\n");
 		}
-		fprintf(gfp, "\n");
 		my_strlcpy(prompt_str, _("Enter value: "), sizeof(prompt_str));
 		if (!get_expr(tlhs, &n_tlhs)) {
 			break;
@@ -927,13 +1034,13 @@
 {
 	int		i, j, k;
 	long		v, last_v, it_v = 0;
-	long		counter;
-	long		counter_max;
+	long		counter, counter_max;
 	sign_array_type	sa_mark;
 	sign_array_type	sa_value;
-	int		iterations = 1;
+	long		l, iterations = 1;
+	token_type	*source;
 	int		n;
-	token_type	*source;
+	int		diff_sign;
 
 	if (current_not_defined()) {
 		return false;
@@ -997,20 +1104,25 @@
 	if (it_v) {
 		list_var(it_v, 0);
 		snprintf(prompt_str, sizeof(prompt_str), _("Enter initial %s: "), var_str);
-		while (!get_expr(scratch, &n))
+		while (!get_expr(tes, &n_tes))
 			;
+		calc_simp(tes, &n_tes);
 		blt(tlhs, trhs, n_trhs * sizeof(token_type));
 		n_tlhs = n_trhs;
-		for (j = 0; j < iterations; j++) {
+		for (l = 0; l < iterations; l++) {
 			blt(trhs, tlhs, n_tlhs * sizeof(token_type));
 			n_trhs = n_tlhs;
-			subst_var_with_exp(trhs, &n_trhs, scratch, n, it_v);
+			subst_var_with_exp(trhs, &n_trhs, tes, n_tes, it_v);
 			calc_simp(trhs, &n_trhs);
-			blt(scratch, trhs, n_trhs * sizeof(token_type));
-			n = n_trhs;
+			if (se_compare(trhs, n_trhs, tes, n_tes, &diff_sign) && !diff_sign) {
+				printf(_("Convergence reached after %ld iterations.\n"), l + 1);
+				break;
+			}
+			blt(tes, trhs, n_trhs * sizeof(token_type));
+			n_tes = n_trhs;
 		}
 	} else {
-		simp_side(trhs, &n_trhs);
+		calc_simp(trhs, &n_trhs);
 	}
 	for (j = 0; j < ARR_CNT(sa_mark); j++)
 		sa_mark[j] = false;
@@ -1024,9 +1136,8 @@
 			k++;
 		}
 	}
-	counter_max = (1L << k) - 1;
-	counter = 0;
-	for (; counter <= counter_max; counter++) {
+	counter_max = (1L << k) - 1L;
+	for (counter = 0; counter <= counter_max; counter++) {
 		blt(tlhs, trhs, n_trhs * sizeof(token_type));
 		n_tlhs = n_trhs;
 		for (j = 0, k = 0; j < ARR_CNT(sa_mark); j++) {
@@ -1075,7 +1186,7 @@
 			fprintf(gfp, " = ");
 		}
 		list_proc(tlhs, n_tlhs, false);
-		fprintf(gfp, "\n");
+		fprintf(gfp, "\n\n");
 	}
 	return true;
 }
@@ -1122,7 +1233,7 @@
 
 	rv = se_compare(rhs[i], n_rhs[i], rhs[i], n_rhs[i], diff_signp);
 	if (!rv || *diff_signp) {
-		error(_("Error in compare function or too many terms to compare!"));
+		error(_("Error in compare function or too many terms to compare."));
 		return false;
 	}
 	sign_flag = true;
@@ -1140,7 +1251,7 @@
 
 	rv = se_compare(lhs[i], n_lhs[i], lhs[i], n_lhs[i], &diff_sign);
 	if (!rv || diff_sign) {
-		error(_("Error in compare function or too many terms to compare!"));
+		error(_("Error in compare function or too many terms to compare."));
 		return false;
 	}
 	sign_flag = true;
@@ -1204,7 +1315,7 @@
 				fprintf(gfp, _("Expressions are identical.\n"));
 				return true;
 			}
-			fprintf(gfp, _("Expressions may differ.\n"));
+			fprintf(gfp, _("Expressions differ.\n"));
 			return false;
 		}
 		error(_("Cannot compare an expression with an equation."));
@@ -1265,7 +1376,7 @@
 		fprintf(gfp, _("Equations are identical.\n"));
 		return true;
 	}
-	fprintf(gfp, _("Equations may differ.\n"));
+	fprintf(gfp, _("Equations differ.\n"));
 	return false;
 times_neg1:
 	if (!diff_sign && lhs[i][0].token.variable == lhs[j][0].token.variable) {
@@ -1303,7 +1414,7 @@
 		if (cp == NULL) {
 			return false;
 		}
-		if (extra_garbage(cp))
+		if (extra_characters(cp))
 			return false;
 	}
 	i = next_espace();
@@ -1320,8 +1431,8 @@
 	calc_simp(rhs[i], &nr);
 	if (get_constant(rhs[i], nr, &d1) && get_constant(lhs[i], nl, &d2)) {
 		d4 = modf(d1 / d2, &d3);
-		fprintf(gfp, _("Result of numerical division: %.14g\n"), d1 / d2);
-		fprintf(gfp, _("Quotient: %.14g, Remainder: %.14g\n"), d3, d4 * d2);
+		fprintf(gfp, _("Result of numerical division: %.*g/%.*g = %.*g\n"), precision, d1, precision, d2, precision, d1 / d2);
+		fprintf(gfp, _("Quotient: %.*g, Remainder: %.*g\n"), precision, d3, precision, d4 * d2);
 		d1 = fabs(d1);
 		d2 = fabs(d2);
 		d3 = gcd(d1, d2);
@@ -1329,18 +1440,14 @@
 			fprintf(gfp, _("No GCD found.\n"));
 			return true;
 		}
-		fprintf(gfp, _("Greatest Common Divisor (GCD) = %.14g\n"), d3);
-		fprintf(gfp, _("Least Common Multiple (LCM) = %.14g\n"), (d1 * d2) / d3);
+		fprintf(gfp, _("Greatest Common Divisor (GCD) = %.*g\n"), precision, d3);
+		fprintf(gfp, _("Least Common Multiple (LCM) = %.*g\n"), precision, (d1 * d2) / d3);
 		return true;
 	}
 	if (parse_complex(rhs[i], nr, &c1) && parse_complex(lhs[i], nl, &c2)) {
 		c3 = complex_div(c1, c2);
-		fprintf(gfp, _("Result of complex division: "));
-		if (c3.im == 0.0) {
-			fprintf(gfp, "%.12g\n\n", c3.re);
-		} else {
-			fprintf(gfp, "%.12g%+.12g*i#\n\n", c3.re, c3.im);
-		}
+		fprintf(gfp, _("Result of complex number division:\n"));
+		fprintf(gfp, "%.*g %+.*g*i\n\n", precision, c3.re, precision, c3.im);
 		return true;
 	}
 	v_tmp = v;
@@ -1364,7 +1471,7 @@
 	}
 	if (j) {
 		simp_divide(trhs, &n_trhs);
-		fprintf(gfp, _("Polynomial Greatest Common Divisor (iterations = %d):\n"), j);
+		fprintf(gfp, _("Polynomial GCD (Euclidean algorithm iterations = %d):\n"), j);
 		list_proc(trhs, n_trhs, false);
 		fprintf(gfp, "\n");
 	} else {
@@ -1387,56 +1494,60 @@
 	char	used[N_EQUATIONS];
 	int	vc = 0;
 
+	if (*cp == '\0') {
+		error(_("Please specify the variables to eliminate or \"all\" for all variables."));
+		return false;
+	}
 	for (i = 0; i < ARR_CNT(used); i++)
 		used[i] = false;
 	if (current_not_defined()) {
 		return false;
 	}
-	if (is_all(cp)) {
-		cp = skip_param(cp);
-		if (extra_garbage(cp))
-			return false;
-		last_v = 0;
-		for (;;) {
-			v1 = -1;
-			for (i = 0; i < n_lhs[cur_equation]; i += 2) {
-				if (lhs[cur_equation][i].kind == VARIABLE
-				    && lhs[cur_equation][i].token.variable > last_v) {
-					if (v1 == -1 || lhs[cur_equation][i].token.variable < v1) {
-						v1 = lhs[cur_equation][i].token.variable;
+next_var:
+	if (vc) {
+		v = va[--vc];
+	} else if (*cp) {
+		if (is_all(cp)) {
+			cp = skip_param(cp);
+			vc = 0;
+			last_v = 0;
+			for (;;) {
+				v1 = -1;
+				for (i = 0; i < n_lhs[cur_equation]; i += 2) {
+					if (lhs[cur_equation][i].kind == VARIABLE
+					    && lhs[cur_equation][i].token.variable > last_v) {
+						if (v1 == -1 || lhs[cur_equation][i].token.variable < v1) {
+							v1 = lhs[cur_equation][i].token.variable;
+						}
 					}
 				}
-			}
-			for (i = 0; i < n_rhs[cur_equation]; i += 2) {
-				if (rhs[cur_equation][i].kind == VARIABLE
-				    && rhs[cur_equation][i].token.variable > last_v) {
-					if (v1 == -1 || rhs[cur_equation][i].token.variable < v1) {
-						v1 = rhs[cur_equation][i].token.variable;
+				for (i = 0; i < n_rhs[cur_equation]; i += 2) {
+					if (rhs[cur_equation][i].kind == VARIABLE
+					    && rhs[cur_equation][i].token.variable > last_v) {
+						if (v1 == -1 || rhs[cur_equation][i].token.variable < v1) {
+							v1 = rhs[cur_equation][i].token.variable;
+						}
 					}
 				}
-			}
-			if (v1 == -1)
-				break;
-			last_v = v1;
-			if ((v1 & VAR_MASK) > SIGN) {
-				if (vc >= ARR_CNT(va)) {
+				if (v1 == -1)
 					break;
+				last_v = v1;
+				if ((v1 & VAR_MASK) > SIGN) {
+					if (vc >= ARR_CNT(va)) {
+						break;
+					}
+					va[vc++] = v1;
 				}
-				va[vc++] = v1;
 			}
+			goto next_var;
 		}
-	}
-next_var:
-	if (*cp) {
 		cp = parse_var2(&v, cp);
 		if (cp == NULL) {
 			return false;
 		}
-	} else if (vc) {
-		v = va[--vc];
 	} else {
 		if (did_something) {
-			return_result(cur_equation);
+			did_something = return_result(cur_equation);
 		} else {
 			error(_("No substitutions made."));
 		}
@@ -1482,7 +1593,6 @@
 		}
 	}
 	did_something = true;
-	simp_sub(cur_equation);
 	used[i] = true;
 	goto next_var;
 }
@@ -1497,7 +1607,7 @@
 #if	!SILENT
 	if (debug_level >= 0) {
 		list_var(v, 0);
-		printf(_("Solving equation #%d for (%s)...\n"), i + 1, var_str);
+		printf(_("Solving equation #%d for (%s) and substituting into the current equation...\n"), i + 1, var_str);
 	}
 #endif
 	want.level = 1;
@@ -1509,22 +1619,24 @@
 	}
 	subst_var_with_exp(rhs[cur_equation], &n_rhs[cur_equation], rhs[i], n_rhs[i], v);
 	subst_var_with_exp(lhs[cur_equation], &n_lhs[cur_equation], rhs[i], n_rhs[i], v);
+	simp_sub(cur_equation);
 	return true;
 }
 
 /*
- * The flist command.
+ * The display command.
  *
- * Displays equations in fraction format.
+ * Displays equations in multi-line fraction format.
  */
 int
-flist_cmd(cp)
+display_cmd(cp)
 char	*cp;
 {
 	int	i, j;
 	int	factor_flag;
 
-	if (factor_flag = (strcmp_tospace(cp, "factor") == 0)) {
+	factor_flag = (strcmp_tospace(cp, "factor") == 0);
+	if (factor_flag) {
 		cp = skip_param(cp);
 	}
 	if (!get_range_eol(&cp, &i, &j)) {
@@ -1532,15 +1644,15 @@
 	}
 	for (; i <= j; i++) {
 		if (n_lhs[i] > 0) {
-			group_sub(i);
+			make_fractions_and_group(i);
 			if (factor_flag || factor_int_flag) {
-				factor_int(lhs[i], &n_lhs[i]);
-				factor_int(rhs[i], &n_rhs[i]);
+				factor_int_sub(i);
 			}
 #if	LIBRARY
 			if (gfp == stdout) {
+				free(result_str);
 				result_str = list_equation(i, false);
-				return true;
+				return(result_str != NULL);
 			}
 #endif
 			flist_sub(i);
@@ -1562,7 +1674,8 @@
 	if (strcmp_tospace(cp, "export") == 0) {
 		export_flag = 2;
 		cp = skip_param(cp);
-	} else if (strcmp_tospace(cp, "maxima") == 0) {
+	}
+	if (strcmp_tospace(cp, "maxima") == 0) {
 		export_flag = 1;
 		cp = skip_param(cp);
 	}
@@ -1570,10 +1683,14 @@
 		return false;
 	}
 	for (; i <= j; i++) {
+		if (factor_int_flag) {
+			factor_int_sub(i);
+		}
 #if	LIBRARY
 		if (gfp == stdout) {
+			free(result_str);
 			result_str = list_equation(i, export_flag);
-			return true;
+			return(result_str != NULL);
 		}
 #endif
 		list1_sub(i, export_flag);
@@ -1581,7 +1698,7 @@
 	return true;
 }
 
-#if	!BASICS && !LIBRARY
+#if	!LIBRARY
 /*
  * The code command.
  */
@@ -1590,17 +1707,17 @@
 char	*cp;
 {
 	int	i, j;
-	int	java_flag = 0;
-	int	int_flag = false;
+	int	language = 0;
+	int	int_flag = false, displayed = false;
 
-	if (strcmp_tospace(cp, "c") == 0) {
+	if (strcmp_tospace(cp, "c") == 0 || strcmp_tospace(cp, "c++") == 0) {
 		cp = skip_param(cp);
 	} else if (strcmp_tospace(cp, "java") == 0) {
 		cp = skip_param(cp);
-		java_flag = 1;
+		language = 1;
 	} else if (strcmp_tospace(cp, "python") == 0) {
 		cp = skip_param(cp);
-		java_flag = 2;
+		language = 2;
 	} else if (strcmp_tospace(cp, "int") == 0 || strcmp_tospace(cp, "integer") == 0) {
 		cp = skip_param(cp);
 		int_flag = true;
@@ -1611,30 +1728,27 @@
 	for (; i <= j; i++) {
 		if (n_lhs[i] > 0) {
 			if (n_rhs[i] == 0 || n_lhs[i] != 1 || lhs[i][0].kind != VARIABLE) {
-#if	!SILENT
-				printf(_("#%d is not a solved equation.\n"), i + 1);
-#endif
+				error(_("Not a solved equation."));
 				continue;
 			}
-			in_calc_cmd = true;
+			approximate_roots = true;
+			simp_i(rhs[i], &n_rhs[i]);
+			approximate_roots = false;
 			if (int_flag) {
-				elim_loop(rhs[i], &n_rhs[i]);
 				uf_repeat_always(rhs[i], &n_rhs[i]);
 			}
-			group_sub(i);
-			in_calc_cmd = false;
+			make_fractions_and_group(i);
 			if (int_flag) {
 				if (!int_expr(rhs[i], n_rhs[i])) {
-#if	!SILENT
-					printf(_("#%d is not an integer equation.\n"), i + 1);
-#endif
+					error(_("Not an integer equation."));
 					continue;
 				}
 			}
-			list_c_equation(i, java_flag, int_flag);
+			list_c_equation(i, language, int_flag);
+			displayed = true;
 		}
 	}
-	return true;
+	return displayed;
 }
 #endif
 
@@ -1661,13 +1775,14 @@
 	i = cur_equation;
 	if (strcmp_tospace(cp, "constants") == 0) {
 		cp = skip_param(cp);
-		if (extra_garbage(cp))
+		if (extra_characters(cp))
 			return false;
 		subst_constants(lhs[i], &n_lhs[i]);
 		subst_constants(rhs[i], &n_rhs[i]);
+		approximate_roots = true;
 		simp_sub(i);
-		return_result(i);
-		return true;
+		approximate_roots = false;
+		return return_result(i);
 	}
 	for (vc = 0; *cp; vc++) {
 		if (strcmp_tospace(cp, "with") == 0) {
@@ -1696,14 +1811,14 @@
 	last_v = 0;
 	for (;;) {
 		v = -1;
-		for (j = 0; j < n_lhs[i]; j++) {
+		for (j = 0; j < n_lhs[i]; j += 2) {
 			if (lhs[i][j].kind == VARIABLE) {
 				if (lhs[i][j].token.variable > last_v
 				    && (v == -1 || lhs[i][j].token.variable < v))
 					v = lhs[i][j].token.variable;
 			}
 		}
-		for (j = 0; j < n_rhs[i]; j++) {
+		for (j = 0; j < n_rhs[i]; j += 2) {
 			if (rhs[i][j].kind == VARIABLE) {
 				if (rhs[i][j].token.variable > last_v
 				    && (v == -1 || rhs[i][j].token.variable < v))
@@ -1731,11 +1846,10 @@
 				if (!case_sensitive_flag) {
 					str_tolower(cp1);
 				}
-				if ((cp1 = parse_section(scratch, &n, cp1)) == NULL
-				    || n <= 0) {
+				if ((cp1 = parse_section(scratch, &n, cp1)) == NULL || n <= 0) {
 					return false;
 				}
-				if (extra_garbage(cp1))
+				if (extra_characters(cp1))
 					return false;
 				goto do_this;
 			}
@@ -1765,8 +1879,7 @@
 	n_rhs[i] = n_trhs;
 	blt(rhs[i], trhs, n_trhs * sizeof(token_type));
 	simp_sub(i);
-	return_result(i);
-	return true;
+	return return_result(i);
 }
 
 /*
@@ -1830,7 +1943,7 @@
 			d = strtod(cp, &cp);
 			cp = skip_space(cp);
 			if (!factor_one(d)) {
-				error(_("Not a valid integer."));
+				error(_("Not a valid integer or number too large."));
 				return false;
 			}
 			display_unique();
@@ -1870,7 +1983,8 @@
 	int	i, j;
 	int	fully_flag;
 
-	if (fully_flag = (strncasecmp(cp, "fully", 4) == 0)) {
+	fully_flag = (strncasecmp(cp, "fully", 4) == 0);
+	if (fully_flag) {
 		cp = skip_param(cp);
 	}
 	if (!get_range_eol(&cp, &i, &j)) {
@@ -1888,6 +2002,28 @@
 	return true;
 }
 
+/*
+ * The fraction command.
+ */
+int
+fraction_cmd(cp)
+char	*cp;
+{
+	int	i, j;
+
+	if (!get_range_eol(&cp, &i, &j)) {
+		return false;
+	}
+	for (; i <= j; i++) {
+		if (n_lhs[i]) {
+			frac_side(lhs[i], &n_lhs[i]);
+			frac_side(rhs[i], &n_rhs[i]);
+			return_result(i);
+		}
+	}
+	return true;
+}
+
 #if	!LIBRARY
 /*
  * The quit command.
@@ -1896,14 +2032,14 @@
 quit_cmd(cp)
 char	*cp;
 {
-	if (extra_garbage(cp))
+	if (extra_characters(cp))
 		return false;
 	exit_program(0);
 	return false;
 }
 #endif
 
-#if	!SECURE && !LIBRARY
+#if	!SECURE
 /*
  * The read command.
  */
@@ -1913,7 +2049,6 @@
 {
 	int	rv;
 	FILE	*fp;
-	jmp_buf	save_save;
 	char	buf[MAX_CMD_LEN];
 
 	if (*cp == '\0') {
@@ -1926,31 +2061,54 @@
 	if (fp == NULL) {
 		fp = fopen(cp, "r");
 		if (fp == NULL) {
-			error(_("Can't open file."));
+			error(_("Can't open input file."));
 			return false;
 		}
+	} else {
+		cp = buf;
 	}
+	rv = read_sub(fp);
+	if (rv) {
+		printf(_("Read operation aborted.\n"));
+	} else {
+		printf(_("Finished reading file \"%s\".\n"), cp);
+	}
+	fclose(fp);
+	return(!rv);
+}
+
+/*
+ * Read and process Mathomatic input from a file pointer.
+ *
+ * Return zero if no error, non-zero if aborted.
+ */
+int
+read_sub(fp)
+FILE	*fp;
+{
+	int	rv;
+	jmp_buf	save_save;
+	char	*cp;
+
 	blt(save_save, jmp_save, sizeof(jmp_save));
 	if ((rv = setjmp(jmp_save)) != 0) {
 		clean_up();
-		if (rv == 14)
-			error(_("Expression too big."));
-		printf(_("Read operation aborted.\n"));
-		goto end_read;
-	}
-	while (cp = fgets((char *) tlhs, n_tokens * sizeof(token_type), fp)) {
-		default_color();
-		input_column = printf("%d%s", cur_equation + 1, html_flag ? HTML_PROMPT : PROMPT);
-		printf("%s", cp);
-		set_error_level(cp);
-		if (!process(cp)) {
-			longjmp(jmp_save, 3);
+		if (rv == 14) {
+			error(_("Expression too large."));
 		}
+	} else {
+		while ((cp = fgets((char *) tlhs, n_tokens * sizeof(token_type), fp)) != NULL) {
+			default_color();
+			input_column = printf("%d%s", cur_equation + 1, html_flag ? HTML_PROMPT : PROMPT);
+			printf("%s", cp);
+			set_error_level(cp);
+			if (!process(cp)) {
+				longjmp(jmp_save, 3);
+			}
+		}
 	}
-end_read:
 	blt(jmp_save, save_save, sizeof(jmp_save));
-	fclose(fp);
-	return(!rv);
+	return rv;
 }
 #endif
 
@@ -1969,7 +2127,7 @@
 
 	if (*cp == '\0') {
 #if	CYGWIN
-		my_strlcpy(tmp_file, "mathxxx.tmp", sizeof(tmp_file));
+		my_strlcpy(tmp_file, "math.tmp", sizeof(tmp_file));
 		fp = fopen(tmp_file, "w+");
 		if (fp == NULL) {
 			error(_("Can't create temporary file."));
@@ -2028,7 +2186,7 @@
 	}
 	clear_all();
 	if (!read_cmd(cp)) {
-		if (pause_cmd("Prepare to run the editor")) {
+		if (pause_cmd(_("Prepare to run the editor"))) {
 			goto edit_again;
 		}
 	}
@@ -2051,6 +2209,7 @@
 		error(_("No file specified."));
 		return false;
 	}
+#if	!SILENT
 	if (access(cp, 0) == 0) {
 		snprintf(prompt_str, sizeof(prompt_str), _("\"%s\" exists.  Overwrite (Y/N)? "), cp);
 		if (!get_yes_no()) {
@@ -2058,6 +2217,7 @@
 			return false;
 		}
 	}
+#endif
 	fp = fopen(cp, "w");
 	if (fp == NULL) {
 		error(_("Can't create file."));
@@ -2071,7 +2231,9 @@
 	if (fclose(fp))
 		rv = false;
 	if (rv) {
+#if	!SILENT
 		printf(_("All equations saved in file: \"%s\".\n"), cp);
+#endif
 	} else {
 		error(_("Error encountered while saving equations."));
 	}

Modified: branches/vendor/mathomatic/compile.secure
===================================================================
--- branches/vendor/mathomatic/compile.secure	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/compile.secure	2007-06-24 11:58:26 UTC (rev 1806)
@@ -2,5 +2,5 @@
 # Shell script for creating the executable "mathomatic_secure".
 # The result can safely be used as a telnet app or CGI program.
 
-cc -s -O -DUNIX -DREADLINE -DVERSION=\"`cat VERSION`\" -DSECURE -DTIMEOUT_SECONDS=3600 *.c -lm -lreadline -lncurses -o mathomatic_secure && echo mathomatic_secure created.
+cc -s -O -DREADLINE -DVERSION=\"`cat VERSION`\" -DSECURE -DTIMEOUT_SECONDS=3600 *.c -lm -lreadline -lncurses -o mathomatic_secure && echo mathomatic_secure created.
 make clean # for any subsequent makes

Modified: branches/vendor/mathomatic/complex.c
===================================================================
--- branches/vendor/mathomatic/complex.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/complex.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
  * Floating point complex number routines specifically for Mathomatic.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -26,13 +26,13 @@
 roots_cmd(cp)
 char	*cp;
 {
-#define	MAX_ROOT	1000.0
+#define	MAX_ROOT	1000.0	/* put a limit here because more roots become more inaccurate */
 
 	complexs	c, c2, check;
 	double		d, k;
 	double		root;
 	double		radius, theta;
-	double		radius_root;
+	double		radius_root = 0.0;
 	char		buf[MAX_CMD_LEN];
 
 	if (*cp == '\0') {
@@ -42,7 +42,7 @@
 	}
 	root = strtod(cp, &cp);
 	if ((*cp && !isspace(*cp)) || root < 0.0 || root > MAX_ROOT || fmod(root, 1.0) != 0.0) {
-		printf(_("Root must be a positive integer less than or equal to %.12g.\n"), MAX_ROOT);
+		printf(_("Root must be a positive integer less than or equal to %.0f.\n"), MAX_ROOT);
 		return false;
 	}
 	cp = skip_space(cp);
@@ -78,22 +78,22 @@
 	}
 	check_err();
 	fprintf(gfp, _("\nThe polar coordinates are:\n%.12g amplitude and %.12g radians (%.12g degrees).\n\n"),
-	    radius, theta, theta * 180 / PI);
+	    radius, theta, theta * 180.0 / M_PI);
 	if (root) {
 		if (c.im == 0.0) {
 			fprintf(gfp, _("The %.12g roots of %.12g^(1/%.12g) are:\n\n"), root, c.re, root);
 		} else {
-			fprintf(gfp, _("The %.12g roots of (%.12g%+.12g*i#)^(1/%.12g) are:\n\n"), root, c.re, c.im, root);
+			fprintf(gfp, _("The %.12g roots of (%.12g%+.12g*i)^(1/%.12g) are:\n\n"), root, c.re, c.im, root);
 		}
 		for (k = 0.0; k < root; k += 1.0) {
 /* add constants to theta and convert back to rectangular coordinates */
-			c2.re = radius_root * cos((theta + 2.0 * k * PI) / root);
-			c2.im = radius_root * sin((theta + 2.0 * k * PI) / root);
+			c2.re = radius_root * cos((theta + 2.0 * k * M_PI) / root);
+			c2.im = radius_root * sin((theta + 2.0 * k * M_PI) / root);
 			complex_fixup(&c2);
 			if (c2.im == 0.0) {
 				fprintf(gfp, "%.12g\n", c2.re);
 			} else {
-				fprintf(gfp, "%.12g %+.12g*i#\n", c2.re, c2.im);
+				fprintf(gfp, "%.12g %+.12g*i\n", c2.re, c2.im);
 			}
 			check = c2;
 			for (d = 1.0; d < root; d += 1.0) {
@@ -103,7 +103,7 @@
 			if (check.im == 0.0) {
 				printf(_("Inverse Check: %.12g\n\n"), check.re);
 			} else {
-				printf(_("Inverse Check: %.12g %+.12g*i#\n\n"), check.re, check.im);
+				printf(_("Inverse Check: %.12g %+.12g*i\n\n"), check.re, check.im);
 			}
 		}
 	}
@@ -175,6 +175,9 @@
 		modified = true;
 		goto start_over;
 	}
+	if (modified) {
+		debug_string(0, "Warning: complex number root approximated, result may be inaccurate.");
+	}
 	return modified;
 }
 

Modified: branches/vendor/mathomatic/complex.h
===================================================================
--- branches/vendor/mathomatic/complex.h	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/complex.h	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,8 @@
 /*
- * Include file for complex number arithmetic in C.
+ * Include file for floating point complex number arithmetic in C.
+ * Goes with "complex_lib.c".
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 typedef struct complexs {	/* complex number structure */
@@ -9,7 +10,9 @@
 	double	im;		/* imaginary part */
 } complexs;
 
-/* complex arithmetic functions */
+/*
+ * Complex arithmetic function prototypes
+ */
 int complex_fixup(complexs *ap);
 complexs complex_add(complexs a, complexs b);
 complexs complex_negate(complexs a);

Modified: branches/vendor/mathomatic/complex_lib.c
===================================================================
--- branches/vendor/mathomatic/complex_lib.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/complex_lib.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,8 +1,8 @@
 /*
- * An independent, floating point complex number library for C.
+ * An independent, floating point complex number arithmetic library for C.
  * Include "complex.h" if you use this.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "complex.h"
@@ -14,13 +14,14 @@
 #define epsilon	0.00000000000005	/* a good value for doubles */
 
 /*
- * Zero out relatively very small real or imaginary parts.
+ * Zero out relatively very small real or imaginary parts of a complex number,
+ * because they probably are a result of accumulated floating point inaccuracies.
  *
  * Return true if something was zeroed out.
  */
 int
 complex_fixup(ap)
-complexs	*ap;
+complexs	*ap;	/* complex number pointer */
 {
 	if (fabs(ap->re * epsilon) > fabs(ap->im)) {
 		ap->im = 0.0;
@@ -65,8 +66,7 @@
  */
 complexs
 complex_mult(a, b)
-complexs	a;
-complexs	b;
+complexs	a, b;
 {
 	complexs	r;
 
@@ -76,7 +76,7 @@
 }
 
 /*
- * Divide complex "a" by complex "b" and return result.
+ * Divide two complex numbers (a / b) and return result.
  */
 complexs
 complex_div(a, b)
@@ -131,8 +131,7 @@
  */
 complexs
 complex_pow(a, b)
-complexs	a;
-complexs	b;
+complexs	a, b;
 {
 	complexs	r;
 

Modified: branches/vendor/mathomatic/diff.c
===================================================================
--- branches/vendor/mathomatic/diff.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/diff.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
- * Algebraic manipulator differentiation routines and commands.
+ * Mathomatic differentiation routines and commands.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -60,8 +60,8 @@
 
 	if (equation[loc].level < level) {
 /* First differentiate if it is a single variable or constant. */
-/* If it is the specified variable, change it to the constant "1.0", */
-/* otherwise change it to "0.0". */
+/* If it is the specified variable, change it to the constant 1, */
+/* otherwise change it to the constant 0. */
 		if (equation[loc].kind == VARIABLE
 		    && ((v == MATCH_ANY && (equation[loc].token.variable & VAR_MASK) > SIGN)
 		    || equation[loc].token.variable == v)) {
@@ -73,8 +73,7 @@
 		}
 		return true;
 	}
-	op = 0;
-	for (endloc = loc + 1; endloc < *np && equation[endloc].level >= level; endloc += 2) {
+	for (op = 0, oploc = endloc = loc + 1; endloc < *np && equation[endloc].level >= level; endloc += 2) {
 		if (equation[endloc].level == level) {
 			switch (op) {
 			case 0:
@@ -120,9 +119,9 @@
 		return true;
 	}
 /* Differentiate PLUS and MINUS operators. */
-/* Use rule: d(u+v) = d(u) + d(v), */
-/* where "d()" is the derivative function, */
-/* "u" and "v" are expressions. */
+/* Use addition rule: d(u+v) = d(u) + d(v), */
+/* where "d()" is the derivative function */
+/* and "u" and "v" are expressions. */
 	for (i = loc; i < *np && equation[i].level >= level;) {
 		if (equation[i].kind != OPERATOR) {
 			if (!d_recurse(equation, np, i, level + 1, v))
@@ -137,7 +136,7 @@
 	return true;
 d_times:
 /* Differentiate TIMES operator. */
-/* Use rule: d(u*v) = u*d(v) + v*d(u). */
+/* Use product rule: d(u*v) = u*d(v) + v*d(u). */
 	if (*np + 1 + (endloc - loc) > n_tokens) {
 		error_huge();
 	}
@@ -153,7 +152,7 @@
 	return(d_recurse(equation, np, loc, level + 2, v));
 d_divide:
 /* Differentiate DIVIDE operator. */
-/* Use rule: d(u/v) = (v*d(u) - u*d(v))/v^2. */
+/* Use quotient rule: d(u/v) = (v*d(u) - u*d(v))/v^2. */
 	if (*np + 3 + (endloc - loc) + (endloc - oploc) > n_tokens) {
 		error_huge();
 	}
@@ -186,7 +185,7 @@
 	return(d_recurse(equation, np, loc, level + 3, v));
 d_power:
 /* Differentiate POWER operator. */
-/* Since we don't have logarithms, just do what we can without them. */
+/* Since we don't have symbolic logarithms, do all we can without them. */
 	for (i = oploc; i < endloc; i++) {
 		if (equation[i].kind == VARIABLE
 		    && ((v == MATCH_ANY && (equation[i].token.variable & VAR_MASK) > SIGN)
@@ -288,8 +287,8 @@
 derivative_cmd(cp)
 char	*cp;
 {
+	int		i;
 	long		v = 0;
-	int		i, j;
 	long		l1, order = 1;
 	token_type	*source, *dest;
 	int		n1, *nps, *np;
@@ -309,12 +308,13 @@
 		dest = lhs[i];
 		np = &n_lhs[i];
 	}
+/* parse the command line or prompt: */
 	if (*cp) {
 		if (is_all(cp)) {
 			cp = skip_param(cp);
 			v = MATCH_ANY;
 		} else {
-			if (!(isascii(*cp) && isdigit(*cp))) {
+			if (!isdigit(*cp)) {
 				cp = parse_var2(&v, cp);
 				if (cp == NULL) {
 					return false;
@@ -329,21 +329,9 @@
 			return false;
 		}
 	}
-	if (v == 0) {
-		for (j = 0; j < *nps; j += 2) {
-			if (source[j].kind == VARIABLE) {
-				if ((source[j].token.variable & VAR_MASK) <= SIGN)
-					continue;
-				if (v) {
-					if (v != source[j].token.variable) {
-						v = 0;
-						break;
-					}
-				} else {
-					v = source[j].token.variable;
-				}
-			}
-		}
+	if (no_vars(source, *nps, &v)) {
+		error(_("Current expression contains no variables, result would be zero."));
+		return false;
 	}
 	if (v == 0) {
 		if (!prompt_var(&v)) {
@@ -351,7 +339,7 @@
 		}
 	}
 	if (v != MATCH_ANY && !found_var(source, *nps, v)) {
-		error(_("Variable not found.  Result would be zero."));
+		error(_("Variable not found, result would be zero."));
 		return false;
 	}
 #if	!SILENT
@@ -365,6 +353,7 @@
 #endif
 	blt(dest, source, *nps * sizeof(token_type));
 	n1 = *nps;
+/* do the actual differentiating and simplifying: */
 	for (l1 = 0; l1 < order; l1++) {
 		if (!differentiate(dest, &n1, v)) {
 			error(_("Differentiation failed."));
@@ -378,8 +367,7 @@
 	}
 	*np = n1;
 	cur_equation = i;
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }
 
 /*
@@ -389,8 +377,9 @@
 extrema_cmd(cp)
 char	*cp;
 {
-	int		i, j;
+	int		i;
 	long		v = 0;
+	long		l1, order = 1;
 	token_type	want;
 	token_type	*source;
 	int		n;
@@ -410,29 +399,23 @@
 		n = n_lhs[cur_equation];
 	}
 	if (*cp) {
-		cp = parse_var2(&v, cp);
-		if (cp == NULL) {
-			return false;
+		if (!isdigit(*cp)) {
+			cp = parse_var2(&v, cp);
+			if (cp == NULL) {
+				return false;
+			}
 		}
-		if (extra_garbage(cp)) {
+		if (*cp) {
+			order = decstrtol(cp, &cp);
+		}
+		if (*cp || order <= 0) {
+			error(_("The order must be a positive integer."));
 			return false;
 		}
 	}
-	if (v == 0) {
-		for (j = 0; j < n; j += 2) {
-			if (source[j].kind == VARIABLE) {
-				if ((source[j].token.variable & VAR_MASK) <= SIGN)
-					continue;
-				if (v) {
-					if (v != source[j].token.variable) {
-						v = 0;
-						break;
-					}
-				} else {
-					v = source[j].token.variable;
-				}
-			}
-		}
+	if (no_vars(source, n, &v)) {
+		error(_("Current expression contains no variables, there are no extrema."));
+		return false;
 	}
 	if (v == 0) {
 		if (!prompt_var(&v)) {
@@ -445,19 +428,24 @@
 	}
 	i = next_espace();
 	blt(rhs[i], source, n * sizeof(token_type));
-	n_rhs[i] = n;
-	if (!differentiate(rhs[i], &n_rhs[i], v)) {
-		error(_("Differentiation failed."));
-		return false;
+/* take derivatives with respect to the specified variable and simplify: */
+	for (l1 = 0; l1 < order; l1++) {
+		if (!differentiate(rhs[i], &n, v)) {
+			error(_("Differentiation failed."));
+			return false;
+		}
+		simpa_side(rhs[i], &n, true);
 	}
-	simpa_side(rhs[i], &n_rhs[i], true);
-	if (!found_var(rhs[i], n_rhs[i], v)) {
-		error(_("There are no extrema for this equation."));
+	if (!found_var(rhs[i], n, v)) {
+		error(_("There are no solutions."));
 		return false;
 	}
+	n_rhs[i] = n;
+/* set equal to zero: */
 	n_lhs[i] = 1;
 	lhs[i][0] = zero_token;
 	cur_equation = i;
+/* lastly, solve for the specified variable and simplify: */
 	want.level = 1;
 	want.kind = VARIABLE;
 	want.token.variable = v;
@@ -466,8 +454,7 @@
 		return false;
 	}
 	simpa_side(rhs[i], &n_rhs[i], false);
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }
 
 /*
@@ -513,7 +500,7 @@
 		dest = lhs[i];
 		np = &n_lhs[i];
 	}
-	if (*cp && !(isascii(*cp) && isdigit(*cp))) {
+	if (*cp && !isdigit(*cp)) {
 		cp = parse_var2(&v, cp);
 		if (cp == NULL) {
 			return false;
@@ -527,25 +514,14 @@
 		}
 		cp = cp1;
 	}
-	if (v == 0) {
-		for (j = 0; j < *nps; j += 2) {
-			if (source[j].kind == VARIABLE) {
-				if ((source[j].token.variable & VAR_MASK) <= SIGN)
-					continue;
-				if (v) {
-					if (v != source[j].token.variable) {
-						v = 0;
-						break;
-					}
-				} else {
-					v = source[j].token.variable;
-				}
-			}
-		}
+	if (no_vars(source, *nps, &v)) {
+		error(_("Current expression contains no variables."));
+		return false;
 	}
 	if (v == 0) {
-		if (!prompt_var(&v))
+		if (!prompt_var(&v)) {
 			return false;
+		}
 	}
 	if (!found_var(source, *nps, v)) {
 		error(_("Variable not found."));
@@ -565,16 +541,15 @@
 		if ((cp = parse_section(lhs[our], &our_nlhs, cp)) == NULL || our_nlhs <= 0) {
 			return false;
 		}
-		if (extra_garbage(cp))
+		if (extra_characters(cp))
 			return false;
 	} else {
 #if	!SILENT
 		list_var(v, 0);
-		printf(_("Taylor series expansion about (%s) = point.\n"), var_str);
+		printf(_("Taylor series expansion about %s = point.\n"), var_str);
 #endif
 		my_strlcpy(prompt_str, _("Enter point: "), sizeof(prompt_str));
 		if (!get_expr(lhs[our], &our_nlhs)) {
-			error(_("Enter 0 if you don't know."));
 			return false;
 		}
 	}
@@ -657,7 +632,7 @@
 	for (; i1 < n1; i1++)
 		dest[i1].level++;
 	simp_loop(dest, &n1);
-	side_debug(1, dest, n1);
+/*	side_debug(1, dest, n1); */
 	if (n < order) {
 		if (n > 0) {
 			if (!differentiate(rhs[our], &our_nrhs, v)) {
@@ -682,13 +657,15 @@
 			goto loop_again;
 		}
 	}
+#if	!SILENT
+	printf(_("%ld derivative%s applied.\n"), n, (n == 1) ? "" : "s");
+#endif
 	if (n_rhs[cur_equation]) {
 		n_lhs[i] = n_lhs[cur_equation];
 	}
 	*np = n1;
 	cur_equation = i;
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }
 
 /*
@@ -699,10 +676,9 @@
 char	*cp;
 {
 	int		i, j, k;
-	long		v;
+	long		v = 0;
 	token_type	solved_v, want;
 	char		*cp_start;
-	int		nl;
 	int		infinity_flag, found_den, complex_den, num, den;
 	int		level;
 
@@ -711,25 +687,31 @@
 		return false;
 	}
 	if (n_rhs[cur_equation] == 0) {
+/* make expression into an equation: */
 		blt(rhs[cur_equation], lhs[cur_equation], n_lhs[cur_equation] * sizeof(token_type));
 		n_rhs[cur_equation] = n_lhs[cur_equation];
 		n_lhs[cur_equation] = 1;
 		lhs[cur_equation][0].level = 1;
 		lhs[cur_equation][0].kind = VARIABLE;
-		lhs[cur_equation][0].token.variable = V_ANSWER;
+		parse_var(&lhs[cur_equation][0].token.variable, "answer");
 	}
 	if (!solved_equation(cur_equation)) {
 		error(_("The current equation is not solved for a variable."));
 		return false;
 	}
 	solved_v = lhs[cur_equation][0];
-	i = next_espace();
+/* parse the command line or prompt: */
 	if (*cp) {
 		cp = parse_var2(&v, cp);
 		if (cp == NULL) {
 			return false;
 		}
-	} else {
+	}
+	if (no_vars(rhs[cur_equation], n_rhs[cur_equation], &v)) {
+		error(_("Current expression contains no variables."));
+		return false;
+	}
+	if (v == 0) {
 		if (!prompt_var(&v)) {
 			return false;
 		}
@@ -743,33 +725,39 @@
 		if (!case_sensitive_flag) {
 			str_tolower(cp);
 		}
-		if ((cp = parse_section(lhs[i], &nl, cp)) == NULL || nl <= 0) {
+		if ((cp = parse_section(tes, &n_tes, cp)) == NULL || n_tes <= 0) {
 			return false;
 		}
 	} else {
-		my_strlcpy(prompt_str, _("goes to: "), sizeof(prompt_str));
-		if (!get_expr(lhs[i], &nl)) {
+		list_var(v, 0);
+		snprintf(prompt_str, sizeof(prompt_str), _("as (%s) goes to: "), var_str);
+		if (!get_expr(tes, &n_tes)) {
 			return false;
 		}
 	}
-	if (extra_garbage(cp))
+	if (extra_characters(cp))
 		return false;
-	simp_loop(lhs[i], &nl);
-	infinity_flag = exp_contains_infinity(lhs[i], nl);
+/* copy to a new equation space and work on the copy: */
+	i = next_espace();
+	copy_espace(cur_equation, i);
+	cur_equation = i;
+/* see if the limit expression contains infinity: */
+	simp_loop(tes, &n_tes);
+	infinity_flag = exp_contains_infinity(tes, n_tes);
+/* first fully simplify the current equation and group denominators together: */
 	simpa_side(rhs[cur_equation], &n_rhs[cur_equation], false);
 	group_proc(rhs[cur_equation], &n_rhs[cur_equation]);
-	found_den = false;
-	complex_den = false;
+	found_den = complex_den = false;
 	for (j = 1; j < n_rhs[cur_equation]; j += 2) {
 		switch (rhs[cur_equation][j].token.operatr) {
 		case DIVIDE:
 		case MODULUS:
-			num = false;
-			den = false;
+			num = den = false;
 			level = rhs[cur_equation][j].level;
 			for (k = j + 2;; k += 2) {
 				if (rhs[cur_equation][k-1].kind == VARIABLE
 				    && rhs[cur_equation][k-1].token.variable == v) {
+/* the limit variable was found in a denominator */
 					den = true;
 					found_den = true;
 				}
@@ -779,6 +767,7 @@
 				switch (rhs[cur_equation][k].token.operatr) {
 				case DIVIDE:
 				case MODULUS:
+/* a denominator contains a fraction */
 					complex_den = true;
 					break;
 				}
@@ -786,6 +775,7 @@
 			for (k = j - 1; k >= 0 && rhs[cur_equation][k].level >= level; k--) {
 				if (rhs[cur_equation][k].kind == VARIABLE
 				    && rhs[cur_equation][k].token.variable == v) {
+/* the limit variable was found in a numerator */
 					num = true;
 				}
 			}
@@ -795,15 +785,18 @@
 			break;
 		}
 	}
-	if (!found_den || (infinity_flag && !complex_den)) {
-		subst_var_with_exp(rhs[cur_equation], &n_rhs[cur_equation], lhs[i], nl, v);
+	if (infinity_flag ? (!complex_den && found_den) : (!found_den)) {
+/* in this case, just substitute the limit variable with the limit expression and simplify: */
+		subst_var_with_exp(rhs[cur_equation], &n_rhs[cur_equation], tes, n_tes, v);
 		simpa_side(rhs[cur_equation], &n_rhs[cur_equation], false);
-		return_result(cur_equation);
-		return true;
+		return return_result(cur_equation);
 	}
-	if (infinity_flag) {
-		nl = 1;
-		lhs[i][0] = zero_token;
+	debug_string(1, "Taking the limit by solving...");
+	if (n_tes == 1 && tes[0].kind == CONSTANT && tes[0].token.constant == HUGE_VAL) {
+/* To take the limit to positive infinity, */
+/* replace infinity with zero and replace the limit variable with its reciprocal: */
+		n_tes = 1;
+		tes[0] = zero_token;
 		tlhs[0] = one_token;
 		tlhs[1].level = 1;
 		tlhs[1].kind = OPERATOR;
@@ -814,6 +807,7 @@
 		n_tlhs = 3;
 		subst_var_with_exp(rhs[cur_equation], &n_rhs[cur_equation], tlhs, n_tlhs, v);
 	}
+/* General limit taking, solve for the limit variable: */
 	want.level = 1;
 	want.kind = VARIABLE;
 	want.token.variable = v;
@@ -821,18 +815,21 @@
 		error(_("Can't take the limit because solve failed."));
 		return false;
 	}
-	blt(lhs[cur_equation], lhs[i], nl * sizeof(token_type));
-	n_lhs[cur_equation] = nl;
+/* replace the limit variable (LHS) with the limit expression: */
+	blt(lhs[cur_equation], tes, n_tes * sizeof(token_type));
+	n_lhs[cur_equation] = n_tes;
+/* symbolically simplify the RHS: */
 	symb_flag = true;
 	simpa_side(rhs[cur_equation], &n_rhs[cur_equation], false);
 	symb_flag = false;
+/* solve back for the original variable: */
 	if (solve_sub(&solved_v, 1, lhs[cur_equation], &n_lhs[cur_equation], rhs[cur_equation], &n_rhs[cur_equation]) <= 0) {
 		error(_("Can't take the limit because solve failed."));
 		return false;
 	}
+/* symbolically simplify before returning the result: */
 	symb_flag = true;
 	simpa_side(rhs[cur_equation], &n_rhs[cur_equation], false);
 	symb_flag = false;
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }

Modified: branches/vendor/mathomatic/doc/am.html
===================================================================
--- branches/vendor/mathomatic/doc/am.html	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/doc/am.html	2007-06-24 11:58:26 UTC (rev 1806)
@@ -2,10 +2,16 @@
 <html>
 <head>
 <title>Mathomatic Command Reference</title>
+<style type="text/css">
+.sample { border-style: dotted; border-width: 1px; color: green; background-color: white; padding: 10px; }
+.indent { margin-left: 2em; margin-right: 2em; }
+</style>
 </head>
+
 <body>
 <center>
-<h1>Mathomatic Version 12.5 Command Reference</h1>
+<h1>Mathomatic Command Reference</h1>
+<img src="greenfade.png" alt="decoration">
 </center>
 
 <h2>Topics:</h2>
@@ -16,7 +22,7 @@
 <li>
 <a href="#selecting">Selecting Equations</a>
 <li>
-<a href="#solve">Solving Equations</a>
+<a href="#solving">Solving Equations</a>
 </ol>
 
 <h2>Commands:</h2>
@@ -37,9 +43,13 @@
 <br>
 <a href="#derivative">Derivative</a>
 <br>
+<a href="#display">Display</a>
+<br>
 <a href="#divide">Divide</a>
 </td>
 <td>
+<a href="#echo">Echo</a>
+<br>
 <a href="#edit">Edit</a>
 <br>
 <a href="#eliminate">Eliminate</a>
@@ -48,7 +58,7 @@
 <br>
 <a href="#factor">Factor</a>
 <br>
-<a href="#flist">FList</a>
+<a href="#fraction">Fraction</a>
 <br>
 <a href="#help">Help</a>
 <br>
@@ -68,10 +78,10 @@
 <a href="#optimize">Optimize</a>
 <br>
 <a href="#pause">Pause</a>
+<br>
+<a href="#product">Product</a>
 </td>
 <td>
-<a href="#product">Product</a>
-<br>
 <a href="#push">Push</a>
 <br>
 <a href="#quit">Quit</a>
@@ -83,14 +93,16 @@
 <a href="#replace">Replace</a>
 <br>
 <a href="#roots">Roots</a>
-</td>
-<td>
+<br>
 <a href="#save">Save</a>
 <br>
 <a href="#set">Set</a>
-<br>
+</td>
+<td>
 <a href="#simplify">Simplify</a>
 <br>
+<a href="#solve">Solve</a>
+<br>
 <a href="#sum">Sum</a>
 <br>
 <a href="#tally">Tally</a>
@@ -98,8 +110,7 @@
 <a href="#taylor">Taylor</a>
 <br>
 <a href="#unfactor">Unfactor</a>
-</td>
-<td>
+<br>
 <a href="#version">Version</a>
 </td>
 </tr>
@@ -108,30 +119,33 @@
 
 <hr>
 <a name="introduction"></a>
-<h3>Introduction</h3>
+<h2>Introduction</h2>
 <p>
-At the Mathomatic prompt, you can enter:
+At the Mathomatic main prompt, you may enter:
 
 <ul>
 <li>
-a numerical expression, which is instantly evaluated and displayed,
+a numerical expression, which is instantly evaluated and displayed (autocalc),
 <li>
 an algebraic expression or equation,
 which is stored and made the current equation,
 <li>
-a variable to solve the current equation for,
+a variable to solve the current equation for (autosolve),
 <li>
 an equation number to select as the current equation,
 <li>
 a Mathomatic command (listed in this document),
 <li>
+a question mark (?) for quick help,
+<li>
 a semicolon (;) followed by a comment
 (everything on a line after a semicolon is ignored),
 <li>
 or an exclamation point (!) followed by a shell (or system) command.
 </ul>
+
 <p>
-Mathomatic has about 35 different commands.
+Mathomatic has about 39 different commands.
 They are described below, in alphabetical order.
 If the command is longer than 4 letters, you only need
 to type in the first 4 letters for Mathomatic to recognize the command.
@@ -140,19 +154,20 @@
 Some commands only operate on the current expression or
 RHS (Right Hand Side) of the current equation.
 <p>
-Many commands have an "equation number range" argument.
+Many commands have an <strong>equation number range</strong> argument.
 An equation number range may be a single equation number,
 a range of equation numbers separated by a dash (-),
 or the word "all", which specifies all stored expressions and equations.
 If a number is omitted, the current expression or equation is assumed.
 <p>
-A greater-than symbol (&gt;) may be appended to any command line,
-followed by a file name.  This will redirect command output
-to a file.  Two greater-than symbols (&gt;&gt;) next to each other
+A greater-than character (&gt;) may be appended to any command line,
+followed by a file name.  This will redirect command output to a file.
+If the file already exists, it will be overwritten without asking.
+Two greater-than characters (&gt;&gt;) next to each other
 will <strong>append</strong> command output to a file.
 For example:
 
-<pre>
+<pre class="indent">
 list export all &gt;filename
 </pre>
 
@@ -163,25 +178,26 @@
 
 <hr>
 <a name="selecting"></a>
-<h3>Selecting Equations</h3>
+<h2>Selecting Equations</h2>
 <p>
-Syntax: <b>#["+" or "-"]number [new-equation]</b>
+Syntax: <b>#["+" or "-"]equation-number</b>
 <p>
-To change the current equation number,
+To change the current equation number at the main prompt,
 type a pound sign (#) followed by the number of the
 equation you wish to select.
-If the number is followed by a space and a new equation,
-the equation at the number is replaced with the new equation.
 <p>
 The equation number may be preceded by "+" or "-", to select
-an equation relative to the current equation.
+an equation number relative to the current equation number.
 <p>
-New feature: Selecting equations is now possible by just typing the equation number
-at the prompt.
+This syntax also works when prompted for an expression.
+The RHS or expression at that equation number is substituted.
+<p>
+New feature: Selecting equations is now possible by typing only
+the equation number at the main prompt.
 
 <hr>
-<a name="solve"></a>
-<h3>Solving Equations</h3>
+<a name="solving"></a>
+<h2>Solving Equations</h2>
 <p>
 Syntax: <b>variable-to-solve-for</b>
 <p>
@@ -193,7 +209,7 @@
 and works perfectly.
 <p>
 To automatically solve for a variable,
-just type the variable in at the prompt.
+type the variable name in at the prompt.
 Mathomatic will proceed to manipulate the current equation
 until all of the solutions for the specified variable
 are determined.
@@ -215,7 +231,7 @@
 <p>
 An example of solving:
 
-<pre>
+<pre class="sample">
 1-&gt; a=b+1/b
 
             1
@@ -249,30 +265,31 @@
 
 <hr>
 <a name="calculate"></a>
-<h3>Calculate</h3>
+<h2>Calculate</h2>
 <p>
 Syntax: <b>calculate [variable number-of-iterations]</b>
 <p>
 This command prompts you for the values of each variable in the
 current expression or the RHS of the current equation.
-It then simplifies the result and automatically substitutes "sign" variables
-with all possible values, displaying each solution as it does so.
+It then simplifies, approximates, and substitutes all "sign" variables
+with all possible combinations of values, displaying each solution as it does so.
 Nothing is modified by this command.
 <p>
-This command is used to approximate expressions
-and expand confusing "sign" variables.
+This command is used to approximate expressions and expand confusing "sign" variables.
 It is also automatically invoked when you type in a numeric expression,
 without any variables, at the Mathomatic prompt.
-No need to get out your calculator when you are using Mathomatic!
+No need to get out your calculator when using Mathomatic!
 <p>
-If a variable and number of iterations are supplied,
+If a <b>variable</b> and <b>number of iterations</b> are specified on the command line,
 you will be prompted for the initial value of the variable,
 and the calculation will be iterated, with the result
 repeatedly plugged back into the specified variable.
+This will be done until convergence (the output equals the input)
+or the number of iterations is performed.
 <p>
 Some examples of using the calculate command:
 
-<pre>
+<pre class="sample">
 1-&gt; y=x^2+x ; the simplest quadratic equation
 
 #1: y = (x^2) + x
@@ -291,7 +308,7 @@
 Solution #1 with sign1 = 1:
  x = -1
 Solution #2 with sign1 = -1:
- x = -0
+ x = 0
 1-&gt; a=b+1 ; an example of iteration
 
 #2: a = b + 1
@@ -304,7 +321,7 @@
 
 <hr>
 <a name="clear"></a>
-<h3>Clear</h3>
+<h2>Clear</h2>
 <p>
 Syntax: <b>clear [equation-numbers-or-ranges]</b>
 <p>
@@ -312,10 +329,13 @@
 The specified equations are deleted from memory.
 <p>
 "clear all" clears all memory, as if Mathomatic was restarted.
+<p>
+Multiple equation numbers and/or ranges may be specified, only in this command,
+for ease in clearing out equation spaces.
 
 <hr>
 <a name="code"></a>
-<h3>Code</h3>
+<h2>Code</h2>
 <p>
 Syntax: <b>code ["c" or "java" or "python" or "integer"] [equation-number-range]</b>
 <p>
@@ -327,23 +347,22 @@
 <p>
 With "code integer", integer arithmetic is assumed,
 otherwise double precision floating point arithmetic is assumed.
-"code integer" is more generic and should work with other programming languages.
+"code integer" is more generic and should work with the C, Java, and Python languages.
 <p>
 To represent factorials, the user supplied function "fact()" is called,
 since there is no equivalent function or operator in these languages.
 "fact()" functions for several languages are supplied in the
-directory "fact" in the Mathomatic source distribution.
+directory "factorial" in the Mathomatic source distribution.
 <p>
-Complex number arithmetic is not supported with C or Java,
-however it is supported with Python.
+Complex number arithmetic is supported with Python only.
 <p>
-For the most efficient code, use the <a href="#simplify">"simplify"</a>
-and <a href="#optimize">"optimize"</a> commands on your equations
+For the most efficient code, use the <a href="#simplify">simplify</a>
+and <a href="#optimize">optimize</a> commands on your equations
 before running this command.
 
 <hr>
 <a name="compare"></a>
-<h3>Compare</h3>
+<h2>Compare</h2>
 <p>
 Syntax: <b>compare equation-number ["with" equation-number]</b>
 <p>
@@ -355,14 +374,13 @@
 <p>
 If this command says the equations or expressions are identical,
 then they are definitely identical.
-If this command says the equations or expressions may differ,
+If this command says the equations or expressions differ,
 then they might be identical if
-one of them is too hard for
-Mathomatic to simplify completely.
+they are too hard for Mathomatic to simplify completely.
 
 <hr>
 <a name="copy"></a>
-<h3>Copy</h3>
+<h2>Copy</h2>
 <p>
 Syntax: <b>copy [equation-number-range]</b>
 <p>
@@ -371,12 +389,14 @@
 
 <hr>
 <a name="derivative"></a>
-<h3>Derivative</h3>
+<h2>Derivative</h2>
 <p>
 Syntax: <b>derivative [variable or "all"] [order]</b>
+<br>
+Alternate command name: <b>differentiate</b>
 <p>
 This command computes the symbolic derivative of the current expression or equation
-with respect to the specified variable.
+with respect to the specified <b>variable</b>.
 It does this by recursively applying the rule of differentiation for each operator
 encountered and simplifying.
 If it is an equation, the RHS is differentiated.
@@ -390,12 +410,16 @@
 variables.  It is equivalent to adding together the derivatives with
 respect to each variable.
 <p>
-Specifying the order allows you to repeatedly differentiate all at once.
+Specifying the <b>order</b> allows you to repeatedly differentiate all at once.
 The default is to differentiate only once (order = 1).
 <p>
+If differentiation fails, it is probably because symbolic logarithms are required.
+Symbolic logarithms are not implemented in Mathomatic.
+Also, factorial and modulus cannot be differentiated.
+<p>
 Some examples:
 
-<pre>
+<pre class="sample">
 1-&gt; x^3+x^2+x+1
 
 #1: (x^3) + (x^2) + x + 1
@@ -416,49 +440,65 @@
 </pre>
 
 <hr>
+<a name="display"></a>
+<h2>Display</h2>
+<p>
+Syntax: <b>display ["factor"] [equation-number-range]</b>
+<br>
+Alternate command name: <b>flist</b>
+<p>
+This command displays stored expressions in multi-line fraction format.
+<p>
+Non-integer constants are converted to reduced fractions,
+if they are exactly equal to a fraction and it would improve readability.
+<p>
+The "factor" option causes all integers, less than or equal to 14 digits long,
+to be factored into their prime factors before display,
+including the numerator and denominator of fractions.
+To always factor integers before display, use the "set factor_integers" command.
+
+<hr>
 <a name="divide"></a>
-<h3>Divide</h3>
+<h2>Divide</h2>
 <p>
 Syntax: <b>divide [variable]</b>
 <p>
 This command is for doing and experimenting with polynomial, complex number,
 and numerical division and Greatest Common Divisors (GCD).
-Mathomatic has a symbolic polynomial division routine which
+Mathomatic has symbolic polynomial division and GCD routines which
 this command calls without any other processing.
 <p>
 This command prompts for
 the dividend (the main polynomial) and the divisor (what you want to
-divide the main polynomial by).  The quotient and remainder are displayed.
-Then the GCD is displayed.  If just numbers were
-entered, the LCM (Least Common Multiple) is also displayed.
-The LCM is the same as the Lowest Common Denominator and
+divide the main polynomial by).
+The quotient, remainder, and GCD are displayed.
+If two numbers were entered, the Least Common Multiple (LCM) is also displayed,
+which is the smallest positive number that can be evenly divided by both numbers
+without remainder.
+The LCM is the same as the Lowest Common Denominator (LCD) of two fractions and
 is the two numbers multiplied together, divided by the GCD.
 <p>
-A variable may be specified on the command line
-as the base variable of the two polynomials,
-but it is usually not necessary because Mathomatic
-automatically selects a base variable.
+A <b>variable</b> may be specified on the command line as the base variable of the two polynomials,
+but is usually not necessary because a base variable is automatically selected.
 <p>
-The Greatest Common Divisor of "a" and "b" is defined as the greatest
-number or polynomial that evenly divides both "a" and "b".
-The Euclidean algorithm is used
-by Mathomatic to compute the GCD for both
+The Greatest Common Divisor of <b>a</b> and <b>b</b> (<b>gcd(a, b)</b>) is defined as the greatest
+positive number or polynomial that evenly divides both <b>a</b> and <b>b</b> without remainder.
+The Euclidean algorithm is used by Mathomatic to compute the GCD for
 numbers and polynomials.
 <p>
-The GCD is the best way to reduce any fraction to its
-simplest form.
-Just divide the numerator and denominator by the GCD,
+The GCD is the best way to reduce any fraction to its simplest form.
+Just divide the numerator and denominator by their GCD,
 and replace them with the quotients (there will be no remainder),
-and your fraction is completely reduced.
+and the fraction is completely reduced.
 The GCD is also used when factoring polynomials and for simplifying.
 <p>
 The Euclidean algorithm of successive divides is the best way to compute the
-GCD for numbers and univariate polynomials.
-Multivariate polynomials usually require something more.
+GCD for numbers and univariate polynomials (polynomials in one variable).
+Multivariate polynomials require recursion or other methods.
 <p>
 An example of polynomial division:
 
-<pre>
+<pre class="sample">
 1-&gt; divide
 Enter dividend: (x^4) - (7*(x^3)) + (18*(x^2)) - (22*x) + 12
 Enter divisor: (x^2) - (2*x) + 2
@@ -475,16 +515,28 @@
 1-&gt;
 </pre>
 
+<p>
+The number of iterations displayed is the number of polynomial divides
+done to compute the GCD.
+
 <hr>
+<a name="echo"></a>
+<h2>Echo</h2>
+<p>
+Syntax: <b>echo [text]</b>
+<p>
+This command outputs a line of <b>text</b>, followed by a newline.
+The following characters cannot be echoed: ";&gt;".
+
+<hr>
 <a name="edit"></a>
-<h3>Edit</h3>
+<h2>Edit</h2>
 <p>
 Syntax: <b>edit [file-name]</b>
 <p>
-This command invokes the editor specified in the "EDITOR" environment
-variable.
+This command invokes the editor specified in the "EDITOR" environment variable.
 <p>
-Just type "edit" at the Mathomatic prompt to edit all equations
+Type "edit" at the Mathomatic prompt to edit all expressions and equations
 stored in the equation spaces.
 When you are done editing Mathomatic equations and commands,
 save and exit the editor to have them automatically read in by
@@ -493,22 +545,22 @@
 observe where the error is and continue, to
 automatically re-enter the editor.
 <p>
-To edit an existing file and have it read in, just specify the file name
-on the "edit" command line.
+To edit an existing file and have it read in, specify the <b>file name</b>
+on the edit command line.
 
 <hr>
 <a name="eliminate"></a>
-<h3>Eliminate</h3>
+<h2>Eliminate</h2>
 <p>
 Syntax: <b>eliminate variables or "all" ["using" equation-number]</b>
 <p>
 This command is used to combine simultaneous equations.
-It will replace all occurrences of the specified variables
-in the current equation with solved equations,
-essentially eliminating the specified variables from the current equation.
+It will scan the command line from left to right,
+replacing all occurrences of the specified <b>variables</b>
+in the current equation with the RHS of solved equations.
 If you are eliminating only one variable,
-the equation to solve can be specified using the "using" argument.
-If the "using" equation number is not specified,
+the equation to solve can be specified with the "using" argument.
+If "using" is not specified,
 Mathomatic will search backwards,
 starting at the current equation minus one,
 for the first equation that contains the specified variable.
@@ -527,10 +579,12 @@
 <p>
 "eliminate all" is shorthand for specifying all normal variables
 on the command line.
+"eliminate all all" will eliminate all variables twice over,
+using each equation only once.
 <p>
 Here is a simple example of combining two equations:
 
-<pre>
+<pre class="sample">
 1-&gt; ; This input to Mathomatic arrives at the distance between two points
 1-&gt; ; in 3D space from the Pythagorean theorem (distance between two points
 1-&gt; ; in 2D space).
@@ -559,24 +613,33 @@
 
 <hr>
 <a name="extrema"></a>
-<h3>Extrema</h3>
+<h2>Extrema</h2>
 <p>
-Syntax: <b>extrema variable</b>
+Syntax: <b>extrema [variable] [order]</b>
+<br>
+Alternate command name: <b>stationary</b>
 <p>
-This command computes the minimums and maximums of the current expression
-or the RHS of the current equation.
+This command computes possible extrema (minimums and maximums) or possible inflection points
+of the current expression or equation.
 The result is placed in the next available equation space, displayed,
 and becomes the current equation.
 The original expression is not modified.
 <p>
-"y=f(x)" where f(x) is the RHS, this command gives the values of x that make the
-minimums and maximums of y.
-This is computed by taking the derivative of f(x), setting it equal to zero,
-and then solving for x.
+By default this command computes stationary points.
+The stationary points of function <b>f(x)</b> are the values of <b>x</b>
+when the slope (derivative) equals zero.
+Stationary points are likely the local minimums and maximums of the function.
 <p>
-The extrema of a function are simply the values of x when the slope equals zero.
+<b>y = f(x)</b>, where <b>f(x)</b> is the RHS and <b>x</b> is the specified <b>variable</b>,
+this command gives the values of <b>x</b> that make the minimums and maximums of <b>y</b>.
+This is computed by taking the derivative of <b>f(x)</b>, setting it equal to zero,
+and then solving for <b>x</b>.
+<p>
+The number of derivatives to take can be specified by the <b>order</b> parameter (default is 1).
+When <b>order</b> is 2, possible points of inflection are determined.
+A point of inflection is a point on a curve at which the second derivative changes sign.
 
-<pre>
+<pre class="sample">
 1-&gt; y=x^2
 
 #1: y = x^2
@@ -589,50 +652,51 @@
 </pre>
 
 <p>
-This function is a parabola, with a minimum at (x = 0).
+This function is a parabola, with the minimum at <b>x = 0</b>.
 
 <hr>
 <a name="factor"></a>
-<h3>Factor</h3>
+<h2>Factor</h2>
 <p>
 Syntax: <b>factor ["number" [integers]] or [equation-number-range] [variables]</b>
 <p>
-This command will factor manually entered integers
+This command will factor manually entered <b>integers</b>
 or trivially factor expressions in equation spaces.
+To factor <b>integers</b> in equation spaces and display,
+use the "<a href="#display">display</a> factor" command.
 <p>
-"factor number" will prompt for integers to factor,
-which may be up to 14 digits.
-The integers should be separated with spaces.
-Otherwise, the "factor" command
-factors variables in the current or specified equations.
+"factor number" will prompt for <b>integers</b> to factor, which may be up to 14 digits.
+The <b>integers</b> should be separated with spaces.
+Otherwise, this command factors expressions containing
+<b>variables</b> in the current or specified equation spaces.
 <p>
 When factoring expressions, it does some basic simplification and
-trivially factors out any common sub-expressions
-it can, unless variables are specified on the command line,
+factors out any common sub-expressions it can,
+unless <b>variables</b> are specified on the command line,
 in which case only common sub-expressions
 containing those variables are factored out.
 <p>
 For example, with the following expression:
 
-<pre>
+<pre class="indent">
 (b*c) + (b*d)
 </pre>
 
 <p>
 variable "b" factors out and the result of this command is:
 
-<pre>
+<pre class="indent">
 b*(c + d)
 </pre>
 
 <p>
-If no variables are specified on the command line,
+If no <b>variables</b> are specified on the command line,
 this command factors even more.
 All equal bases raised to any power are factored.
 This is called Horner factoring or Horner's rule.
 For example:
 
-<pre>
+<pre class="sample">
 1-&gt; x^3+2x^2+3x+4
 
 #1: (x^3) + (2*(x^2)) + (3*x) + 4
@@ -645,36 +709,54 @@
 </pre>
 
 <p>
-To undo the factoring, use the <a href="#unfactor">"unfactor"</a> command.
+To undo the factoring, use the <a href="#unfactor">unfactor</a> command.
 <p>
-This command usually cannot factor polynomials.
-To factor polynomials,
-use the <a href="#simplify">"simplify"</a> command.
+This command cannot factor polynomials.
+To factor polynomials with repeated or symbolic factors,
+use the <a href="#simplify">simplify</a> command.
 
 <hr>
-<a name="flist"></a>
-<h3>FList</h3>
+<a name="fraction"></a>
+<h2>Fraction</h2>
 <p>
-Syntax: <b>flist ["factor"] [equation-number-range]</b>
+Syntax: <b>fraction [equation-number-range]</b>
 <p>
-This command displays stored expressions in multi-line fraction format.
+This command converts expressions with any algebraic fractions in them
+into a single simple algebraic fraction (usually the ratio of two polynomials).
+It does this by combining all algebraic fractions
+added together with unlike denominators.
 <p>
-Non-integer constants are converted to reduced fractions,
-if they are exactly equal to a fraction and it would improve
-readability.
-<p>
-The "factor" option causes all integers, less than or equal to
-14 digits long,
-to be factored into their prime factors,
-including the numerator and denominator of fractions.
+Example:
 
+<pre class="sample">
+1-&gt; 1/x+1/y+1/z
+
+    1   1   1
+#1: - + - + -
+    x   y   z
+
+1-&gt; fraction
+
+    (((y + x)*z) + (x*y))
+#1: ---------------------
+           (x*y*z)
+
+1-&gt; simplify
+
+    1   1   1
+#1: - + - + -
+    x   y   z
+
+1-&gt; 
+</pre>
+
 <hr>
 <a name="help"></a>
-<h3>Help</h3>
+<h2>Help</h2>
 <p>
 Syntax: <b>help [topic or command-name]</b>
 <p>
-This command is provided as a quick reference.
+This command is provided as a quick reference while using Mathomatic.
 If the argument is a command name,
 a one line description and syntax of that command are displayed.
 The command name may be abbreviated.
@@ -682,15 +764,18 @@
 Entering this command by itself will display a list of topics
 and commands.
 <p>
-To create a command quick reference text file, type:
+To create a Mathomatic command quick reference text file, type:
 
-<pre>
+<pre class="indent">
 help all &gt;quick_ref.txt
 </pre>
 
+<p>
+A question mark (?) is shorthand for this help command.
+
 <hr>
 <a name="imaginary"></a>
-<h3>Imaginary</h3>
+<h2>Imaginary</h2>
 <p>
 Syntax: <b>imaginary [variable]</b>
 <p>
@@ -699,22 +784,21 @@
 If the expression or RHS of the equation is not complex,
 it will tell you and abort.
 A complex expression contains both imaginary and real parts.
-To copy the real part, see the <a href="#real">"real"</a> command.
+To copy the real part, see the <a href="#real">real</a> command.
 <p>
-The separation variable may be specified on the command line, the default is "i#".
+The separation <b>variable</b> may be specified on the command line, the default is <b>i#</b>.
 <p>
-If you want to exclude "i#" from the result,
-type the following command after
-the "imaginary" command:
+If you want to exclude <b>i#</b> from the result,
+type the following command after the imaginary command:
 
-<pre>
+<pre class="indent">
 replace i# with 1
 </pre>
 
 <p>
 For example:
 
-<pre>
+<pre class="sample">
 1-&gt; (a+b*i#)/(c+d*i#)
 
     (a + (b*i#))
@@ -738,12 +822,14 @@
 
 <hr>
 <a name="integrate"></a>
-<h3>Integrate</h3>
+<h2>Integrate</h2>
 <p>
 Syntax: <b>integrate ["definite"] variable [order]</b>
+<br>
+Alternate command name: <b>integral</b>
 <p>
 This command computes the symbolic integral of a function
-with respect to the specified variable,
+with respect to the specified <b>variable</b>,
 using the RHS of the current equation as the function.
 If successful,
 the integral is placed in the next available equation space,
@@ -752,16 +838,21 @@
 <p>
 "integrate definite" also integrates, but prompts you for the lower and upper
 bounds for definite integration.
-If g(x) is the indefinite integral (anti-derivative) of f(x),
-the definite integral is (g(upper_bound) - g(lower_bound)).
+If <b>g(x)</b> is the indefinite integral (anti-derivative) of <b>f(x)</b>,
+the definite integral is:
+
+<pre class="indent">
+g(upper_bound) - g(lower_bound)
+</pre>
+
 <p>
-Specifying the order allows you to repeatedly integrate all at once.
+Specifying the <b>order</b> allows you to repeatedly integrate all at once.
 The default is to integrate only once (order = 1).
 <p>
 This command is not very sophisticated and is only for integrating
 polynomials.
 
-<pre>
+<pre class="sample">
 1-&gt; x^3+x^2+x+1
 
 #1: (x^3) + (x^2) + x + 1
@@ -781,12 +872,12 @@
 
 <hr>
 <a name="laplace"></a>
-<h3>Laplace</h3>
+<h2>Laplace</h2>
 <p>
 Syntax: <b>laplace ["inverse"] variable</b>
 <p>
 This command computes the Laplace transform of a function
-with respect to the specified variable,
+with respect to the specified <b>variable</b>,
 using the RHS of the current equation as the function.
 If successful,
 the transform is placed in the next available equation space,
@@ -796,7 +887,7 @@
 <p>
 Inverse Laplace transforms are done with the "inverse" option.
 
-<pre>
+<pre class="sample">
 1-&gt; y=a*x^n
 
 #1: y = a*(x^n)
@@ -816,45 +907,38 @@
 
 <hr>
 <a name="limit"></a>
-<h3>Limit</h3>
+<h2>Limit</h2>
 <p>
 Syntax: <b>limit variable expression</b>
 <p>
-This command takes the limit of the current expression or equation as "variable"
-goes to "expression", approaching "expression" from both sides.
-"expression" may be anything, including infinity.
-If successful, the current equation will contain the result
-and be displayed.
+This command takes the limit of the current expression or equation as <b>variable</b>
+goes to <b>expression</b>, approaching <b>expression</b> from both sides.
+<b>expression</b> may be anything, including infinity.
+The result is placed in the next available equation space,
+displayed, and becomes the current equation.
 <p>
-L'Hopital's rule is not currently used by this command.
-Instead the limit is taken by solving and substitution.
+L'Hopital's rule is not used by this command.
+Instead the limit is taken by simplifying, solving, and substituting.
+This command is experimental and does not know about negative infinity
+and sometimes gives the wrong answer.
 
-<pre>
-1-&gt; ; Compute the derivative of (x^.5) using limits:
-1-&gt; a=((x+h)^.5-x^.5)/h
+<pre class="sample">
+1-&gt; 2x/(x+1)
 
-                  1       1
-        (((x + h)^-) - (x^-))
-                  2       2
-#1: a = ---------------------
-                  h
+      2*x
+#1: -------
+    (x + 1)
 
-1-&gt; limit h 0
-Raising both sides to the power of 2 and unfactoring...
-Removing possible solution: "h = 0".
+1-&gt; limit x inf ; take the limit as x goes to infinity
 
-            1
-#1: a = ---------
-              1
-        (2*(x^-))
-              2
+#2: answer = 2
 
-1-&gt;
+2-&gt;
 </pre>
 
 <hr>
 <a name="list"></a>
-<h3>List</h3>
+<h2>List</h2>
 <p>
 Syntax: <b>list ["export" or "maxima"] [equation-number-range]</b>
 <p>
@@ -865,37 +949,38 @@
 so they can be read in with a different math program.
 "list maxima" is for making output compatible with the program Maxima.
 <p>
-This command simply outputs expressions and equations as stored internally by
-Mathomatic.  There is no simplification and nothing more is done.
+This command simply outputs expressions and equations as stored internally by Mathomatic.
+There is no simplification and nothing more is done.
 <p>
-To display equations in fraction format,
-see the <a href="#flist">"flist"</a> command.
+To display equation spaces in multi-line fraction format,
+see the <a href="#display">display</a> command.
 
 <hr>
 <a name="nintegrate"></a>
-<h3>NIntegrate</h3>
+<h2>NIntegrate</h2>
 <p>
-Syntax: <b>nintegrate ["trapezoidal"] variable [partitions]</b>
+Syntax: <b>nintegrate ["trapezoid"] variable [partitions]</b>
 <p>
 This is a numerical integrate command and it will
 not generally compute the exact symbolic integral
 except for the simplest of expressions.
 This command will prompt you for the lower
 and upper bounds to perform numerical definite integration
-on the RHS of the current equation with respect to the specified variable.
+on the current expression or the RHS of the current equation,
+with respect to the specified <b>variable</b>.
 These bounds may be any expression not containing infinity.
 <p>
+This command uses Simpson's rule to do the approximation.
 Accuracy varies widely, depending on the expression integrated
 and the interval.
-This command uses Simpson's rule to do the approximation.
-If "trapezoidal" is specified on the command line,
-the trapezoidal method is used instead, which is usually less
+<p>
+If "trapezoid" (can be shortened to "trap") is specified on the command line,
+the trapezoid method is used instead, which is usually less
 accurate than Simpson's rule.
-The way the trapezoidal method
-works is the interval from the lower bound to the
+The way the trapezoid method works is the interval from the lower bound to the
 upper bound is divided into 1000 partitions to produce 1000 trapezoids.
 Then the area of each trapezoid is added together to produce the result.
-This means that the accuracy decreases as the interval increases.
+This means that the accuracy usually decreases as the interval increases.
 Simpson's rule uses the same method,
 except parabolas are used, instead of trapezoids.
 <p>
@@ -905,7 +990,7 @@
 If there are any singularities between the bounds of integration,
 the computed result will be wrong.
 
-<pre>
+<pre class="sample">
 1-&gt; y=x+1
 
 #1: y = x + 1
@@ -924,12 +1009,17 @@
 </pre>
 
 <p>
-This works because if g(x) is the indefinite integral (anti-derivative) of f(x),
-the definite integral is (g(upper_bound) - g(lower_bound)).
-In this case, it is (g(x) - g(0)), which is (g(x) - 0), which is
-simply g(x).
+This works because if <b>g(x)</b> is the indefinite integral (anti-derivative) of <b>f(x)</b>,
+the definite integral is:
 
-<pre>
+<pre class="indent">
+g(upper_bound) - g(lower_bound)
+</pre>
+
+<p>
+In this case, it is <b>g(x) - g(0)</b>, which is <b>g(x) - 0</b>, which is simply <b>g(x)</b>.
+
+<pre class="sample">
 1-&gt; y=x^0.5/(1-x^3)
 
               1
@@ -951,11 +1041,11 @@
 </pre>
 
 <p>
-This example avoids the singularity at x = 1 and is accurate to 12 digits.
+This example avoids the singularity at <b>x = 1</b> and is accurate to 12 digits.
 
 <hr>
 <a name="optimize"></a>
-<h3>Optimize</h3>
+<h2>Optimize</h2>
 <p>
 Syntax: <b>optimize [equation-number-range]</b>
 <p>
@@ -968,9 +1058,9 @@
 It should work with partial expressions too, to be perfect.
 <p>
 To undo this command and substitute the split up equations into the original
-equation, use the <a href="#eliminate">"eliminate"</a> command.
+equation, use the <a href="#eliminate">eliminate</a> command.
 
-<pre>
+<pre class="sample">
 1-&gt; y = (a+b+c+d)^(a+b+c+d)
 
 #1: y = (a + b + c + d)^(a + b + c + d)
@@ -992,26 +1082,31 @@
 
 <hr>
 <a name="pause"></a>
-<h3>Pause</h3>
+<h2>Pause</h2>
 <p>
 Syntax: <b>pause [text]</b>
 <p>
-This command waits for the user the press the Enter key.
+This command waits for the user to press the Enter key.
 It is useful in text files that are read in to Mathomatic.
 Optionally, a one line text message may be displayed.
+<p>
+Typing "quit" or "exit" before pressing the Enter key will fail this command
+and abort the current script.
 
 <hr>
 <a name="product"></a>
-<h3>Product</h3>
+<h2>Product</h2>
 <p>
 Syntax: <b>product variable start end [step]</b>
 <p>
-This command performs a mathematical product of an expression or the RHS of the current equation
-as the index "variable" goes from "start" to "end" in steps of "step" (default 1).
+This command performs a mathematical product of the current expression
+or the RHS of the current equation
+as the index <b>variable</b> goes from <b>start</b> to <b>end</b>
+in steps of <b>step</b> (default 1).
 The result is stored and displayed.
 The current equation is not modified.
 
-<pre>
+<pre class="sample">
 1-&gt; y=a*x
 
 #1: y = a*x
@@ -1030,7 +1125,7 @@
 
 <hr>
 <a name="push"></a>
-<h3>Push</h3>
+<h2>Push</h2>
 <p>
 Syntax: <b>push [equation-number-range]</b>
 <p>
@@ -1039,48 +1134,47 @@
 After this command, the pushed expressions are
 accessed by using the cursor UP key.
 <p>
-This command only exists if Mathomatic was compiled with "readline" support.
+This command only exists if Mathomatic was compiled with readline support.
 
 <hr>
 <a name="quit"></a>
-<h3>Quit</h3>
+<h2>Quit</h2>
 <p>
 Syntax: <b>quit</b>
+<br>
+Alternate command name: <b>exit</b>
 <p>
-Type in this command to exit
-Mathomatic.
-All equations are discarded.
+Type in this command to exit Mathomatic.
+All equations and expressions in memory are discarded.
 <p>
-To save your equations, see the
-<a href="#save">"save"</a> command.
+To save your stored equations and expressions, see the
+<a href="#save">save</a> command.
 
 <hr>
 <a name="read"></a>
-<h3>Read</h3>
+<h2>Read</h2>
 <p>
 Syntax: <b>read file-name</b>
 <p>
 This command reads in a text file as if you
 typed the text of the file in at the prompts.
-The text file should contain Mathomatic
-equations and commands.
-"read" commands may be nested.
+The text file should contain Mathomatic equations and commands.
+Read commands may be nested.
 If any command or operation returns with an error,
 the read operation is aborted.
 <p>
-Equations saved with the <a href="#save">"save"</a> command
-are restored using this "read" command.
+Equations saved with the <a href="#save">save</a> command
+are restored using this read command.
 <p>
-This command is automatically executed
-when you start up Mathomatic with
+This command is automatically executed when you start up Mathomatic with
 file names on the command line.
 <p>
-The default file name extension for Mathomatic input files
-is ".in".
+The default file name extension for Mathomatic input files is ".in".
+A file name extension is not required.
 
 <hr>
 <a name="real"></a>
-<h3>Real</h3>
+<h2>Real</h2>
 <p>
 Syntax: <b>real [variable]</b>
 <p>
@@ -1090,13 +1184,13 @@
 it will tell you and abort.
 A complex expression contains both imaginary and real parts.
 To copy the imaginary part, see the
-<a href="#imaginary">"imaginary"</a> command.
+<a href="#imaginary">imaginary</a> command.
 <p>
-The separation variable may be specified on the command line, the default is "i#".
+The separation <b>variable</b> may be specified on the command line, the default is <b>i#</b>.
 <p>
 There will be no imaginary numbers in the result.
 
-<pre>
+<pre class="sample">
 2-&gt; (a+b*i#)/(c+d*i#)
 
     (a + (b*i#))
@@ -1114,56 +1208,55 @@
 
 <hr>
 <a name="replace"></a>
-<h3>Replace</h3>
+<h2>Replace</h2>
 <p>
-Syntax: <b>replace ["constants"] [variables ["with" expression]]</b>
+Syntax: <b>replace ["constants"] or [variables ["with" expression]]</b>
 <p>
 By default, this command prompts you for a replacement expression
 for each variable in the current expression or equation.
-If an empty line is entered for a variable,
-that variable remains unchanged.
+If an empty line is entered for a variable, that variable remains unchanged.
 The result is placed in the current expression or equation and displayed.
 <p>
 This command is very useful for renaming or substituting variables.
 It is smart enough to do variable interchange.
 <p>
-If variables are specified on the command line,
+If <b>variables</b> are specified on the command line,
 you will be prompted for those variables only and
 all other variables will be left unchanged.
 <p>
 If "with" is specified,
-you won't be prompted and all variables specified will be
-replaced with the expression that follows.
+you won't be prompted and all <b>variables</b> specified will be
+replaced with the <b>expression</b> that follows.
 <p>
-"replace constants" substitutes pi and e#
-in the current expression or equation with
-their respective floating point values.
+"replace constants" approximates constants and substitutes <b>pi#</b> and <b>e#</b>
+in the current expression or equation with their respective floating point values.
 This allows them to combine with other constants and may help sometimes.
 
 <hr>
 <a name="roots"></a>
-<h3>Roots</h3>
+<h2>Roots</h2>
 <p>
 Syntax: <b>roots root real-part imaginary-part</b>
 <p>
-This command displays all complex roots of a given root of a complex
-number.
-The number of the root equals the
-number of correct solutions.
+This command displays all complex number roots
+of a given positive integer <b>root</b> of a complex number.
+The number of the root equals the number of correct solutions.
 For example, "3" would give the 3 roots of the cubed root.
 This command will also convert rectangular coordinates to polar coordinates.
 <p>
-The real and imaginary parts of the complex number are prompted for.
+The floating point <b>real part</b> (X coordinate)
+and <b>imaginary part</b> (Y coordinate)
+of the complex number are prompted for.
 Just enter an empty line if the value is zero.
-The polar coordinates of the complex number are displayed.
-Polar coordinates consist of an amplitude (distance from the origin)
+The polar coordinates of the complex number are displayed first,
+which consist of an amplitude (distance from the origin)
 and an angle (direction).
 Then each root is displayed, along with an "Inverse Check" value,
 which should equal the original complex number.
 <p>
 Since double precision floating point is used, the results may not be exact.
 
-<pre>
+<pre class="sample">
 1-&gt; roots
 Enter root (positive integer): 3
 Enter real part (X): 8
@@ -1177,10 +1270,10 @@
 2
 Inverse Check: 8
 
--1 +1.73205080757*i#
+-1 +1.73205080757*i
 Inverse Check: 8
 
--1 -1.73205080757*i#
+-1 -1.73205080757*i
 Inverse Check: 8
 
 1-&gt;
@@ -1188,41 +1281,51 @@
 
 <hr>
 <a name="save"></a>
-<h3>Save</h3>
+<h2>Save</h2>
 <p>
 Syntax: <b>save file-name</b>
 <p>
 This command saves all equations in the specified text file.
-If the file exists, Mathomatic will ask you if you want
-to overwrite it.
+If the file exists, Mathomatic will ask you if you want to overwrite it.
 The saved equations can be reloaded at a later time
-by using the <a href="#read">"read"</a> command.
+by using the <a href="#read">read</a> command.
 You can edit the saved equations with your favorite ASCII text editor.
 
 <hr>
 <a name="set"></a>
-<h3>Set</h3>
+<h2>Set</h2>
 <p>
-Syntax: <b>set [["no"] options]</b>
+Syntax: <b>set [["no"] option]</b>
 <p>
-This command sets various options for the current session.
+This command sets various options listed below, for the current session.
 They remain in effect until you exit Mathomatic.
-Typing "set" without arguments shows you the current option settings.
+Typing "set" without arguments shows the current option settings.
 <p>
+The specified <b>option</b> is turned on, unless it is preceded by "no", which turns it off.
+<p>
 To change the default settings of Mathomatic,
-put your set options in the file "~/.mathomaticrc"
-("mathomatic.rc" in the same directory as the executable under Windows).
-It should be a text file with one set option per line,
-without the word "set".
+set options can be put in the file "~/.mathomaticrc"
+(for Windows: "mathomatic.rc" in the same directory as the Mathomatic executable).
+It should be a text file with one set option per line, without the word "set".
+This file is loaded every time Mathomatic starts up, when not in test or secure mode.
 
-<h4>Options:</h4>
+<h3>Options:</h3>
 <blockquote>
 <p>
+"set no autosolve" will disable solving by typing the variable at the prompt.
+This allows entry of single variable expressions.
+When disabled, use the <a href="#solve">solve</a> command.
+<p>
+"set no autocalc" will disable automatic approximation (calculation) of
+purely numerical input.
+Instead, numerical input will be entered into equation
+spaces, so it can be operated on by commands.
+<p>
 "set debug" followed by an integer sets the debug level number.
 The initial debug level is 0, for no debugging.
 If the level number is 2,
 Mathomatic will show you how it solves equations.
-Level 4 debugs the <a href="#simplify">"simplify"</a>
+Level 4 debugs the <a href="#simplify">simplify</a>
 command and its polynomial routines.
 Levels 5 and 6 show all intermediate expressions.
 Set the debug level to -1 for suppression of unnecessary helpful messages.
@@ -1258,14 +1361,17 @@
 <p>
 "set preserve" will set "preserve_roots" mode, which suppresses approximation
 of roots of rational numbers, if the result will be irrational.
-For example, "2^.5" will remain "2^.5" in all Mathomatic operations.
+For example, <b>2^.5</b> will remain <b>2^.5</b> unless explicitly approximated.
+This is the default.
 <p>
-"set true_modulus" will set true modulus mode, which is 100% mathematically correct.
-Pseudo-modulus mode is used by default, which is the modulus used by computer languages.
-Pseudo-modulus only gives the remainder of the division, which may be negative and
-will sometimes fail the simplification rules employed by Mathomatic.
+"set true_modulus" sets true modulus mode, which is 100% mathematically correct.
+Pseudo-modulus mode is used by default,
+which is the modulus used by the C and Java computer languages.
+Pseudo-modulus only gives the remainder of the division,
+which may be negative when the dividend is negative,
+and will sometimes fail the simplification rules employed by Mathomatic.
 True modulus always gives a positive value or zero.
-This mode only affects modulus operator calculations.
+This mode only affects modulo operator calculations.
 All true modulus simplification rules are enabled, regardless of this mode.
 <p>
 "set finance" sets finance mode, which displays all constants with exactly 2 digits
@@ -1273,63 +1379,105 @@
 Displayed constants are always rounded to the nearest cent,
 though internally there is no loss of accuracy.
 <p>
-"set factor_integers" sets automatic factoring of integers for all displayed
-expressions.
+"set factor_integers" sets automatic factoring of integers for all displayed expressions.
+All integers up to 14 digits are factored into their prime factors before any expression
+is displayed, after every command.
+This command can be shortened to "set factor".
 <p>
+"set special_variable_character" followed by an ASCII character will allow Mathomatic
+to use that character in variable names.  For example, "set special $" will allow
+variable names like "$a" and "a$".
+The default is backslash (\).
+<p>
 "set directory" followed by a directory name will change the current working directory
-to that directory.  This command can be shortened to "set dir".
+to that directory.
+This command can be shortened to "set dir".
 </blockquote>
 
 <hr>
 <a name="simplify"></a>
-<h3>Simplify</h3>
+<h2>Simplify</h2>
 <p>
 Syntax: <b>simplify ["symbolic"] ["quick"] [equation-number-range]</b>
 <p>
-This command completely and automatically simplifies
-the current or specified expressions or equations.
+This command automatically simplifies expressions in place.
+The result is usually the smallest possible, easily readable expression.
 <p>
 Use this command whenever you think an expression is not completely
 simplified or if you don't like the way an expression is factored.
 <p>
 More than one option may be specified at a time.
 
-<h4>Options:</h4>
+<h3>Options:</h3>
 <blockquote>
 <p>
-The "symbolic" option indicates ((a^n)^m) should always be reduced
-to (a^(n*m)).
-This removes any absolute value operations
-((a^2)^.5 = a^(2*.5) = a^1 = a).
+The "symbolic" option indicates <b>(a^n)^m</b> should always be reduced to <b>a^(n*m)</b>.
+This removes any absolute value operations:
+(<b>(a^2)^.5 = a^(2*.5) = a^1 = a</b>).
 <p>
 The "quick" option skips expanding expressions raised to the power of 2
-or higher, like ((x+1)^5).
+or higher, like <b>(x+1)^5</b>.
 Algebraic fractions are kept simple (no fractions within fractions) only when using this option.
 </blockquote>
 
 <p>
-This command applies some algebraic transformations
-and then tries to reduce fractions by finding and dividing by the GCD.
+This command applies many algebraic transformations
+and then tries to combine and reduce algebraic fractions and rationalize their denominators.
 Then smart (heuristic) and polynomial division are tried on any divides.
 Polynomials with repeated or symbolic factors are factored.
+Lastly, the expressions are nicely factored and displayed.
 <p>
 Smart division is like polynomial division,
 but it tries every term in the dividend,
-instead of just the term raised to the highest power,
+instead of the term raised to the highest power,
 to make the expression smaller.
 
+<pre class="sample">
+1-&gt; (x+2^.5)^3 ; an irrational polynomial with repeated factors
+
+            1
+#1: (x + (2^-))^3
+            2
+
+1-&gt; unfactor ; multiply it out
+
+                        1                   1
+#1: (x^3) + (3*(x^2)*(2^-)) + (6*x) + (2*(2^-))
+                        2                   2
+
+1-&gt; simplify ; put it back together, since factored is its simplest form
+
+            1
+#1: (x + (2^-))^3
+            2
+
+1-&gt;
+</pre>
+
 <hr>
+<a name="solve"></a>
+<h2>Solve</h2>
+<p>
+Syntax: <b>solve variable or "0"</b>
+<p>
+This command automatically solves the current equation for the specified <b>variable</b> or for zero.
+The current equation is replaced with the result.
+See <a href="#solving">Solving Equations</a>.
+
+<hr>
 <a name="sum"></a>
-<h3>Sum</h3>
+<h2>Sum</h2>
 <p>
 Syntax: <b>sum variable start end [step]</b>
 <p>
-This command performs a mathematical summation of an expression or the RHS of the current equation
-as the index "variable" goes from "start" to "end" in steps of "step" (default 1).
+This command performs a mathematical summation of the current expression
+or the RHS of the current equation
+as the index <b>variable</b> goes from <b>start</b> to <b>end</b>
+in steps of <b>step</b> (default 1).
 The result is stored and displayed.
 The current equation is not modified.
 
-<pre>
+<pre class="sample">
 1-&gt; y=a*x
 
 #1: y = a*x
@@ -1346,7 +1494,7 @@
 
 <hr>
 <a name="tally"></a>
-<h3>Tally</h3>
+<h2>Tally</h2>
 <p>
 Syntax: <b>tally</b>
 <p>
@@ -1354,23 +1502,24 @@
 total, simplifies, displays the running total and average, and repeats.
 No equation spaces are used.
 <p>
-It is a convenient way of adding, subtracting, and averaging many numbers.
+It is a convenient way of adding, subtracting, and averaging many numbers and/or variables.
 Enter an empty line to end.
 
 <hr>
 <a name="taylor"></a>
-<h3>Taylor</h3>
+<h2>Taylor</h2>
 <p>
 Syntax: <b>taylor [variable] [order] [point]</b>
 <p>
 This command computes the Taylor series expansion of the current
-expression or RHS of the current equation, with respect to the specified variable.
+expression or RHS of the current equation, with respect to the specified <b>variable</b>.
+The Taylor series is sometimes used to approximate expressions.
 <p>
-It prompts you for the "point" of expansion, which is usually a variable or 0,
+It prompts you for the <b>point</b> of expansion, which is usually a variable or 0,
 but may be any expression.
-Use 0 to generate Maclaurin polynomials.
+Typically 0 is used to generate Maclaurin polynomials.
 <p>
-Then it prompts you for the order
+Then it prompts you for the <b>order</b>
 of the series, which is an integer indicating how many derivatives to
 take in the expansion (default is infinity, until the derivative reaches 0).
 <p>
@@ -1378,7 +1527,7 @@
 equation space, displayed, and becomes the current equation.
 The original expression is not modified.
 
-<pre>
+<pre class="sample">
 1-&gt; e#^x
 
 #1: e#^x
@@ -1397,20 +1546,22 @@
 
 <hr>
 <a name="unfactor"></a>
-<h3>Unfactor</h3>
+<h2>Unfactor</h2>
 <p>
 Syntax: <b>unfactor ["fully"] [equation-number-range]</b>
+<br>
+Alternate command name: <b>expand</b>
 <p>
-This command algebraically expands expressions.
+This command algebraically expands expressions by multiplying out products of sums and exponentiated sums.
 <p>
-"unfactor fully" will fully expand algebraic fractions.
-Use this if just plain "unfactor" doesn't do enough.
+"unfactor fully" fully expands by also expanding algebraic fractions,
+separating each fraction with a sum in the numerator into
+smaller fractions with the same denominator for each term in numerator.
 <p>
-Unfactoring is known as "expanding" or "multiplying out".
 To illustrate what unfactoring does,
 suppose you have the following equations:
 
-<pre>
+<pre class="sample">
 1-&gt; a=b*(c+d)
 
 #1: a = b*(c + d)
@@ -1430,23 +1581,22 @@
 </pre>
 
 <p>
-(x+y)^2 is converted to (x+y)*(x+y) and then multiplied out.
+<b>(x+y)^2</b> is converted to <b>(x+y)*(x+y)</b> and then multiplied out.
 
 <hr>
 <a name="version"></a>
-<h3>Version</h3>
+<h2>Version</h2>
 <p>
 Syntax: <b>version</b>
 <p>
-Outputs the Mathomatic version number and compile flags used.
+Outputs the Mathomatic version number, compile flags used, and maximum memory usage
+for the currently running version of Mathomatic.  The maximum memory usage displayed
+does not include stack size (which varies) or executable size.
 
 <hr>
-<p>
-<font size=2 color="red">Copyright &copy; 2005 George Gesslein II
-</font>
+<font color="red">Copyright &copy; 1987-2007 George Gesslein II</font>
 
 <hr>
-<p>
 <a href="http://www.mathomatic.org">Mathomatic Home Page</a>
 
 </body>

Modified: branches/vendor/mathomatic/doc/index.html
===================================================================
--- branches/vendor/mathomatic/doc/index.html	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/doc/index.html	2007-06-24 11:58:26 UTC (rev 1806)
@@ -3,22 +3,30 @@
 <head>
 <title>Mathomatic Documentation</title>
 </head>
+
 <body>
-<h1><img src="open_book_nae_02.png" alt="open book">Available Documentation for Mathomatic</h1>
-<ul>
-<li>
-The Mathomatic <a href="manual.html">User's Manual</a>
-<li>
+<h1>Available Documentation for Mathomatic</h1>
+
+<blockquote>
+<font size="+2">
+<img src="led_circle_green.png" alt="button">
+The Mathomatic <a href="manual.html">User Manual</a>
+<br>
+<img src="led_circle_green.png" alt="button">
 The Mathomatic <a href="am.html">Command Reference</a>
-<li>
+<br>
+<img src="led_circle_green.png" alt="button">
 The Mathomatic <a href="manpage.html">Man Page</a>
-<li>
-<a href="notes.html">Notes</a> on the Limitations of Computer Algebra Systems
-</ul>
-<p>
-All documentation for Mathomatic is hand-written in HTML and is easily printed.
+</font>
+</blockquote>
+
+<marquee>
+All documentation for Mathomatic is hand-written in HTML
+and is easily printed on a black and white or color printer using your web browser.
+</marquee>
+
 <hr>
-<p>
 <a href="http://www.mathomatic.org">Mathomatic Home Page</a>
+
 </body>
 </html>

Modified: branches/vendor/mathomatic/doc/manpage.html
===================================================================
--- branches/vendor/mathomatic/doc/manpage.html	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/doc/manpage.html	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,5 +1,5 @@
 <!-- Creator     : groff version 1.19.1 -->
-<!-- CreationDate: Tue May  9 12:05:11 2006 -->
+<!-- CreationDate: Tue Jun 12 16:58:46 2007 -->
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
 <html>
@@ -19,6 +19,7 @@
 <a href="#GENERAL">GENERAL</a><br>
 <a href="#ENVIRONMENT">ENVIRONMENT</a><br>
 <a href="#FILES">FILES</a><br>
+<a href="#REPORTING BUGS">REPORTING BUGS</a><br>
 <a href="#AUTHOR">AUTHOR</a><br>
 
 <hr>
@@ -41,8 +42,8 @@
 <tr valign="top" align="left">
 <td width="11%"></td>
 <td width="89%">
-<p><b>mathomatic</b> [ <b>-chqtuv</b> ] [ <b>-m</b> number ]
-[ input_files ]</p>
+<p><b>mathomatic</b> [ <b>-chqrtuv</b> ] [ <b>-m</b> number
+] [ input_files ]</p>
 </td>
 </table>
 <a name="DESCRIPTION"></a>
@@ -54,13 +55,19 @@
 <td width="11%"></td>
 <td width="89%">
 <p>Mathomatic is a portable, general purpose CAS (Computer
-Algebra System) that can automatically solve, simplify,
-combine, and compare algebraic equations. It does some
-calculus and handles all algebra, except trigonometry and
-logarithms. It is entirely hand-written in optimized C. It
+Algebra System) that can symbolically solve, simplify,
+combine, and compare algebraic equations, perform complex
+number and polynomial arithmetic, etc. It does some calculus
+and handles all algebra, except trigonometry and
+logarithms.</p>
+<!-- INDENTATION -->
+<p>Mathomatic is entirely hand-written in optimized C. It
 does not permit extremely large expressions, which can take
 a lot of memory and time. Instead reliability, ease of use,
 and speed are its features.</p>
+<!-- INDENTATION -->
+<p>All arithmetic is double precision floating point with 14
+decimal digits accuracy.</p>
 </td>
 </table>
 <a name="OPTIONS"></a>
@@ -90,11 +97,12 @@
 <td width="8%"></td>
 <td width="78%">
 
-<p>Enable HTML mode (also valid XHTML). This makes
-Mathomatic output suitable for inclusion in a web page. The
-color mode flag affects this mode, allowing HTML color
-output. It is recommended that the web page have a black
-background in color mode.</p>
+<p>Enable HTML output mode (also valid XHTML) and disable
+readline input. This makes Mathomatic output suitable for
+inclusion in a web page. The color mode flag affects this
+mode, allowing HTML color output. By default, Mathomatic
+uses maximum brightness colors for HTML, so it is
+recommended that the web page have a dark background.</p>
 </td>
 </table>
 <!-- INDENTATION -->
@@ -112,9 +120,9 @@
 <td width="22%"></td>
 <td width="78%">
 <p>Change the memory size of equation spaces. It is followed
-by a floating point number which is a multiplier of the
-default equation size. Please don&rsquo;t set this higher
-than 10, unless you know what you are doing.</p>
+by a decimal floating point number which is a multiplier of
+the default equation size. Please don&rsquo;t set this
+higher than 10, unless you know what you are doing.</p>
 </td>
 </table>
 <!-- TABS -->
@@ -129,20 +137,36 @@
 <td width="8%"></td>
 <td width="78%">
 
-<p>Sets quiet mode. Prompts are not displayed.</p>
+<p>Set quiet mode. The startup message and prompts are not
+displayed. This is useful when piping or redirecting input
+into Mathomatic, because the input won&rsquo;t be displayed,
+so prompt output should be turned off.</p>
 </td>
 <tr valign="top" align="left">
 <td width="11%"></td>
 <td width="3%">
 
+<p><b>&minus;r</b></p>
+</td>
+<td width="8%"></td>
+<td width="78%">
+
+<p>Completely disable readline input processing. Readline
+allows using the cursor keys and outputs terminal control
+codes which can be turned off with this option.</p>
+</td>
+<tr valign="top" align="left">
+<td width="11%"></td>
+<td width="3%">
+
 <p><b>&minus;t</b></p>
 </td>
 <td width="8%"></td>
 <td width="78%">
 
-<p>Sets test mode. Used when testing and comparing output.
-Bypasses loading startup file, turns off color mode,
-etc.</p>
+<p>Set test mode. Used when testing and comparing output.
+Bypasses loading startup file, turns off color mode and
+readline, sets infinite screen width and height, etc.</p>
 </td>
 <tr valign="top" align="left">
 <td width="11%"></td>
@@ -164,8 +188,10 @@
 <td width="8%"></td>
 <td width="78%">
 
-<p>Display version number and compile flags used and
-exit.</p>
+<p>Display version number, compile flags used, maximum
+memory usage, and then exit. The maximum memory usage
+displayed does not include stack size (which varies) or
+executable size.</p>
 </td>
 </table>
 <a name="GENERAL"></a>
@@ -177,22 +203,23 @@
 <td width="11%"></td>
 <td width="89%">
 <p>First you type in your algebraic equations in standard
-infix notation, then you can solve them by just typing in
-the variable, or perform operations on them with simple
-English commands. Type &quot;help&quot; for the help
-command. If the command is longer than 4 letters, you only
-need to type in the first 4 letters. Most commands operate
-on the current equation by default.</p>
+infix notation, then you can solve them by typing in the
+variable name at the prompt, or perform operations on them
+with simple English commands. Type &quot;help&quot; for the
+help command. If the command is longer than 4 letters, you
+only need to type in the first 4 letters. Most commands
+operate on the current equation by default.</p>
 <!-- INDENTATION -->
-<p>Documentation is available in HTML format, see the web
-site &quot;www.mathomatic.org&quot;.</p>
+<p>Documentation is available in HTML format, see the
+documentation directory or the web site
+&quot;www.mathomatic.org&quot;.</p>
 </td>
 </table>
 <a name="ENVIRONMENT"></a>
 <h2>ENVIRONMENT</h2>
 <!-- TABS -->
 <table width="100%" border=0 rules="none" frame="void"
-       cols="5" cellspacing="0" cellpadding="0">
+       cols="4" cellspacing="0" cellpadding="0">
 <tr valign="top" align="left">
 <td width="11%"></td>
 <td width="9%">
@@ -200,12 +227,11 @@
 <p><b>EDITOR</b></p>
 </td>
 <td width="2%"></td>
-<td width="53%">
+<td width="78%">
 
-<p>Editor to use for the edit command.</p>
+<p>This environment variable specifies the editor to use
+for the edit command.</p>
 </td>
-<td width="25%">
-</td>
 </table>
 <a name="FILES"></a>
 <h2>FILES</h2>
@@ -228,6 +254,17 @@
 not include the word &quot;set&quot;.</p>
 </td>
 </table>
+<a name="REPORTING BUGS"></a>
+<h2>REPORTING BUGS</h2>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="11%"></td>
+<td width="89%">
+<p>Report bugs to &lt;gesslein at panix.com&gt;.</p>
+</td>
+</table>
 <a name="AUTHOR"></a>
 <h2>AUTHOR</h2>
 <!-- INDENTATION -->
@@ -236,7 +273,7 @@
 <tr valign="top" align="left">
 <td width="11%"></td>
 <td width="89%">
-<p>George Gesslein II</p>
+<p>George Gesslein II &lt;gesslein at panix.com&gt;</p>
 </td>
 </table>
 <hr>

Modified: branches/vendor/mathomatic/doc/manual.html
===================================================================
--- branches/vendor/mathomatic/doc/manual.html	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/doc/manual.html	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,27 +1,37 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
 <html>
 <head>
-<title>Mathomatic User's Manual</title>
+<title>Mathomatic User Manual</title>
+<style type="text/css">
+.sample { border-style: dotted; border-width: 1px; color: green; background-color: white; padding: 10px; }
+.indent { margin-left: 2em; margin-right: 2em; }
+</style>
 </head>
+
 <body>
 <center>
-<h1>Mathomatic Version 12.5 User's Manual</h1>
+<h1>Mathomatic User Manual</h1>
+<img src="greenfade.png" alt="decoration">
 </center>
 
 <h2>Introduction</h2>
 <p>
-Mathomatic is a symbolic interpreter that can:
+Mathomatic is a symbolic math interpreter that can:
 <ul>
 <li>
-Solve, simplify, combine, and compare algebraic equations,
+combine and solve algebraic equations,
 <li>
-Perform calculus transformations,
+completely simplify and compare expressions,
 <li>
-Help with series analysis,
+perform calculus transformations,
 <li>
-Perform standard, complex number, and polynomial arithmetic and GCD computations,
+help with series analysis,
 <li>
-Generate efficient C, Java, or Python code from equations.
+perform standard, complex number, and polynomial arithmetic,
+<li>
+generate efficient C, Java, or Python code from equations,
+<li>
+do quick calculations, etc.
 </ul>
 
 <p>
@@ -35,7 +45,7 @@
 <dt>
 SYNOPSIS
 <dd>
-<b>mathomatic [-chqtuv] [-m number] [input_files]</b>
+<b>mathomatic [ options ] [ input_files ]</b>
 </dl>
 <p>
 To start the Mathomatic interpreter,
@@ -49,64 +59,68 @@
 The other options are described in the
 <a href="manpage.html">man page</a>.
 <p>
-After any options, file names may be specified on the command line
-that will be read in with the <a href="am.html#read">"read"</a> command.
+After any options, file names may be specified
+that will be read in with the <a href="am.html#read">read</a> command.
+<p>
+It is recommended that the name "mathomatic" be shortened to "am" for quicker access.
+This can be done in the Bash shell by adding the following line to the "~/.bashrc" file:
 
+<pre class="indent">
+alias am=mathomatic
+</pre>
+
+<p>
+Then just typing "am" at the shell prompt will bring up Mathomatic.
+
 <hr>
-<h2>Equations</h2>
+<h2>Equations and Expressions</h2>
 <p>
 Mathematical equations and expressions are entered
 into <strong>equation spaces</strong>.
 The number of available equation spaces is displayed
 every time Mathomatic starts up.
-
 <p>
 The Mathomatic prompt contains
 the number of the current equation space (origin 1).
-
 <p>
 To enter an equation into the first available equation space,
 simply type the equation at the prompt.
-Equations consist of a Left Hand Side (LHS)
-and a Right Hand Side (RHS).
-The equation sides are separated by one, and only one,
-equals sign (=).
+Equations consist of a Left Hand Side (LHS) and a Right Hand Side (RHS).
+The equation sides are separated by one, and only one, equals sign (<b>=</b>).
 An equation side consists of an algebraic mathematical expression,
 which is a mix of variables, constants, and operators,
-mostly in infix notation.
-Parentheses are used to override operator precedence and
-group things together.
-
+mostly in standard infix notation.
+Parentheses are used to override operator precedence and group things together.
 <p>
+Mathomatic currently doesn't support any functions, like trigonometry and logarithms.
+<p>
 Shown below is a valid equation with its parts labeled:
 
-<pre>
-                equation
-        -----------------------
-        | variables   constant|
-        |--------------     | |
-        ||     |      |     | |
-         a  =  b  -  (c  +  2)
-        | |   |   |      |    |
-        | |   |   --------    |
-        | |   |   operators   |
-        ---   -----------------
-        LHS          RHS
+<pre class="indent">
+        equation
+-----------------------
+| variables   constant|
+|--------------     | |
+||     |      |     | |
+ a  =  b  -  (c  +  2)
+| |   |   |      |    |
+| |   |   --------    |
+| |   |   operators   |
+---   -----------------
+LHS          RHS
 </pre>
 
 <p>
-In the above equation, the variable (a) is called the dependent
-variable because its value depends on the variables (b) and (c).
-(b) and (c) are called independent variables.  In Mathomatic,
+In the above equation, the variable <b>a</b> is called the dependent
+variable because its value depends on the variables <b>b</b> and <b>c</b>.
+<b>b</b> and <b>c</b> are called independent variables.  In Mathomatic,
 any variable can be made the dependent variable by simply typing
-the variable name in at the prompt.  This will <a href="am.html#solve">solve</a> the equation
-for that variable
-and, if successful, make that variable the LHS.
-
+the variable name in at the prompt.  This will <a href="am.html#solving">solve</a> the equation
+for that variable and, if successful, make that variable the LHS.
 <p>
-Here is the above equation entered into Mathomatic and solved for (b):
+Here is the above equation entered into Mathomatic and solved for <b>b</b>:
 
-<pre>
+<pre class="sample">
 1-&gt; a=b-(c+2)
 
 #1: a = b - c - 2
@@ -120,19 +134,20 @@
 
 <h3>Constants</h3>
 <p>
-Constants are IEEE 64 bit double precision (14 decimal digits) floating point numbers.
+Constants are IEEE 64-bit (8 bytes) double precision floating point numbers.
 They may be entered in normal, scientific, or hexadecimal notation.
-They are displayed in decimal in normal or scientific notation,
+They are displayed in decimal (up to 14 digits) in normal or scientific notation,
 whichever is shortest.
-
+Results exceeding 14 digits are always rounded to 14 digits and
+are usually accurate from 12 to 14 digits, due to accumulated round-off error.
 <p>
+Constants always start with a digit (0..9) or a period.
 To enter a constant in hexadecimal, prepend it with "0x".
-
 <p>
 Examples of equivalent constants follow:
 </p>
 
-<table summary="constant notation examples" border=1>
+<table summary="constant notation examples" border=1 cellpadding=5>
 <tr>
 <th>
 Normal Notation
@@ -186,12 +201,24 @@
 The smallest value of a constant is &plusmn;2.3e-308.
 </ul>
 <p>
-Mathomatic results are almost always accurate to 12 digits.
-It is possible to get a result that is accurate to less digits,
-due to floating point inexactness,
-but you would have to really try.
+The infinity constant is entered by typing "inf".
+Positive and negative infinity are distinct and understood,
+however division by zero produces infinity, not &plusmn;infinity
+which would be more correct.
 <p>
-The infinity constant is entered by typing "inf".
+Fractions (such as <b>100/101</b>) are preserved if
+the numerator and denominator are not large.
+Fractions are always presented in fully reduced form
+(for example, <b>6/9</b> is converted to <b>2/3</b>).
+Constants which are exactly equal to a fraction are converted and displayed
+as fully reduced fractions (for example, <b>0.5</b> converts to <b>1/2</b>).
+Mathomatic internally converts a fraction to a single floating point value,
+then converts it back to a fraction for display,
+after all floating point arithmetic has been done.
+<p>
+Irrational numbers, such as <b>2^(1/2)</b>, are preserved and simplified, if possible.
+This can be turned off with the command "set no preserve_roots",
+<b>2^(1/2)</b> will then always be approximated as <b>1.4142135623731</b>.
 
 <h3>Variables</h3>
 <p>
@@ -201,33 +228,30 @@
 They can represent known or unknown values,
 or any expression.
 <p>
-Variables consist of any combination of letters, digits, underscores (_),
-and backslashes (\).  They never start with a digit.
-
+Variables consist of any combination of letters, digits, and underscores (_).
+They never start with a digit.
 <p>
 The following variables are predefined and are not normal variables:
 
-<pre>
-<b>e#</b> - the universal constant e (2.718281828...).
-<b>pi</b> - the universal constant pi (3.1415926...).
-<b>i#</b> - imaginary number (square root of -1).
-<b>sign, sign1, sign2, sign3, ...</b> - may be +1 or -1.
+<pre class="indent">
+<b>e</b> or <b>e#</b> - the universal constant e (2.718281828...).
+<b>pi</b> or <b>pi#</b> - the universal constant pi (3.1415926...).
+<b>i</b> or <b>i#</b> - imaginary number (square root of -1).
+<b>sign, sign1, sign2, sign3, ...</b> - may only be +1 or -1.
 <b>integer</b> - may be any integer.
 </pre>
 
 <p>
-By default,
-letters in variable names
-are case sensitive.
+By default, letters in variable names are case sensitive.
 <p>
-To automatically enter a unique (sign) variable,
+To automatically enter a unique <b>sign</b> variable,
 precede any expression with "+/-".
 
 <h3>Operators</h3>
 <p>
 Operators have precedence decreasing as indicated:
 
-<pre>
+<pre class="indent">
 - negate                               (unary prefix operator)
 ! factorial (gamma function)           (unary postfix operator)
 ** or ^ power (exponentiation)         (binary infix operator)
@@ -239,53 +263,68 @@
 <p>
 Operators in the same precedence level are evaluated left to right.
 <p>
-The negate operator "-" may precede any expression.
-The negate operator has the highest precedence of all operators.
-This is different from many math programs, where negate
-has been erroneously given the same precedence as times/divide.
-So things like "-2^x" will give the expected -2 to the power
-of x, and not "-1*(2^x)", which are completely different.
+All operators can be symbolically simplified by Mathomatic, except for factorial.
 <p>
-The default operator for variables and constants is multiply ("*").
+The negate operator (<b>-</b>) may precede any expression and
+has the highest precedence of all operators.
+This is different from many other math programs, where negate
+has been given the same precedence as times/divide.
+So in Mathomatic <b>-2^x</b> will give the expected <b>-2</b> to the power
+of <b>x</b>, and not <b>-1*(2^x)</b>, which are completely different.
+<p>
+The default operator for variables and constants is multiply (<b>*</b>).
 If a variable or constant is entered when an operator is expected,
 a multiply operator is automatically inserted.
 <p>
-The modulus operator "a % b" gives the numerical remainder
-of the division "a / b".
+The modulo operator <b>a % b</b> gives the remainder
+of the division <b>a / b</b>.
 <p>
-Standard absolute value notation is allowed.
-"|x|" is converted to "(x^2)^.5".
+Factorials (<b>x!</b>) use the gamma function (<b>gamma(x+1)</b>),
+so that they work with any real number, not just the positive integers.
+On overflow the factorial remains unevaluated:
+
+<pre class="sample">
+1-&gt; 170!
+ answer = 7.2574156153081e+306
+
+1-&gt; 171!
+ answer = 171!
+
+1-&gt;
+</pre>
+
+<p>
+Standard absolute value notation is allowed,
+<b>|x|</b> is converted to <b>(x^2)^.5</b>.
 This doesn't always work as expected,
 but works enough to be useful.
 <p>
 The following example shows why operator precedence is important.
 Given the expression:
 
-<pre>
+<pre class="indent">
 64/-2^4 + 6*(3+1)
 </pre>
 
 <p>
-Mathomatic will first parenthesize the highest precedence operator (power)
-and then the lower precedence operators (times and divide).
+Mathomatic will parenthesize the highest precedence operators first
+(negate, then power, then times and divide).
 Addition and subtraction are the lowest precedence, so no need
 to parenthesize them.
 The result will be:
 
-<pre>
-(64/(-2^4)) + (6*(3+1))
+<pre class="indent">
+(64/((-2)^4)) + (6*(3+1))
 </pre>
 
 <p>
-Mathomatic will evaluate this by combining constants from left to right
+This is evaluated by combining constants from left to right
 on the same level of parentheses, deepest levels first.
 So the calculations are performed in the following order:
 
-<pre>
+<pre class="indent">
 (64/16) + (6*4)   Combine deepest level parentheses first.
-
 4 + 24            Divided 64 by 16 and then multiplied 6 by 4.
-
 28                Added 24 to 4.
 </pre>
 
@@ -295,42 +334,52 @@
 
 <h3>Complex Numbers</h3>
 <p>
-Mathomatic can perform
-complex number addition, subtraction,
+Mathomatic automatically performs complex number addition, subtraction,
 multiplication, and division.
-It can also do roots and powers of complex numbers.
+It will also approximate roots and powers of complex numbers.
 <p>
 Complex numbers are in the form:
 
-<pre>
+<pre class="indent">
 a + b*i#
 </pre>
 
 <p>
-where "a" is the <a href="am.html#real">"real part"</a>
-and "b" is the <a href="am.html#imaginary">"imaginary part"</a>.
-"a" and "b" may be constants, variables, or expressions.
-"i#" represents the square root of -1.
+where <b>a</b> is the <a href="am.html#real">real part</a>
+and <b>b</b> is the <a href="am.html#imaginary">imaginary part</a>.
+<b>i#</b> represents the square root of -1
+("-1^.5" in Mathomatic notation).
 <p>
-The imaginary number "i#" may appear anywhere within an expression,
+The imaginary number <b>i#</b> may appear anywhere within an expression,
 as many times as you want.
 Mathomatic will handle it properly.
+<p>
+As an example of imaginary numbers being produced, <b>-2^.5</b> will be converted
+to <b>(2^.5)*i#</b>.
+<p>
+Roots of complex numbers, such as <b>i#^.5</b>, will be approximated, and
+only a single root will be produced, even though there may be many roots.
+This may produce inaccurate, unexpected, or even incorrect results, therefore
+a warning is displayed when this is done.
+<p>
+Conjugation of all complex numbers in the current equation
+is accomplished by typing the following command:
 
+<pre class="indent">
+replace i# with -i#
+</pre>
+
 <hr>
 <h2>Commands</h2>
 <p>
-Please consult the Mathomatic Command Reference,
+Mathomatic has about 39 different commands that may be typed at the main prompt.
+Please consult the <a href="am.html">Mathomatic Command Reference</a>,
 for detailed information on commands.
-It is available in the file
-<a href="am.html">"am.html"</a>.
 
 <hr>
-<p>
-<font size=2 color="red">Copyright &copy; 2005 George Gesslein II
-</font>
+<font color="red">Copyright &copy; 1987-2007 George Gesslein II</font>
 
 <hr>
-<p>
 <a href="http://www.mathomatic.org">Mathomatic Home Page</a>
 
 </body>

Deleted: branches/vendor/mathomatic/doc/notes.html

Modified: branches/vendor/mathomatic/externs.h
===================================================================
--- branches/vendor/mathomatic/externs.h	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/externs.h	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,25 +1,27 @@
 /*
- * Algebraic manipulator externals.
+ * Mathomatic global variable extern definitions, from file "globals.c".
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 extern int		n_tokens;
 extern int		n_equations;
 extern int		cur_equation;
 
+extern token_type	*lhs[N_EQUATIONS];
+extern token_type	*rhs[N_EQUATIONS];
+
 extern int		n_lhs[N_EQUATIONS];
 extern int		n_rhs[N_EQUATIONS];
 
-extern token_type	*lhs[N_EQUATIONS];
-extern token_type	*rhs[N_EQUATIONS];
+extern token_type	*tlhs;
+extern token_type	*trhs;
+extern token_type	*tes;
 
 extern int		n_tlhs;
 extern int		n_trhs;
+extern int		n_tes;
 
-extern token_type	*tlhs;
-extern token_type	*trhs;
-
 extern token_type	*scratch;
 
 extern token_type	zero_token;
@@ -27,22 +29,26 @@
 
 extern char		*var_names[MAX_VAR_NAMES];
 
+extern int		precision;
 extern int		case_sensitive_flag;
 extern int		factor_int_flag;
-extern int		groupall;
-extern int		in_calc_cmd;
+extern int		display2d;
+extern int		approximate_roots;
 extern int		preserve_roots;
 extern int		true_modulus;
 extern int		screen_columns;
 extern int		screen_rows;
 extern int		finance_option;
-extern int		starstar;
+extern int		autosolve;
+extern int		autocalc;
+extern char		special_variable_character;
 extern int		debug_level;
 extern int		domain_check;
 extern int		color_flag;
 extern int		bold_colors;
 extern int		cur_color;
 extern int		html_flag;
+extern int		readline_enabled;
 extern int		partial_flag;
 extern int		symb_flag;
 extern int		high_prec;

Modified: branches/vendor/mathomatic/factor.c
===================================================================
--- branches/vendor/mathomatic/factor.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/factor.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
- * Algebraic manipulator symbolic factorizing routines.
+ * Mathomatic symbolic factorizing routines.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  *
  * There are proper mathematical names for many algebraic rules.
  * I obviously don't know what they are.
@@ -18,8 +18,7 @@
 static int	fpower_sub();
 
 /*
- * Factor divides only.
- * (a/c + b/c) -> ((a+b)/c).
+ * Factor divides only: (a/c + b/c) -> ((a+b)/c).
  *
  * Return true if equation side was modified.
  */
@@ -30,13 +29,12 @@
 long		v;
 double		d;
 {
-	return fplus_recurse(equation, np, 0, 1, v, d, 2);
+	return fplus_recurse(equation, np, 0, 1, v, d, false, true);
 }
 
 /*
  * Take care of subtraction and addition of the same expression
- * multiplied by constants.
- * (2*a + 3*a - a) -> (4*a).
+ * multiplied by constants: (2*a + 3*a - a) -> (4*a).
  *
  * Return true if equation side was modified.
  */
@@ -45,19 +43,18 @@
 token_type	*equation;
 int		*np;
 {
-	return fplus_recurse(equation, np, 0, 1, 0L, 0.0, 1);
+	return fplus_recurse(equation, np, 0, 1, 0L, 0.0, true, false);
 }
 
 /*
- * Factor equation side.
- * (a*c + b*c) -> (c*(a + b)).
+ * Factor equation side: (a*c + b*c) -> (c*(a + b)).
  *
- * If "v" equals 0L, factor anything,
- * including identical bases raised to powers:
- * (x^2 + x) -> (x*(x + 1)).
+ * If "v" and "d" equals 0, factor anything,
+ * including identical bases raised to powers (Horner factoring): (x^2 + x) -> (x*(x + 1)).
  * If "d" equals 1.0, only factor identical bases raised to the power of a constant.
  *
- * If "v" is a variable, only factor expressions containing that variable.
+ * If "v" is a variable, only factor expressions containing that variable,
+ * with no Horner factoring.
  * If "d" is not equal to 0.0 or 1.0, factor only expressions containing "v" raised
  * to the power of "d".
  *
@@ -65,12 +62,12 @@
  */
 int
 factor_plus(equation, np, v, d)
-token_type	*equation;
-int		*np;
-long		v;
-double		d;
+token_type	*equation;	/* pointer to beginning of equation side */
+int		*np;		/* pointer to length of equation side */
+long		v;		/* variable */
+double		d;		/* control exponent */
 {
-	return fplus_recurse(equation, np, 0, 1, v, d, 0);
+	return fplus_recurse(equation, np, 0, 1, v, d, false, false);
 }
 
 /*
@@ -80,12 +77,13 @@
  * Return true if the expression was modified.
  */
 static int
-fplus_recurse(equation, np, loc, level, v, d, factor_code)
+fplus_recurse(equation, np, loc, level, v, d, whole_flag, div_only)
 token_type	*equation;
 int		*np, loc, level;
 long		v;
 double		d;
-int		factor_code;
+int		whole_flag;	/* factor only whole expressions multiplied by a constant */
+int		div_only;	/* factor only divides */
 {
 	int	modified = false;
 	int	i, j, k;
@@ -117,7 +115,7 @@
 						break;
 				}
 				len2 = k - j;
-				if (fplus_sub(equation, np, loc, i, len1, j, len2, level + 1, factor_code == 1, factor_code == 2, v, d)) {
+				if (fplus_sub(equation, np, loc, i, len1, j, len2, level + 1, v, d, whole_flag, div_only)) {
 					modified = true;
 					goto f_again;
 				}
@@ -131,7 +129,7 @@
 		return true;
 	for (i = loc; i < *np && equation[i].level >= level;) {
 		if (equation[i].level > level) {
-			modified |= fplus_recurse(equation, np, i, level + 1, v, d, factor_code);
+			modified |= fplus_recurse(equation, np, i, level + 1, v, d, whole_flag, div_only);
 			i++;
 			for (; i < *np && equation[i].level > level; i += 2)
 				;
@@ -148,16 +146,16 @@
  * Return true if a transformation was made.
  */
 static int
-fplus_sub(equation, np, loc, i1, n1, i2, n2, level, whole_flag, div_only, v, d)
+fplus_sub(equation, np, loc, i1, n1, i2, n2, level, v, d, whole_flag, div_only)
 token_type	*equation;	/* the entire expression */
 int		*np;		/* pointer to length of the entire expression */
 int		loc;		/* index into the beginning of this additive subexpression */
 int		i1, n1, i2, n2;
 int		level;
+long		v;
+double		d;
 int		whole_flag;	/* factor only whole expressions multiplied by a constant */
 int		div_only;	/* factor only divides */
-long		v;
-double		d;
 {
 	int	e1, e2;
 	int	op1, op2;
@@ -171,7 +169,7 @@
 	int	same_flag;
 	double	save_k1, save_k2;
 	double	save_d1, save_d2;
-	double	power;
+	double	power;		/* for constant power horner factoring */
 	double	d1, d2;
 
 	e1 = i1 + n1;
@@ -179,8 +177,9 @@
 	op2 = equation[i2-1].token.operatr;
 	if (i1 <= loc) {
 		op1 = PLUS;
-	} else
+	} else {
 		op1 = equation[i1-1].token.operatr;
+	}
 	i = i1 - 1;
 f_outer:
 	b1 = i + 1;
@@ -276,33 +275,33 @@
 	}
 	ai = i;
 	aj = j;
-	if (whole_flag) {
-		if (flag1 = (b1 > i1)) {
-			b1 = i1;
-			save_k1 = equation[b1].token.constant;
-			equation[b1].token.constant = 1.0;
-		}
-		if (flag2 = (b2 > i2)) {
-			b2 = i2;
-			save_k2 = equation[b2].token.constant;
-			equation[b2].token.constant = 1.0;
-		}
+	save_k1 = 0.0;
+	save_k2 = 0.0;
+	flag1 = (whole_flag && b1 > i1);
+	if (flag1) {
+		b1 = i1;
+		save_k1 = equation[b1].token.constant;
+		equation[b1].token.constant = 1.0;
 	}
+	flag2 = (whole_flag && b2 > i2);
+	if (flag2) {
+		b2 = i2;
+		save_k2 = equation[b2].token.constant;
+		equation[b2].token.constant = 1.0;
+	}
 	same_flag = se_compare(&equation[b1], i - b1, &equation[b2], j - b2, &diff_sign);
-	if (whole_flag) {
-		if (flag1) {
-			equation[i1].token.constant = save_k1;
-			b1 += 2;
-		}
-		if (flag2) {
-			equation[i2].token.constant = save_k2;
-			b2 += 2;
-		}
+	if (flag1) {
+		equation[i1].token.constant = save_k1;
+		b1 += 2;
 	}
+	if (flag2) {
+		equation[i2].token.constant = save_k2;
+		b2 += 2;
+	}
 	if (same_flag) {
 		/* do the factor transformation */
-		power = 1.0;
-more_power:
+		power = 1.0;	/* not doing Horner factoring */
+horner_factor:
 		if (sop1 == DIVIDE) {
 			scratch[0].level = level;
 			scratch[0].kind = CONSTANT;
@@ -311,10 +310,11 @@
 			scratch[1].kind = OPERATOR;
 			scratch[1].token.operatr = DIVIDE;
 			len = 2;
-		} else
+		} else {
 			len = 0;
+		}
 		k = len;
-		blt(&scratch[len], &equation[b1], (ai - b1) * sizeof(*equation));
+		blt(&scratch[len], &equation[b1], (ai - b1) * sizeof(token_type));
 		len += ai - b1;
 		if (power != 1.0) {
 			for (; k < len; k++)
@@ -338,12 +338,12 @@
 		scratch[len].token.operatr = TIMES;
 		len++;
 		k = len;
-		blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(*equation));
+		blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
 		len += b1 - i1;
 		if (ai != i) {
 			l = len;
 			m = len + ai - b1;
-			blt(&scratch[len], &equation[b1], (i - b1) * sizeof(*equation));
+			blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
 			len += i - b1;
 			if (b1 == i1 && i == e1) {
 				for (; l < len; l++)
@@ -370,20 +370,22 @@
 		scratch[len].kind = CONSTANT;
 		if (op1 == MINUS) {
 			scratch[len].token.constant = -1.0;
-		} else
+		} else {
 			scratch[len].token.constant = 1.0;
+		}
 		len++;
-		blt(&scratch[len], &equation[i], (e1 - i) * sizeof(*equation));
+		blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
 		len += e1 - i;
 		for (; k < len; k++)
 			scratch[k].level += 2;
 		scratch[len].level = level + 1;
 		scratch[len].kind = OPERATOR;
 		diff_sign ^= (op2 == MINUS);
-		if (diff_sign)
+		if (diff_sign) {
 			scratch[len].token.operatr = MINUS;
-		else
+		} else {
 			scratch[len].token.operatr = PLUS;
+		}
 		len++;
 		k = len;
 		if (aj != j) {
@@ -395,11 +397,11 @@
 				error_huge();
 			}
 		}
-		blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(*equation));
+		blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
 		len += b2 - i2;
 		if (aj != j) {
 			m = len + aj - b2;
-			blt(&scratch[len], &equation[b2], (j - b2) * sizeof(*equation));
+			blt(&scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
 			len += j - b2;
 			l = m;
 			m++;
@@ -419,7 +421,7 @@
 			scratch[len].token.constant = 1.0;
 			len++;
 		}
-		blt(&scratch[len], &equation[j], (e2 - j) * sizeof(*equation));
+		blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
 		len += e2 - j;
 		for (; k < len; k++)
 			scratch[k].level += 2;
@@ -430,17 +432,17 @@
 		if (op1 == MINUS) {
 			equation[i1-1].token.operatr = PLUS;
 		}
-		blt(&equation[i2-1], &equation[e2], (*np - e2) * sizeof(*equation));
+		blt(&equation[i2-1], &equation[e2], (*np - e2) * sizeof(token_type));
 		*np -= n2 + 1;
-		blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(*equation));
+		blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(token_type));
 		*np += len - n1;
-		blt(&equation[i1], scratch, len * sizeof(*equation));
+		blt(&equation[i1], scratch, len * sizeof(token_type));
 		return true;
 	}
 	if (whole_flag)
 		return false;
 	if (v || div_only)
-		goto f_inner;
+		goto f_inner;	/* don't do Horner factoring */
 	if (b1 == i1 && i == e1)
 		k = level;
 	else
@@ -455,8 +457,9 @@
 				save_d1 = equation[l+1].token.constant;
 				if (save_d1 <= 0.0)
 					goto f_inner;
-			} else
+			} else {
 				save_d1 = -1.0;
+			}
 			ai = l;
 			break;
 		}
@@ -475,8 +478,9 @@
 				save_d2 = equation[l+1].token.constant;
 				if (save_d2 <= 0.0)
 					goto f_inner;
-			} else
+			} else {
 				save_d2 = -1.0;
+			}
 			aj = l;
 			break;
 		}
@@ -489,22 +493,22 @@
 		goto f_inner;
 	if (se_compare(&equation[b1], ai - b1, &equation[b2], aj - b2, &diff_sign)) {
 		if (save_d1 > 0.0 || save_d2 > 0.0) {
-			if (save_d1 < 0.0)
+			if (save_d1 < 0.0) {
 				power = save_d2;
-			else if (save_d2 < 0.0)
+			} else if (save_d2 < 0.0) {
 				power = save_d1;
-			else {
+			} else {
 				power = min(save_d1, save_d2);
 				if (!diff_sign && (fmod(power, 1.0) != 0.0)) {
 					if (fmod(max(save_d1, save_d2) - power, 1.0) == 0.0) {
-						goto more_power;
+						goto horner_factor;
 					}
 				}
 			}
 			if (power < 1.0)
 				goto f_inner;
 			modf(power, &power);
-			goto more_power;
+			goto horner_factor;
 		}
 		d1 = i - ai;
 		d2 = j - aj;
@@ -546,7 +550,7 @@
 
 /*
  * Factor transformation for a more general pair of subexpressions added together
- * with a common base.
+ * with a common base and any exponent.
  */
 static int
 big_fplus(equation, level, diff_sign, sop1, op1, op2, i1, i2, b1, b2, ai, aj, i, j, e1, e2)
@@ -572,11 +576,12 @@
 		scratch[1].kind = OPERATOR;
 		scratch[1].token.operatr = DIVIDE;
 		len = 2;
-	} else
+	} else {
 		len = 0;
+	}
 	k = len;
 	o = len + ai - b1;
-	blt(&scratch[len], &equation[b1], (i - b1) * sizeof(*equation));
+	blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
 	len += i - b1;
 	if (b1 == i1 && i == e1) {
 		for (; k < len; k++)
@@ -587,7 +592,7 @@
 	scratch[len].token.operatr = TIMES;
 	len++;
 	k = len;
-	blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(*equation));
+	blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
 	len += b1 - i1;
 	scratch[len].level = level;
 	scratch[len].kind = CONSTANT;
@@ -597,7 +602,7 @@
 		scratch[len].token.constant = 1.0;
 	}
 	len++;
-	blt(&scratch[len], &equation[i], (e1 - i) * sizeof(*equation));
+	blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
 	len += e1 - i;
 	for (; k < len; k++)
 		scratch[k].level += 2;
@@ -606,14 +611,14 @@
 	scratch[len].token.operatr = op2;
 	len++;
 	k = len;
-	blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(*equation));
+	blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
 	len += b2 - i2;
 	if (len + (e2 - b2) + 2 * (i - ai) + 2 > n_tokens) {
 		error_huge();
 	}
 	n = len;
 	m = len + aj - b2;
-	blt(&scratch[len], &equation[b2], (j - b2) * sizeof(*equation));
+	blt(&scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
 	len += j - b2;
 	l = m;
 	m++;
@@ -628,7 +633,7 @@
 	scratch[len].token.operatr = MINUS;
 	len++;
 	m = len;
-	blt(&scratch[len], &equation[ai+1], (i - (ai + 1)) * sizeof(*equation));
+	blt(&scratch[len], &equation[ai+1], (i - (ai + 1)) * sizeof(token_type));
 	len += i - (ai + 1);
 	n = min_level(&equation[ai+1], i - (ai + 1));
 	n = scratch[l].level + 2 - n;
@@ -646,10 +651,10 @@
 		scratch[len].kind = CONSTANT;
 		scratch[len].token.constant = -1.0;
 		len++;
-		blt(&scratch[len], &scratch[o], (i - ai) * sizeof(*equation));
+		blt(&scratch[len], &scratch[o], (i - ai) * sizeof(token_type));
 		len += i - ai;
 	}
-	blt(&scratch[len], &equation[j], (e2 - j) * sizeof(*equation));
+	blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
 	len += e2 - j;
 	for (; k < len; k++)
 		scratch[k].level += 2;
@@ -803,7 +808,7 @@
 	if (*np + len > n_tokens) {
 		error_huge();
 	}
-	blt(&equation[e1+len], &equation[e1], (*np - e1) * sizeof(*equation));
+	blt(&equation[e1+len], &equation[e1], (*np - e1) * sizeof(token_type));
 	*np += len;
 	if (i == e1) {
 		for (k = i1; k < e1; k++)
@@ -817,7 +822,7 @@
 	}
 	if (op1 == DIVIDE && !both_divide) {
 		equation[i1-1].token.operatr = TIMES;
-		blt(&equation[i+3], &equation[i+1], rlen1 * sizeof(*equation));
+		blt(&equation[i+3], &equation[i+1], rlen1 * sizeof(token_type));
 		i++;
 		equation[i].level = level;
 		equation[i].kind = CONSTANT;
@@ -840,10 +845,10 @@
 		equation[i+1].kind = CONSTANT;
 		equation[i+1].token.constant = 1.0;
 	} else {
-		blt(&equation[i+1], &equation[j+len+1], (e2 - j - 1) * sizeof(*equation));
+		blt(&equation[i+1], &equation[j+len+1], (e2 - j - 1) * sizeof(token_type));
 	}
 	binary_parenthesize(equation, i + e2 - j, i);
-	blt(&equation[i2+len-1], &equation[e2+len], (*np - (e2 + len)) * sizeof(*equation));
+	blt(&equation[i2+len-1], &equation[e2+len], (*np - (e2 + len)) * sizeof(token_type));
 	*np -= n2 + 1;
 	return true;
 }
@@ -939,8 +944,9 @@
 	op2 = equation[i2-1].token.operatr;
 	if (i1 <= loc) {
 		op1 = TIMES;
-	} else
+	} else {
 		op1 = equation[i1-1].token.operatr;
+	}
 	for (i = i1 + 1;; i += 2) {
 		if (i >= e1)
 			return false;
@@ -1006,7 +1012,7 @@
 			diff_sign = !diff_sign;
 		all_divide = (op1 == DIVIDE && diff_sign);
 		len = 0;
-		blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(*equation));
+		blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
 		len += b1 - i1;
 		scratch[len].level = level + 1;
 		scratch[len].kind = CONSTANT;
@@ -1016,7 +1022,7 @@
 			scratch[len].token.constant = 1.0;
 		}
 		len++;
-		blt(&scratch[len], &equation[i], (e1 - i) * sizeof(*equation));
+		blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
 		len += e1 - i;
 		for (k = 0; k < len; k++)
 			scratch[k].level += 2;
@@ -1025,7 +1031,7 @@
 		scratch[len].token.operatr = TIMES;
 		len++;
 		k = len;
-		blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(*equation));
+		blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
 		len += b2 - i2;
 		scratch[len].level = level + 1;
 		scratch[len].kind = CONSTANT;
@@ -1035,7 +1041,7 @@
 			scratch[len].token.constant = 1.0;
 		}
 		len++;
-		blt(&scratch[len], &equation[j], (e2 - j) * sizeof(*equation));
+		blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
 		len += e2 - j;
 		for (; k < len; k++)
 			scratch[k].level += 2;
@@ -1054,7 +1060,7 @@
 			len++;
 		}
 		k = len;
-		blt(&scratch[len], &equation[b1], (i - b1) * sizeof(*equation));
+		blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
 		len += i - b1;
 		for (; k < len; k++)
 			scratch[k].level++;
@@ -1064,11 +1070,11 @@
 		if (!all_divide && op1 == DIVIDE) {
 			equation[i1-1].token.operatr = TIMES;
 		}
-		blt(&equation[i2-1], &equation[e2], (*np - e2) * sizeof(*equation));
+		blt(&equation[i2-1], &equation[e2], (*np - e2) * sizeof(token_type));
 		*np -= n2 + 1;
-		blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(*equation));
+		blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(token_type));
 		*np += len - n1;
-		blt(&equation[i1], scratch, len * sizeof(*equation));
+		blt(&equation[i1], scratch, len * sizeof(token_type));
 		return true;
 	}
 	goto fp_inner;

Modified: branches/vendor/mathomatic/factor_int.c
===================================================================
--- branches/vendor/mathomatic/factor_int.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/factor_int.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
- * Algebraic manipulator constant factorizing routines.
+ * Mathomatic floating point constant factorizing routines.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -9,8 +9,9 @@
 static void	try_factor();
 static int	fc_recurse();
 
+/* The following data is used to factor integers: */
 static double nn, vv;
-static double sq[] = {		/* Additive array that skips over multiples of 2, 3, 5, and 7. */
+static double skip_multiples[] = {	/* Additive array that skips over multiples of 2, 3, 5, and 7. */
 	10, 2, 4, 2, 4, 6, 2, 6,
 	 4, 2, 4, 6, 6, 2, 6, 4,
 	 2, 6, 4, 6, 8, 4, 2, 4,
@@ -21,7 +22,7 @@
 
 /*
  * Factor the integer in "start".
- * Store unique factors in the "unique[]" array.
+ * Store the prime factors in the unique[] array.
  *
  * Return true if successful.
  */
@@ -30,12 +31,13 @@
 double	start;
 {
 	int	i;
-	double	ii;
+	double	d;
 
 	uno = 0;
 	nn = start;
-	if (nn == 0.0)
+	if (nn == 0.0) {
 		return false;
+	}
 	if (fabs(nn) >= MAX_K_INTEGER) {
 		/* too large to factor */
 		return false;
@@ -49,16 +51,20 @@
 	try_factor(3.0);
 	try_factor(5.0);
 	try_factor(7.0);
-	ii = 1.0;
-	while (ii <= vv) {
-		for (i = 0; i < ARR_CNT(sq); i++) {
-			ii += sq[i];
-			try_factor(ii);
+	d = 1.0;
+	while (d <= vv) {
+		for (i = 0; i < ARR_CNT(skip_multiples); i++) {
+			d += skip_multiples[i];
+			try_factor(d);
 		}
 	}
 	if (nn != 1.0) {
 		try_factor(nn);
 	}
+	if (start != multiply_out_unique()) {
+		error("Internal error factoring integers.");
+		return false;
+	}
 	return true;
 }
 
@@ -105,7 +111,7 @@
 }
 
 /*
- * Display the factors in the unique[] array.
+ * Display the prime factors in the unique[] array.
  */
 display_unique()
 {
@@ -126,9 +132,9 @@
 }
 
 /*
- * Factor integers in an expression.
+ * Factor integers in an equation side.
  *
- * Return true if expression was modified.
+ * Return true if equation side was modified.
  */
 int
 factor_int(equation, np)
@@ -197,16 +203,30 @@
 }
 
 /*
- * Factor constants in equation side.
+ * Factor integers in an equation space.
+ */
+factor_int_sub(n)
+int	n;	/* equation space number */
+{
+	if (n_lhs[n] <= 0)
+		return;
+	factor_int(lhs[n], &n_lhs[n]);
+	factor_int(rhs[n], &n_rhs[n]);
+}
+
+/*
+ * Neatly factor out coefficients in additive expressions in an equation side.
+ * For example: (2*x + 4*y + 6) becomes 2*(x + 2*y + 3).
  *
  * This routine is often necessary because the expression compare (se_compare())
  * does not return a multiplier (except for +/-1.0).
  * This routine is not used during polynomial operations.
- * It is required for simplification of algebraic fractions, etc.
+ * Normalization done here is required for simplification of algebraic fractions, etc.
  *
  * If "level_code" is 0, all additive expressions are normalized
- * by making at least one coefficient unity by factoring out
- * the smallest constant.
+ * by making at least one coefficient unity (1) by factoring out
+ * the smallest constant.  The absolute value of all other coefficients will be >= 1.
+ * If all coefficients are negative, -1 will be factored out, too.
  *
  * If "level_code" is 1, any level 1 additive expression is factored
  * nicely for readability, while all deeper levels are normalized.
@@ -220,9 +240,9 @@
  */
 int
 factor_constants(equation, np, level_code)
-token_type	*equation;
-int		*np;
-int		level_code;
+token_type	*equation;	/* pointer to the beginning of equation side */
+int		*np;		/* pointer to length of equation side */
+int		level_code;	/* see above */
 {
 	if (level_code > 2)
 		return false;
@@ -268,7 +288,7 @@
 				if (first) {
 					minimum = d;
 					first = false;
-				} else if (d < minimum) {
+				} else if (minimum > d) {
 					minimum = d;
 				}
 				break;
@@ -289,15 +309,14 @@
 				if (first) {
 					minimum = 1.0;
 					first = false;
-				} else if (1.0 < minimum)
+				} else if (minimum > 1.0) {
 					minimum = 1.0;
+				}
 				break;
 			}
 		} else {
 			op = 0;
-			for (j = i + 1;; j += 2) {
-				if (j >= *np || equation[j].level <= level)
-					break;
+			for (j = i + 1; j < *np && equation[j].level > level; j += 2) {
 				if (equation[j].level == level + 1) {
 					op = equation[j].token.operatr;
 				}
@@ -375,7 +394,7 @@
 				if (j >= *np || equation[j].level <= level)
 					break;
 			}
-			blt(&equation[j+2], &equation[j], (*np - j) * sizeof(*equation));
+			blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type));
 			*np += 2;
 			equation[j].level = level + 1;
 			equation[j].kind = OPERATOR;
@@ -390,7 +409,7 @@
 	for (i = loc; i < *np && equation[i].level >= level; i++) {
 		equation[i].level++;
 	}
-	blt(&equation[i+2], &equation[i], (*np - i) * sizeof(*equation));
+	blt(&equation[i+2], &equation[i], (*np - i) * sizeof(token_type));
 	*np += 2;
 	equation[i].level = level;
 	equation[i].kind = OPERATOR;

Added: branches/vendor/mathomatic/factorial/README.txt

Added: branches/vendor/mathomatic/factorial/fact.c

Added: branches/vendor/mathomatic/factorial/fact.java

Added: branches/vendor/mathomatic/factorial/fact.py

Added: branches/vendor/mathomatic/factorial/factorial

Added: branches/vendor/mathomatic/factorial/intfact.c

Modified: branches/vendor/mathomatic/gcd.c
===================================================================
--- branches/vendor/mathomatic/gcd.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/gcd.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,14 +1,16 @@
 /*
- * General floating point GCD routines.
+ * General floating point GCD routine and associated code for Mathomatic.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
 
 /*
- * Return the Greatest Common Divisor of doubles "d1" and "d2",
+ * Return the Greatest Common Divisor (GCD) of doubles "d1" and "d2",
  * by using the Euclidean GCD algorithm.
+ *
+ * The GCD is defined as the largest positive number that evenly divides both "d1" and "d2".
  * Will work with non-integers, but there may be some floating point error.
  * Always works correctly with integers.
  *
@@ -24,6 +26,9 @@
 	double	r1;
 	double	d;
 
+	if (!isfinite(d1) || !isfinite(d2)) {
+		return 0.0;	/* operands must be finite */
+	}
 	d1 = fabs(d1);
 	d2 = fabs(d2);
 	if (d1 > d2) {
@@ -33,12 +38,13 @@
 		larger = d2;
 		divisor = d1;
 	}
-	if (larger >= MAX_K_INTEGER) {
-		return 0.0;
+	if (divisor <= 0.0 || larger >= MAX_K_INTEGER) {
+		return 0.0;	/* out of range */
 	}
 	d = larger * epsilon;
-	if (d >= divisor)
-		return 0.0;
+	if (d >= divisor) {
+		return 0.0;	/* result would be too inaccurate */
+	}
 	for (count = 1; count < 50; count++) {
 		r1 = fmod(larger, divisor);
 		if (r1 <= d || (divisor - r1) <= d) {
@@ -53,7 +59,7 @@
 }
 
 /*
- * Round a double to the nearest integer.
+ * Return a floating point double rounded to the nearest integer.
  */
 double
 my_round(d1)
@@ -71,57 +77,72 @@
  * Convert the passed double "d" to a fully reduced fraction.
  * This done by the following simple algorithm:
  *
- * divisor = GCD(d, 1.0)
+ * divisor = gcd(d, 1.0)
  * numerator = d / divisor
  * denominator = 1.0 / divisor
  *
- * Return true with integer numerator and denominator
- * if conversion was successful.
+ * Return true with integer numerator and denominator if conversion was successful.
  * Otherwise return false with numerator = "d" and denominator = "1.0".
  *
- * True return indicates "d" is rational, otherwise "d" is irrational.
+ * True return indicates "d" is rational and finite, otherwise "d" is irrational.
  */
 int
-f_to_fraction(d, d1p, d2p)
-double	d;	/* floating point number to convert */
-double	*d1p;	/* returned numerator */
-double	*d2p;	/* returned denominator */
+f_to_fraction(d, numeratorp, denominatorp)
+double	d;		/* floating point number to convert */
+double	*numeratorp;	/* returned numerator */
+double	*denominatorp;	/* returned denominator */
 {
 	double	divisor;
-	double	d1, d2;
+	double	numerator, denominator;
 	double	k3, k4;
 
-	*d1p = d;
-	*d2p = 1.0;
-	if (fmod(d, 1.0) == 0.0)
+	*numeratorp = d;
+	*denominatorp = 1.0;
+	if (!isfinite(d)) {
+		return false;
+	}
+/* see if "d" is an integer, or very close to an integer: */
+	if (fmod(d, 1.0) == 0.0) {
 		return true;
+	}
+#if	true	/* set true for more integer oriented math */
+	k3 = fabs(d) * epsilon;
+#else
+	k3 = fabs(d) * small_epsilon;
+#endif
+	k4 = my_round(d);
+	if (k4 != 0.0 && fabs(k4 - d) <= k3) {
+		*numeratorp = k4;
+		return true;
+	}
+/* try to convert non-integer, floating point value in "d" to a fraction: */
 	if ((divisor = gcd(1.0, d)) > epsilon) {
-		d1 = d / divisor;
-		d2 = 1.0 / divisor;
-		d1 = my_round(d1);
-		d2 = my_round(d2);
-		if (fabs(d1) >= 1.0e12)
+		numerator = my_round(d / divisor);
+		denominator = my_round(1.0 / divisor);
+/* don't allow more than 11 digits in the numerator or denominator: */
+		if (fabs(numerator) >= 1.0e12)
 			return false;
-		if (d2 >= 1.0e12)
+		if (denominator >= 1.0e12 || denominator < 2.0)
 			return false;
-		if (d2 < 1.5)
-			return false;
-		divisor = gcd(d1, d2);	/* make sure the result is a fully reduced fraction */
-		if (fmod(divisor, 1.0) != 0.0) {
-			error("Error in gcd() function!");
-			return false;
-		}
+/* make sure the result is a fully reduced fraction: */
+		divisor = gcd(numerator, denominator);
 		if (divisor > 1.0) {	/* shouldn't happen, but just in case */
-			d1 = d1 / divisor;
-			d2 = d2 / divisor;
+			numerator /= divisor;
+			denominator /= divisor;
 		}
-		k3 = (d1 / d2);
+		k3 = (numerator / denominator);
 		k4 = d;
 		if (fabs(k3 - k4) > (small_epsilon * fabs(k3))) {
 			return false;	/* result is too inaccurate */
 		}
-		*d1p = d1;
-		*d2p = d2;
+		if (fmod(numerator, 1.0)) {
+			error("Internal error: Numerator not integral.");
+		}
+		if (fmod(denominator, 1.0)) {
+			error("Internal error: Denominator not integral.");
+		}
+		*numeratorp = numerator;
+		*denominatorp = denominator;
 		return true;
 	}
 	return false;
@@ -129,31 +150,30 @@
 
 /*
  * Convert non-integer constants in an equation side to fractions, when appropriate.
- *
- * Return true if equation side was changed.
  */
-int
 make_fractions(equation, np)
 token_type	*equation;	/* equation side pointer */
 int		*np;		/* pointer to length of equation side */
 {
 	int	i, j, k;
 	int	level;
-	double	d1, d2;
+	double	numerator, denominator;
 	int	inc_level;
-	int	modified = false;
 
 	for (i = 0; i < *np; i += 2) {
 		if (equation[i].kind == CONSTANT) {
 			level = equation[i].level;
 			if (i > 0 && equation[i-1].level == level && equation[i-1].token.operatr == DIVIDE)
 				continue;
-			if (!f_to_fraction(equation[i].token.constant, &d1, &d2) || d2 == 1.0)
+			if (!f_to_fraction(equation[i].token.constant, &numerator, &denominator))
 				continue;
+			if (denominator == 1.0) {
+				equation[i].token.constant = numerator;
+				continue;
+			}
 			if ((*np + 2) > n_tokens) {
 				error_huge();
 			}
-			modified = true;
 			inc_level = (*np > 1);
 			if ((i + 1) < *np && equation[i+1].level == level) {
 				switch (equation[i+1].token.operatr) {
@@ -163,12 +183,12 @@
 							break;
 						}
 					}
-					if (d1 == 1.0) {
-						blt(&equation[i], &equation[i+2], (j - (i + 2)) * sizeof(*equation));
+					if (numerator == 1.0) {
+						blt(&equation[i], &equation[i+2], (j - (i + 2)) * sizeof(token_type));
 						j -= 2;
 					} else {
-						equation[i].token.constant = d1;
-						blt(&equation[j+2], &equation[j], (*np - j) * sizeof(*equation));
+						equation[i].token.constant = numerator;
+						blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type));
 						*np += 2;
 					}
 					equation[j].level = level;
@@ -177,8 +197,8 @@
 					j++;
 					equation[j].level = level;
 					equation[j].kind = CONSTANT;
-					equation[j].token.constant = d2;
-					if (d1 == 1.0) {
+					equation[j].token.constant = denominator;
+					if (numerator == 1.0) {
 						i -= 2;
 					}
 					continue;
@@ -188,9 +208,9 @@
 				}
 			}
 			j = i;
-			blt(&equation[i+3], &equation[i+1], (*np - (i + 1)) * sizeof(*equation));
+			blt(&equation[i+3], &equation[i+1], (*np - (i + 1)) * sizeof(token_type));
 			*np += 2;
-			equation[j].token.constant = d1;
+			equation[j].token.constant = numerator;
 			j++;
 			equation[j].level = level;
 			equation[j].kind = OPERATOR;
@@ -198,12 +218,11 @@
 			j++;
 			equation[j].level = level;
 			equation[j].kind = CONSTANT;
-			equation[j].token.constant = d2;
+			equation[j].token.constant = denominator;
 			if (inc_level) {
 				for (k = i; k <= j; k++)
 					equation[k].level++;
 			}
 		}
 	}
-	return modified;
 }

Modified: branches/vendor/mathomatic/globals.c
===================================================================
--- branches/vendor/mathomatic/globals.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/globals.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,9 +1,9 @@
 /*
- * Algebraic manipulator globals.
+ * Mathomatic global variables and arrays.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  *
- * All global variables for Mathomatic are defined here and duplicated in "externs.h".
+ * Most global variables for Mathomatic are defined here and duplicated in "externs.h".
  */
 
 #include "includes.h"
@@ -20,9 +20,11 @@
 
 token_type	*tlhs;				/* LHS during solve and temporary storage for expressions */
 token_type	*trhs;				/* RHS during solve and temporary storage for expressions */
+token_type	*tes;				/* temporary equation side, used only in commands */
 
 int		n_tlhs;				/* number of tokens in tlhs */
 int		n_trhs;				/* number of tokens in trhs */
+int		n_tes;				/* number of tokens in tes */
 
 token_type	*scratch;			/* very temporary storage for expressions */
 
@@ -30,28 +32,30 @@
 token_type	one_token;			/* the constant 1.0 as a token */
 
 /* set options */
-int		case_sensitive_flag = true;	/* "set case_sensitive" flag */
-int		factor_int_flag;		/* factor integers when displaying expressions */
-int		groupall = true;		/* "set display2d" flag */
-int		preserve_roots = true;		/* true if we are to preserve 2^.5, etc. */
-int		in_calc_cmd;			/* true if in calculate command (force approximations) */
-int		true_modulus;			/* true for mathematically correct modulus */
-int		screen_columns = STANDARD_SCREEN_COLUMNS;	/* screen width */
-int		screen_rows = STANDARD_SCREEN_ROWS;		/* screen height */
-int		finance_option;			/* for displaying dollars and cents */
-int		starstar;			/* output "**" instead of "^" for the power operator */
+int		precision = 14;				/* the display precision for doubles (number of digits) */
+int		case_sensitive_flag = true;		/* "set case_sensitive" flag */
+int		factor_int_flag;			/* factor integers when displaying expressions */
+int		display2d = true;			/* "set display2d" flag */
+int		preserve_roots = true;			/* set option to preserve roots like (2^.5) */
+int		true_modulus;				/* true for mathematically correct modulus */
+int		screen_columns = STANDARD_SCREEN_COLUMNS;	/* screen width of the terminal; 0 = infinite */
+int		screen_rows = STANDARD_SCREEN_ROWS;		/* screen height of the terminal; 0 = infinite */
+int		finance_option;				/* for displaying dollars and cents */
+int		autosolve = true;			/* Allows solving by typing the variable name at the prompt */
+int		autocalc = true;			/* Allows automatically calculating a numerical expression */
+char		special_variable_character = '\\';	/* user defined special character for variable names */
 #if	!SILENT
-int		debug_level;			/* current debug level */
+int		debug_level;				/* current debug level */
 #endif
 
 /* variables having to do with color mode */
 int		color_flag = true;		/* true for color mode */
 int		bold_colors;			/* true for bold colors */
-int		cur_color = -1;			/* current color */
+int		cur_color = -1;			/* current color on the terminal */
 
 /* epsilon constants */
 double		small_epsilon	= 0.000000000000005;	/* for small round-off errors */
-double		epsilon		= 0.00000000000005;	/* for larger accumulated round-off errors */
+double		epsilon		= 0.00000000000005;	/* for larger, accumulated round-off errors */
 
 /* string variables */
 char		*var_names[MAX_VAR_NAMES];	/* storage for long variable names */
@@ -63,7 +67,7 @@
 char		*prog_name = "mathomatic";	/* name of this program */
 
 /* The following are for integer factoring (filled by factor_one()): */
-double		unique[64];		/* storage for the unique factors */
+double		unique[64];		/* storage for the unique prime factors */
 int		ucnt[64];		/* number of times the factor occurs */
 int		uno;			/* number of unique factors stored in unique[] */
 
@@ -74,13 +78,17 @@
 int		test_mode;		/* test mode flag (-t) */
 int		quiet_mode;		/* quiet mode (don't display prompts) */
 int		html_flag;		/* true for HTML mode */
+int		readline_enabled = true;
 int		partial_flag;		/* true for partial unfactoring of algebraic fractions */
 int		symb_flag;		/* true for "simplify symbolic" */
 int		high_prec;		/* flag to output constants in higher precision (used when saving equations) */
 int		input_column;		/* current column number on the screen at the beginning of a parse */
 int		sign_flag;		/* true when all "sign" variables are to compare equal */
 int		domain_check;		/* flag to track domain errors in the pow() function */
+int		approximate_roots;	/* true if in calculate command (force approximations of roots like (2^.5)) */
 
 /* library variables go here */
+#if	SILENT
 char		*error_str;		/* last error when SILENT is defined */
 char		*result_str;		/* returned result when using as library */
+#endif

Added: branches/vendor/mathomatic/hard_stuff/factor_test

Added: branches/vendor/mathomatic/hard_stuff/john.in

Added: branches/vendor/mathomatic/hard_stuff/tasks.txt

Added: branches/vendor/mathomatic/hard_stuff/test.in

Modified: branches/vendor/mathomatic/help.c
===================================================================
--- branches/vendor/mathomatic/help.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/help.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -3,7 +3,7 @@
  *
  * Everything that depends on the command table goes here.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -12,79 +12,82 @@
  * The following structure is used for each Mathomatic command.
  */
 typedef	struct {
-	char	*name;		/* command name to be typed by user */
-	int	(*func)();	/* function that handles this command */
-				/* function is passed a char pointer and returns true if successful */
-	char	*usage;		/* command syntax text */
-	char	*info;		/* one line description of command */
+	char	*name;			/* command name to be typed by user */
+	char	*secondary_name;	/* another name for this command */
+	int	(*func)();		/* function that handles this command */
+					/* function is passed a char pointer and returns true if successful */
+	char	*usage;			/* command syntax text */
+	char	*info;			/* one line description of command */
 } com_type;
 
 /*
  * The Mathomatic command table follows.  It should be in alphabetical order.
  */
 static com_type com_list[] = {
+/*	command name,	alternate name,		function,	usage,							information */
 #if	!LIBRARY
-{	"calculate",	calculate_cmd,	"[variable number-of-iterations]",			"Temporarily plug in values for variables and approximate." },
+{	"calculate",	NULL,			calculate_cmd,	"[variable number-of-iterations]",			"Temporarily plug in values for variables and approximate." },
 #endif
-{	"clear",	clear_cmd,	"[equation-numbers-or-ranges]",				"Delete expressions or equations so equation spaces can be reused." },
-#if	!BASICS && !LIBRARY
-{	"code",		code_cmd,	"[\"c\" or \"java\" or \"python\" or \"integer\"] [equation-number-range]",	"Output C, Java, or Python code for the specified equations." },
+{	"clear",	NULL,			clear_cmd,	"[equation-numbers-or-ranges]",				"Delete expressions or equations so equation spaces can be reused." },
+#if	!LIBRARY
+{	"code",		NULL,			code_cmd,	"[\"c\" or \"java\" or \"python\" or \"integer\"] [equation-number-range]",	"Output C, Java, or Python code for the specified equations." },
 #endif
-{	"compare",	compare_cmd,	"equation-number [\"with\" equation-number]",		"Compare two expressions or equations to see if they are the same." },
-{	"copy",		copy_cmd,	"[equation-number-range]",				"Duplicate the specified expressions or equations." },
-{	"derivative",	derivative_cmd,	"[variable or \"all\"] [order]",			"Symbolically differentiate and simplify, order times." },
+{	"compare",	NULL,			compare_cmd,	"equation-number [\"with\" equation-number]",		"Compare two equation spaces to see if they are the same." },
+{	"copy",		NULL,			copy_cmd,	"[equation-number-range]",				"Duplicate the specified equation spaces." },
+{	"derivative",	"differentiate",	derivative_cmd,	"[variable or \"all\"] [order]",			"Symbolically differentiate and simplify, order times." },
+{	"display",	"flist",		display_cmd,	"[\"factor\"] [equation-number-range]",			"Display stored expressions in multi-line fraction format." },
 #if	!LIBRARY
-{	"divide",	divide_cmd,	"[variable]",						"Prompt for 2 polynomials/numbers and divide.  Display result and GCD." },
-#if	(UNIX || CYGWIN) && !SECURE
-{	"edit",		edit_cmd,	"[file-name]",						"Edit all stored expressions and equations or an input file." },
+{	"divide",	NULL,			divide_cmd,	"[variable]",						"Prompt for 2 polynomials/numbers and divide.  Display result and GCD." },
 #endif
+{	"echo",		NULL,			echo_cmd,	"[text]",						"Output a line of text, followed by a newline." },
+#if	!LIBRARY && (UNIX || CYGWIN) && !SECURE
+{	"edit",		NULL,			edit_cmd,	"[file-name]",						"Edit all equation spaces or an input file." },
 #endif
-{	"eliminate",	eliminate_cmd,	"variables or \"all\" [\"using\" equation-number]",	"Substitute the specified variables with solved equations." },
-{	"extrema",	extrema_cmd,	"[variable]",						"Find the minimums and maximums of the current expression." },
-{	"factor",	factor_cmd,	"[\"number\" [integers]] or [equation-number-range] [variables]",	"Trivially factor integers or stored expressions." },
-{	"flist",	flist_cmd,	"[\"factor\"] [equation-number-range]",			"Display stored expressions in multi-line fraction format." },
-{	"help",		help_cmd,	"[topic or command-name]",				"Short, built-in help." },
-{	"imaginary",	imaginary_cmd,	"[variable]",						"Copy the imaginary part of an expression (see the \"real\" command)." },
-{	"integrate",	integrate_cmd,	"[\"definite\"] variable [order]",			"Symbolically integrate polynomials, order times." },
-{	"laplace",	laplace_cmd,	"[\"inverse\"] variable",				"Compute the Laplace or inverse Laplace transform of polynomials." },
-{	"limit",	limit_cmd,	"variable expression",					"Take the limit of the current expression as variable goes to expression." },
-{	"list",		list_cmd,	"[\"export\" or \"maxima\"] [equation-number-range]",	"Display stored expressions in single line format." },
-#if	!BASICS && !LIBRARY
-{	"nintegrate",	nintegrate_cmd,	"[\"trapezoidal\"] variable [partitions]",		"Approximate the definite integral using Simpson's rule."},
-{	"optimize",	optimize_cmd,	"[equation-number-range]",				"Split up an equation into smaller multiple equations." },
+{	"eliminate",	NULL,			eliminate_cmd,	"variables or \"all\" [\"using\" equation-number]",	"Substitute the specified variables with solved equations." },
+{	"extrema",	"stationary",		extrema_cmd,	"[variable] [order]",					"Find possible local minimums and maximums of the current expression." },
+{	"factor",	NULL,			factor_cmd,	"[\"number\" [integers]] or [equation-number-range] [variables]",	"Trivially factor integers or stored expressions." },
+{	"fraction",	NULL,			fraction_cmd,	"[equation-number-range]",				"Convert expressions with any algebraic fractions into a single fraction." },
+{	"help",		NULL,			help_cmd,	"[topic or command-name]",				"Short, built-in help." },
+{	"imaginary",	NULL,			imaginary_cmd,	"[variable]",						"Copy the imaginary part of an expression (see the \"real\" command)." },
+{	"integrate",	"integral",		integrate_cmd,	"[\"definite\"] variable [order]",			"Symbolically integrate polynomials, order times." },
+{	"laplace",	NULL,			laplace_cmd,	"[\"inverse\"] variable",				"Compute the Laplace or inverse Laplace transform of polynomials." },
+{	"limit",	NULL,			limit_cmd,	"variable expression",					"Take the limit of the current expression as variable goes to expression." },
+{	"list",		NULL,			list_cmd,	"[\"export\" or \"maxima\"] [equation-number-range]",	"Display stored expressions in single line format." },
+#if	!LIBRARY
+{	"nintegrate",	NULL,			nintegrate_cmd,	"[\"trapezoid\"] variable [partitions]",		"Approximate the definite integral using Simpson's rule."},
+{	"optimize",	NULL,			optimize_cmd,	"[equation-number-range]",				"Split up an equation into smaller multiple equations." },
 #endif
 #if	!LIBRARY
-{	"pause",	pause_cmd,	"[text]",						"Wait for user to press the Enter key.  Optionally display a message." },
+{	"pause",	NULL,			pause_cmd,	"[text]",						"Wait for user to press the Enter key.  Optionally display a message." },
 #endif
-{	"product",	product_cmd,	"variable start end [step]",				"Compute the product as variable goes from start to end." },
+{	"product",	NULL,			product_cmd,	"variable start end [step]",				"Compute the product as variable goes from start to end." },
 #if	READLINE
-{	"push",		push_cmd,	"[equation-number-range]",				"Push stored expressions into the readline history." },
+{	"push",		NULL,			push_cmd,	"[equation-number-range]",				"Push stored expressions into the readline history." },
 #endif
 #if	!LIBRARY
-{	"quit",		quit_cmd,	"",							"Terminate this program." },
+{	"quit",		"exit",			quit_cmd,	"",							"Terminate this program without saving." },
 #endif
-#if	!SECURE && !LIBRARY
-{	"read",		read_cmd,	"file-name",						"Read in a text file as if it was typed in." },
+#if	!SECURE
+{	"read",		NULL,			read_cmd,	"file-name",						"Read in a text file as if it was typed in." },
 #endif
-{	"real",		real_cmd,	"[variable]",						"Copy the real part of an expression (see the \"imaginary\" command)." },
-{	"replace",	replace_cmd,	"[\"constants\"] [variables [\"with\" expression]]",	"Substitute variables in the current equation with expressions." },
+{	"real",		NULL,			real_cmd,	"[variable]",						"Copy the real part of an expression (see the \"imaginary\" command)." },
+{	"replace",	NULL,			replace_cmd,	"[\"constants\"] or [variables [\"with\" expression]]",	"Substitute variables in the current equation with expressions." },
 #if	!LIBRARY
-{	"roots",	roots_cmd,	"root real-part imaginary-part",			"Display all the roots of a complex number." },
+{	"roots",	NULL,			roots_cmd,	"root real-part imaginary-part",			"Display all the roots of a complex number." },
 #endif
 #if	!SECURE
-{	"save",		save_cmd,	"file-name",						"Save all stored expressions and equations in a text file." },
+{	"save",		NULL,			save_cmd,	"file-name",						"Save all stored expressions and equations in a text file." },
 #endif
-{	"set",		set_cmd,	"[[\"no\"] options]",					"Set or display various session options." },
-{	"simplify",	simplify_cmd,	"[\"symbolic\"] [\"quick\"] [equation-number-range]",	"Completely simplify stored expressions." },
-{	"sum",		sum_cmd,	"variable start end [step]",				"Compute the summation as variable goes from start to end." },
+{	"set",		NULL,			set_cmd,	"[[\"no\"] option]",					"Set or display various session options." },
+{	"simplify",	NULL,			simplify_cmd,	"[\"symbolic\"] [\"quick\"] [equation-number-range]",	"Completely simplify stored expressions." },
+{	"solve",	NULL,			solve_cmd,	"variable or \"0\"",					"Solve the current equation for a variable or for 0." },
+{	"sum",		NULL,			sum_cmd,	"variable start end [step]",				"Compute the summation as variable goes from start to end." },
 #if	!LIBRARY
-{	"tally",	tally_cmd,	"",							"Prompt for and add numerical entries.  Show running total and average." },
+{	"tally",	NULL,			tally_cmd,	"",							"Prompt for and add numerical entries, show running total and average." },
 #endif
-{	"taylor",	taylor_cmd,	"[variable] [order] [point]",				"Compute the Taylor series expansion of the current expression." },
-{	"unfactor",	unfactor_cmd,	"[\"fully\"] [equation-number-range]",			"Algebraically expand (multiply out) stored expressions." },
-#if	!LIBRARY
-{	"version",	version_cmd,	"",							"Display version number and compile flags used." }
-#endif
+{	"taylor",	NULL,			taylor_cmd,	"[variable] [order] [point]",				"Compute the Taylor series expansion of the current expression." },
+{	"unfactor",	"expand",		unfactor_cmd,	"[\"fully\"] [equation-number-range]",			"Algebraically expand (multiply out) stored expressions." },
+{	"version",	NULL,			version_cmd,	"",							"Display version number, compile flags used, and maximum memory usage." }
 };
 
 /*
@@ -103,11 +106,13 @@
 	if ((cp = parse_equation(n, cp)) != NULL) {
 		if (n_lhs[n] == 0 && n_rhs[n] == 0)
 			return true;
-		if (n_lhs[n]) {
-			cur_equation = n;
-			return_result(cur_equation);
-			return true;
+		if (n_lhs[n] == 0) {
+			/* RHS expression only, set equal to zero */
+			n_lhs[n] = 1;
+			lhs[n][0] = zero_token;
 		}
+		cur_equation = n;
+		return return_result(cur_equation);
 	}
 	n_lhs[n] = 0;
 	n_rhs[n] = 0;
@@ -127,23 +132,32 @@
 int	n;
 char	*cp;
 {
+#if	!LIBRARY
 	int	i;
+#endif
 
 	if ((cp = parse_equation(n, cp)) != NULL) {
 		if (n_lhs[n] == 0 && n_rhs[n] == 0)
 			return true;
 		if (n_lhs[n] == 0 || n_rhs[n] == 0) {
-			if ((n_lhs[n] == 1 && ((lhs[n][0].kind == CONSTANT && lhs[n][0].token.constant == 0.0)
-			    || (lhs[n][0].kind == VARIABLE && (lhs[n][0].token.variable & VAR_MASK) > SIGN)))
-			    || n_rhs[n]) {
-				if (solve(n, cur_equation)) {
-					return_result(cur_equation);
-					return true;
+			if (autosolve) {
+				if ((n_lhs[n] == 1 && ((lhs[n][0].kind == CONSTANT && lhs[n][0].token.constant == 0.0)
+				    || (lhs[n][0].kind == VARIABLE && (lhs[n][0].token.variable & VAR_MASK) > SIGN)))
+				    || (n_rhs[n] == 1 && ((rhs[n][0].kind == CONSTANT && rhs[n][0].token.constant == 0.0)
+				    || (rhs[n][0].kind == VARIABLE && (rhs[n][0].token.variable & VAR_MASK) > SIGN)))) {
+					if (solve(n, cur_equation)) {
+						return return_result(cur_equation);
+					}
+					return false;
 				}
-				return false;
 			}
-			if (n_lhs[n] == 1 && lhs[n][0].kind == CONSTANT
-			    && fmod(lhs[n][0].token.constant, 1.0) == 0.0
+			if (n_rhs[n]) {
+				/* RHS expression only, set equal to zero */
+				n_lhs[n] = 1;
+				lhs[n][0] = zero_token;
+				goto return_ok;
+			}
+			if (n_lhs[n] == 1 && lhs[n][0].kind == CONSTANT && fmod(lhs[n][0].token.constant, 1.0) == 0.0
 			    && lhs[n][0].token.constant > 0.0 && lhs[n][0].token.constant <= n_equations) {
 				/* easy selecting of equation spaces */
 				n_lhs[n] = 0;
@@ -151,32 +165,35 @@
 				goto return_ok;
 			}
 #if	!LIBRARY
-			/* the numerical input calculation */
-			for (i = 0; i < n_lhs[n]; i += 2) {
-				if (lhs[n][i].kind == VARIABLE && (lhs[n][i].token.variable & VAR_MASK) > SIGN) {
-					goto return_ok;		/* not numerical (contains a variable) */
+			if (autocalc) {
+				/* the numerical input calculation */
+				for (i = 0; i < n_lhs[n]; i += 2) {
+					if (lhs[n][i].kind == VARIABLE && (lhs[n][i].token.variable & VAR_MASK) > SIGN) {
+						goto return_ok;		/* not numerical (contains a variable) */
+					}
 				}
+				/* make the expression an equation */
+				blt(rhs[n], lhs[n], n_lhs[n] * sizeof(token_type));
+				n_rhs[n] = n_lhs[n];
+				lhs[n][0].level = 1;
+				lhs[n][0].kind = VARIABLE;
+				parse_var(&lhs[n][0].token.variable, "answer");
+				n_lhs[n] = 1;
+				i = cur_equation;
+				/* make the current equation and run the calculate command on it */
+				cur_equation = n;
+				calculate_cmd("");
+				cur_equation = i;
+				/* delete from memory */
+				n_lhs[n] = 0;
+				n_rhs[n] = 0;
+				return true;
 			}
-			/* make the expression an equation */
-			blt(rhs[n], lhs[n], n_lhs[n] * sizeof(token_type));
-			n_rhs[n] = n_lhs[n];
-			lhs[n][0].level = 1;
-			lhs[n][0].kind = VARIABLE;
-			lhs[n][0].token.variable = V_ANSWER;
-			n_lhs[n] = 1;
-			i = cur_equation;
-			cur_equation = n;
-			calculate_cmd("");
-			cur_equation = i;
-			n_lhs[n] = 0;
-			n_rhs[n] = 0;
-			return true;
 #endif
 		}
 return_ok:
 		cur_equation = n;
-		return_result(cur_equation);
-		return true;
+		return return_result(cur_equation);
 	}
 	n_lhs[n] = 0;
 	n_rhs[n] = 0;
@@ -213,15 +230,10 @@
 		cp++;
 		switch (*cp) {
 		case '+':
-			cp++;
+		case '-':
 			i = decstrtol(cp, &cp1);
 			i = cur_equation + i;
 			break;
-		case '-':
-			cp++;
-			i = decstrtol(cp, &cp1);
-			i = cur_equation - i;
-			break;
 		default:
 			i = decstrtol(cp, &cp1) - 1;
 			break;
@@ -242,7 +254,7 @@
 			return parse(i, cp);
 		}
 		cur_equation = i;
-		return_result(cur_equation);
+		return return_result(cur_equation);
 	}
 #if	!SECURE
 	/* handle shell escape */
@@ -255,23 +267,24 @@
 		if (cp1) {
 			return(!shell_out(cp1));
 		}
+		error(_("SHELL environment variable not set."));
 		return false;
 	}
 #endif
+	/* a quick way to get help */
+	if (*cp == '?') {
+		cp = skip_space(cp + 1);
+		input_column += (cp - cp_start);
+		return(help_cmd(cp));
+	}
 /* See if the string pointed to by "cp" is a command. */
 /* If so, execute it. */
 	cp1 = cp;
-	while (*cp1 && isascii(*cp1) && isalpha(*cp1))
+	while (*cp1 && !isspace(*cp1))
 		cp1++;
 	for (i = 0; i < ARR_CNT(com_list); i++) {
-		if (strlen(com_list[i].name) < 4) {
-			if ((cp1 - cp) != strlen(com_list[i].name))
-				continue;
-		} else {
-			if ((cp1 - cp) < 4)
-				continue;
-		}
-		if (strncasecmp(cp, com_list[i].name, cp1 - cp) == 0) {
+		if (((cp1 - cp) >= min(4, strlen(com_list[i].name)) && strncasecmp(cp, com_list[i].name, cp1 - cp) == 0)
+		    || (com_list[i].secondary_name && (cp1 - cp) >= min(4, strlen(com_list[i].secondary_name)) && strncasecmp(cp, com_list[i].secondary_name, cp1 - cp) == 0)) {
 			cp1 = skip_space(cp1);
 			input_column += (cp1 - cp_start);
 			if (my_strlcpy(buf2, cp1, sizeof(buf2)) >= sizeof(buf2)) {
@@ -311,7 +324,7 @@
 #endif
 			/* remove trailing spaces from the command line */
 		        i1 = strlen(buf2) - 1;
-		        while (i1 >= 0 && isascii(buf2[i1]) && isspace(buf2[i1])) {
+		        while (i1 >= 0 && isspace(buf2[i1])) {
         		        buf2[i1] = '\0';
                 		i1--;
 			}
@@ -355,19 +368,18 @@
 #endif
 
 /*
- * Parse a variable name, with error messages and space character skipping.
+ * Parse a variable name with before and after space character skipping.
  *
  * Return new position in string or NULL if error.
  */
 char	*
 parse_var2(vp, cp)
-long	*vp;	/* pointer to result */
+long	*vp;	/* pointer to returned variable in Mathomatic internal format */
 char	*cp;	/* pointer to variable name string */
 {
 	cp = skip_space(cp);
 	cp = parse_var(vp, cp);
 	if (cp == NULL) {
-		error(_("Invalid variable."));
 		return NULL;
 	}
 	return skip_space(cp);
@@ -376,8 +388,30 @@
 #define P(A)	fprintf(gfp, "%s\n", A)
 
 /*
+ * Output command info and usage.
+ *
+ * Return the number of lines output.
+ */
+int
+display_command(i)
+int	i;	/* command index */
+{
+	int	rows = 3;
+
+	fprintf(gfp, "%s - %s\n", com_list[i].name, com_list[i].info);
+	fprintf(gfp, "Usage: %s %s\n", com_list[i].name, com_list[i].usage);
+	if (com_list[i].secondary_name) {
+		fprintf(gfp, "Alternate name for this command: %s\n", com_list[i].secondary_name);
+		rows++;
+	}
+	fprintf(gfp, "\n");
+	return rows;
+}
+
+/*
  * The help command.
  */
+int
 help_cmd(cp)
 char	*cp;
 {
@@ -387,25 +421,31 @@
 	int	row;
 
 	cp1 = cp;
-	while (*cp1 && !(isascii(*cp1) && isspace(*cp1)))
+	while (*cp1 && !isspace(*cp1))
 		cp1++;
 	if (cp1 != cp) {
 		/* first, see if the argument matches any command names */
 		flag = false;
 		for (i = 0; i < ARR_CNT(com_list); i++) {
-			if (strncasecmp(cp, com_list[i].name, cp1 - cp) == 0) {
-				if (com_list[i].info) {
-					fprintf(gfp, "%s - %s\n", com_list[i].name, com_list[i].info);
-				}
-				fprintf(gfp, "Usage: %s %s\n\n", com_list[i].name, com_list[i].usage);
+			if (strncasecmp(cp, com_list[i].name, cp1 - cp) == 0
+			    || (com_list[i].secondary_name && strncasecmp(cp, com_list[i].secondary_name, cp1 - cp) == 0)) {
+				display_command(i);
 				flag = true;
 			}
 		}
 		if (flag)
 			return true;
 		if (strncasecmp(cp, "usage", cp1 - cp) == 0) {
-			for (i = 0; i < ARR_CNT(com_list); i++) {
+			P("Command Usage Syntax");
+			P("--------------------");
+			for (i = 0, row = 3; i < ARR_CNT(com_list); i++) {
 				fprintf(gfp, "%s %s\n", com_list[i].name, com_list[i].usage);
+				row++;
+				if (gfp == stdout && screen_rows && row >= (screen_rows - 1)) {
+					row = 1;
+					if (!pause_cmd(""))
+						return false;
+				}
 			}
 			return true;
 		}
@@ -416,10 +456,11 @@
 			P("    Area = b*h/2");
 			P("Rectangle of length \"l\" and width \"w\":");
 			P("    Area = l*w                    Perimeter = 2*l + 2*w");
-			P("Trapezoid of height \"h\" and parallel sides \"a\" and \"b\":");
-			P("    Area = h*(a+b)/2");
+			P("Trapezoid of parallel sides \"a\" and \"b\", and \"d\" distance between them:");
+			P("    Area = d*(a + b)/2");
 			P("Circle of radius \"r\":");
 			P("    Area = pi*r^2                 Perimeter = 2*pi*r");
+			P("    Area = Perimeter*r/2");
 			P("Rectangular solid of length \"l\", width \"w\", and height \"h\":");
 			P("    Volume = l*w*h                Surface area = 2*l*w + 2*l*h + 2*w*h");
 			P("Sphere of radius \"r\":");
@@ -429,11 +470,11 @@
 			P("Right circular cone of radius \"r\" and height \"h\":");
 			P("    Volume = pi*r^2*h/3");
 			P("    Base surface area = pi*r^2    Side surface area = pi*r*(r^2 + h^2)^.5\n");
-			P("Convex polygon of \"n\" sides sum of all interior angles formula:");
-			P("    Sum = (n-2)*180 degrees");
+			P("Convex polygon of \"n\" sides, sum of all interior angles formula:");
+			P("    Sum = (n - 2)*180 degrees     Sum = (n - 2)*pi radians");
 			return true;
 		}
-		if (strncasecmp(cp, "expressions", cp1 - cp) == 0) {
+		if (strncasecmp(cp, "expressions", cp1 - cp) == 0 || strncasecmp(cp, "equations", cp1 - cp) == 0) {
 			P("To enter an expression or equation, simply type it in at the prompt.");
 			P("Operators have precedence decreasing as indicated:\n");
 			P("    - negate");
@@ -442,31 +483,28 @@
 			P("    * multiply        / divide          % modulus");
 			P("    + add             - subtract\n");
 			P("Operators in the same precedence level are evaluated left to right.\n");
-			P("Variables consist of any combination of letters, digits, underscores (_),");
-			P("and backslashes (\\).  Predefined constants and variables:\n");
-			P("    e# - the universal constant e (2.718281828...).");
-			P("    pi - the universal constant pi (3.1415926...).");
-			P("    i# - imaginary number (square root of -1).");
-			P("    sign, sign1, sign2, sign3, ... - may be +1 or -1.");
-			P("    integer - may be any integer.");
-			P("    inf - infinity constant.\n");
+			P("Variables consist of any combination of letters, digits, and underscores (_).");
+			P("Constants always start with a digit (0..9) or a period (.).");
+			P("Predefined constants and variables follow:");
+			P("    e or e# - the universal constant e (2.7182818284...).");
+			P("    pi or pi# - the universal constant pi (3.1415926535...).");
+			P("    i or i# - imaginary number (square root of -1).");
+			P("The above constants may also be used anywhere variables are required.");
+			P("    sign, sign1, sign2, sign3, ... - variable that can only be +1 or -1.");
+			P("    integer - variable that may be any integer.");
+			P("    inf - infinity constant (a true constant).\n");
 			P("Absolute value notation \"|x|\" and \"+/-\" are understood.");
 			return true;
 		}
 		if (is_all(cp)) {
-			for (i = 0, row = 1;; i++, row += 3) {
-				if (gfp == stdout && screen_rows && row >= (screen_rows - 3)) {
+			for (i = 0, row = 1; i < ARR_CNT(com_list); i++) {
+				row += display_command(i);
+				if (gfp == stdout && screen_rows && row >= (screen_rows - 5)) {
 					row = 1;
 					if (!pause_cmd(""))
 						return false;
 					printf("\n");
 				}
-				if (i >= ARR_CNT(com_list))
-					break;
-				if (com_list[i].info) {
-					fprintf(gfp, "%s - %s\n", com_list[i].name, com_list[i].info);
-				}
-				fprintf(gfp, "Usage: %s %s\n\n", com_list[i].name, com_list[i].usage);
 			}
 			P("End of command list.");
 			return true;
@@ -474,11 +512,11 @@
 	}
 	/* default help text: */
 	P("This help command is provided as a quick reference.");
-	P("Type \"help all\" for a summary of the all commands.");
+	P("Type \"help all\" for a summary and syntax of the all commands.");
 	P("Type \"help usage\" for syntax of all commands.");
 	P("Type \"help expressions\" for help with entering expressions.");
 	P("Type \"help geometry\" for some commonly used geometric formulas.");
-	P("\"help\" followed by a command name will give info on a command.\n");
+	P("\"help\" or \"?\" followed by a command name will give info on a command.\n");
 	P("Available commands:");
 	for (i = 0; i < ARR_CNT(com_list); i++) {
 		if ((i % 5) == 0)
@@ -487,7 +525,7 @@
 		for (; j > 0; j--)
 			fprintf(gfp, " ");
 	}
-	P("\n\nTo select an equation in memory, just enter the equation number.");
-	P("To solve an equation, simply type the variable name at the prompt.");
+	P("\n\nTo select an equation in memory, type the equation number at the main prompt.");
+	P("To solve the current equation, type the variable name at the main prompt.");
 	return true;
 }

Modified: branches/vendor/mathomatic/includes.h
===================================================================
--- branches/vendor/mathomatic/includes.h	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/includes.h	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,9 +1,10 @@
 /*
  * Standard include files for Mathomatic.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
+/* include files from /usr/include: */
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -24,7 +25,8 @@
 #include <readline/readline.h>
 #endif
 
-#include "am.h"
-#include "complex.h"
-#include "proto.h"
-#include "externs.h"
+/* include files from the current directory: */
+#include "am.h"		/* the main include file for Mathomatic, contains tunable parameters */
+#include "complex.h"	/* floating point complex number arithmetic function prototypes */
+#include "proto.h"	/* global function prototypes */
+#include "externs.h"	/* global variable extern definitions */

Modified: branches/vendor/mathomatic/integrate.c
===================================================================
--- branches/vendor/mathomatic/integrate.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/integrate.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,9 +1,9 @@
 /*
- * Algebraic manipulator integration routines and commands.
+ * Mathomatic integration routines and commands.
  *
  * These are very low level, so they don't do much, polynomials only.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -12,14 +12,12 @@
 static int	laplace_sub();
 static int	inv_laplace_sub();
 
-static double	integrate_order;	/* global order of integration */
-
 /*
  * Make variable "v" always raised to a power,
  * unless it is on the right side of a power operator.
  */
 make_powers(equation, np, v)
-token_type	*equation;	/* equation side pointer */
+token_type	*equation;	/* pointer to beginning of equation side */
 int		*np;		/* pointer to length of equation side */
 long		v;		/* variable */
 {
@@ -64,7 +62,7 @@
  */
 int
 int_dispatch(equation, np, v, func)
-token_type	*equation;	/* equation side to integrate */
+token_type	*equation;	/* pointer to beginning of equation side to integrate */
 int		*np;		/* pointer to length of equation side */
 long		v;		/* integration variable */
 int		(*func)();	/* integration function to call for each term */
@@ -102,11 +100,11 @@
  */
 static int
 integrate_sub(equation, np, loc, eloc, v)
-token_type	*equation;	/* equation side pointer */
+token_type	*equation;	/* pointer to beginning of equation side */
 int		*np;		/* pointer to length of equation side */
 int		loc;		/* beginning location of term */
 int		eloc;		/* end location of term */
-long		v;		/* variable */
+long		v;		/* variable of integration */
 {
 	int		i, j, k;
 	int		len;
@@ -197,15 +195,12 @@
 			equation[j].level = level;
 			equation[j].kind = CONSTANT;
 			equation[j].token.constant = 1.0;
-			j++;
 			blt(&equation[eloc+len+1], &equation[eloc], (*np - eloc) * sizeof(token_type));
 			*np += len + 1;
-			k = eloc;
-			equation[k].level = mlevel;
-			equation[k].kind = OPERATOR;
-			equation[k].token.operatr = DIVIDE;
-			k++;
-			blt(&equation[k], &equation[i], len * sizeof(token_type));
+			equation[eloc].level = mlevel;
+			equation[eloc].kind = OPERATOR;
+			equation[eloc].token.operatr = DIVIDE;
+			blt(&equation[eloc+1], &equation[i], len * sizeof(token_type));
 			return true;
 		}
 	}
@@ -214,14 +209,13 @@
 	}
 	blt(&equation[eloc+2], &equation[eloc], (*np - eloc) * sizeof(token_type));
 	*np += 2;
-	k = eloc;
-	equation[k].level = mlevel;
-	equation[k].kind = OPERATOR;
-	equation[k].token.operatr = TIMES;
-	k++;
-	equation[k].level = mlevel;
-	equation[k].kind = VARIABLE;
-	equation[k].token.variable = v;
+	equation[eloc].level = mlevel;
+	equation[eloc].kind = OPERATOR;
+	equation[eloc].token.operatr = TIMES;
+	eloc++;
+	equation[eloc].level = mlevel;
+	equation[eloc].kind = VARIABLE;
+	equation[eloc].token.variable = v;
 	return true;
 }
 
@@ -233,17 +227,17 @@
 char	*cp;
 {
 	int		i, j;
-	long		v;
-	double		d1;
+	long		v = 0;
 	token_type	*source, *dest;
 	int		n1, n2, *nps, *np;
 	int		def_flag;
+	double		d1, integrate_order = 1.0;
 
-	integrate_order = 1.0;
 	if (current_not_defined()) {
 		return false;
 	}
-	if (def_flag = (strcmp_tospace(cp, "definite") == 0)) {
+	def_flag = (strcmp_tospace(cp, "definite") == 0);
+	if (def_flag) {
 		cp = skip_param(cp);
 	}
 	i = next_espace();
@@ -283,7 +277,7 @@
 	n1 = *nps;
 	for (d1 = 0; d1 < integrate_order; d1++) {
 		if (!int_dispatch(dest, &n1, v, integrate_sub)) {
-			error(_("Integration failed."));
+			error(_("Integration failed, not a polynomial."));
 			return false;
 		}
 		simp_loop(dest, &n1);
@@ -324,8 +318,7 @@
 	}
 	*np = n1;
 	cur_equation = i;
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }
 
 /*
@@ -380,7 +373,6 @@
 			equation[j].level = level;
 			equation[j].kind = CONSTANT;
 			equation[j].token.constant = -1.0;
-			j++;
 			blt(&equation[eloc+len+3], &equation[eloc], (*np - eloc) * sizeof(token_type));
 			*np += len + 3;
 			k = eloc;
@@ -396,8 +388,7 @@
 			k++;
 			equation[k].level = mlevel + 1;
 			equation[k].kind = CONSTANT;
-			equation[k].token.constant = 0.0;
-			k++;
+			equation[k].token.constant = 1.0;
 			return true;
 		}
 	}
@@ -406,14 +397,13 @@
 	}
 	blt(&equation[eloc+2], &equation[eloc], (*np - eloc) * sizeof(token_type));
 	*np += 2;
-	k = eloc;
-	equation[k].level = mlevel;
-	equation[k].kind = OPERATOR;
-	equation[k].token.operatr = DIVIDE;
-	k++;
-	equation[k].level = mlevel;
-	equation[k].kind = VARIABLE;
-	equation[k].token.variable = v;
+	equation[eloc].level = mlevel;
+	equation[eloc].kind = OPERATOR;
+	equation[eloc].token.operatr = DIVIDE;
+	eloc++;
+	equation[eloc].level = mlevel;
+	equation[eloc].kind = VARIABLE;
+	equation[eloc].token.variable = v;
 	return true;
 }
 
@@ -463,7 +453,6 @@
 			equation[j].level = level;
 			equation[j].kind = CONSTANT;
 			equation[j].token.constant = 1.0;
-			j++;
 			blt(&equation[eloc+len+3], &equation[eloc], (*np - eloc) * sizeof(token_type));
 			*np += len + 3;
 			k = eloc;
@@ -479,8 +468,7 @@
 			k++;
 			equation[k].level = mlevel + 1;
 			equation[k].kind = CONSTANT;
-			equation[k].token.constant = 0.0;
-			k++;
+			equation[k].token.constant = 1.0;
 			return true;
 		}
 	}
@@ -495,7 +483,7 @@
 char	*cp;
 {
 	int		i;
-	long		v;
+	long		v = 0;
 	int		inverse_flag;
 	token_type	*source, *dest;
 	int		n1, *nps, *np;
@@ -529,7 +517,7 @@
 			return false;
 		}
 	}
-	if (extra_garbage(cp)) {
+	if (extra_characters(cp)) {
 		return false;
 	}
 	partial_flag = false;
@@ -539,15 +527,13 @@
 	blt(dest, source, *nps * sizeof(token_type));
 	n1 = *nps;
 	if (inverse_flag) {
-		if (!poly_in_v(dest, n1, v, true)
-		    || !int_dispatch(dest, &n1, v, inv_laplace_sub)) {
+		if (!poly_in_v(dest, n1, v, true) || !int_dispatch(dest, &n1, v, inv_laplace_sub)) {
 			error(_("Inverse Laplace failed."));
 			return false;
 		}
 	} else {
-		if (!poly_in_v(dest, n1, v, false)
-		    || !int_dispatch(dest, &n1, v, laplace_sub)) {
-			error(_("Laplace failed."));
+		if (!poly_in_v(dest, n1, v, false) || !int_dispatch(dest, &n1, v, laplace_sub)) {
+			error(_("Laplace failed, not a polynomial."));
 			return false;
 		}
 	}
@@ -558,11 +544,10 @@
 	}
 	*np = n1;
 	cur_equation = i;
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }
 
-#if	!BASICS && !LIBRARY
+#if	!LIBRARY
 /*
  * Numerical integrate command.
  */
@@ -570,7 +555,7 @@
 nintegrate_cmd(cp)
 char	*cp;
 {
-	long		v;
+	long		v = 0;
 	int		i, j, k, i1, i2;
 	int		level;
 	int		iterations;
@@ -616,6 +601,7 @@
 		if (!prompt_var(&v))
 			return false;
 	}
+#if	!SILENT
 	singularity = false;
 	for (j = 1; j < *nps; j += 2) {
 		if (source[j].token.operatr == DIVIDE) {
@@ -629,6 +615,7 @@
 	if (singularity) {
 		printf(_("Warning: Singularity detected, result of numerical integration may be wrong.\n"));
 	}
+#endif
 	my_strlcpy(prompt_str, _("Enter lower bound: "), sizeof(prompt_str));
 	if (!get_expr(tlhs, &n_tlhs)) {
 		return false;
@@ -647,14 +634,16 @@
 		error(_("Error: Bound contains infinity."));
 		return false;
 	}
-	if ((n_tlhs + 1 + n_trhs + 2) > n_tokens) {
+	if ((n_tlhs + n_trhs + 3) > n_tokens) {
 		error_huge();
 	}
+#if	!SILENT
 	if (trap_flag) {
-		debug_string(0, _("Approximating the definite integral using the trapezoidal method..."));
+		printf(_("Approximating definite integral using the trapezoid method (%d partitions)...\n"), iterations);
 	} else {
-		debug_string(0, _("Approximating the definite integral using Simpson's rule..."));
+		printf(_("Approximating definite integral using Simpson's rule (%d partitions)...\n"), iterations);
 	}
+#endif
 	subst_constants(source, nps);
 	simp_loop(source, nps);
 	for (j = 0; j < n_trhs; j++) {
@@ -758,16 +747,18 @@
 			n1 += 2;
 		}
 
-		in_calc_cmd = true;
+		/* simplify and approximate the partial result quickly: */
+		approximate_roots = true;
 		elim_loop(dest, &n1);
 		ufactor(dest, &n1);
 		simp_divide(dest, &n1);
-		in_calc_cmd = false;
+		approximate_roots = false;
 
 		if (exp_contains_infinity(dest, n1)) {
 			error(_("Integration failed because result contains infinity or nan."));
 			return false;
 		}
+		/* detect an ever growing result: */
 		switch (j) {
 		case 0:
 			break;
@@ -811,20 +802,22 @@
 	for (; k < n1; k++)
 		dest[k].level++;
 
-	in_calc_cmd = true;
+	/* simplify and approximate the result as before: */
+	approximate_roots = true;
 	elim_loop(dest, &n1);
 	ufactor(dest, &n1);
 	simp_divide(dest, &n1);
-	in_calc_cmd = false;
+	approximate_roots = false;
 
-	debug_string(0, _("Integration successful."));
+#if	!SILENT
+	printf(_("Integration successful.\n"));
+#endif
 	if (n_rhs[cur_equation]) {
 		blt(lhs[i], lhs[cur_equation], n_lhs[cur_equation] * sizeof(token_type));
 		n_lhs[i] = n_lhs[cur_equation];
 	}
 	*np = n1;
 	cur_equation = i;
-	return_result(cur_equation);
-	return true;
+	return return_result(cur_equation);
 }
 #endif

Modified: branches/vendor/mathomatic/lib/README.txt
===================================================================
--- branches/vendor/mathomatic/lib/README.txt	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/lib/README.txt	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,15 +1,21 @@
 This directory contains the hooks and test for the Mathomatic symbolic math
-library.  Compile and link "*.c" and "../*.c", leaving out "../main.c", with
-"-DLIBRARY" on the C compiler command line, to create the test app which uses
-the library.
+library.  Compile and link "*.c" and "../*.c" with "-DLIBRARY" on the C
+compiler command line, to create the test app which uses the library.  This is
+done by "../makefile.lib".  To compile the library and test, type:
 
+	cd ..
+	make clean
+	make -f makefile.lib
+
+This will create the library test executable "mathomatic" and the library
+file "libmathomatic.a".  To install the library in "/usr/lib", type:
+
+	sudo make -f makefile.lib install
+
 See the file "lib.c" for the very simple API, and "test.c" for an example on
-how to use it.
+how to use it.  Just include the file "mathomatic.h" and call the functions in
+"lib.c" to use the library.
 
 Note that "equation-number-range" is disabled in commands in the library.  This
 is because only one equation result may be returned at a time.  A single
 equation number is allowed for the "equation-number-range" argument.
-
-Also note that the "set display2d" option doesn't do anything in the library,
-the returned result is always a single text line, except when redirecting
-command output to a file.

Modified: branches/vendor/mathomatic/lib/lib.c
===================================================================
--- branches/vendor/mathomatic/lib/lib.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/lib/lib.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -6,7 +6,7 @@
  * And be sure to call "clear_all()" after completing each group of operations,
  * otherwise the equation spaces will fill up.
  *
- * Mathomatic Copyright (c) 1987-2005 George Gesslein II.
+ * Mathomatic Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "../includes.h"
@@ -60,7 +60,7 @@
 	if ((i = setjmp(jmp_save)) != 0) {
 		clean_up();	/* Mathomatic processing was interrupted, so do a clean up. */
 		if (i == 14) {
-			error(_("Expression too big."));
+			error(_("Expression too large."));
 		}
 		*outputp = error_str;
 		free(input);
@@ -100,7 +100,7 @@
 	if ((i = setjmp(jmp_save)) != 0) {
 		clean_up();	/* Mathomatic processing was interrupted, so do a clean up. */
 		if (i == 14) {
-			error(_("Expression too big."));
+			error(_("Expression too large."));
 		}
 		*outputp = error_str;
 		free(input);
@@ -110,7 +110,7 @@
 	error_str = NULL;
 	set_error_level(input);
 	i = next_espace();
-#if	false	/* set this true if you want to be able to enter single variable expressions with no solving */
+#if	true	/* set this true if you want to be able to enter single variable expressions with no solving */
 	if ((rv = parse(i, input))) {
 #else
 	if ((rv = process_parse(i, input))) {
@@ -125,13 +125,10 @@
 
 /*
  * Floating point exception handler.
- *
  * Usually doesn't work in most operating systems.
  */
 void
 fphandler(int sig)
 {
         error(_("Floating point exception."));
-	signal(SIGFPE, fphandler);
-	/* longjmp(jmp_save, 2); */
 }

Deleted: branches/vendor/mathomatic/lib/makefile

Modified: branches/vendor/mathomatic/lib/mathomatic.h
===================================================================
--- branches/vendor/mathomatic/lib/mathomatic.h	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/lib/mathomatic.h	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,6 +1,10 @@
-/* Function prototypes for the Mathomatic library. */
+/*
+ * Include file for the Mathomatic symbolic math library.
+ */
 
 int matho_init(void);
 int matho_process(char *input, char **outputp);
 int matho_parse(char *input, char **outputp);
 int clear_all(void);
+
+extern int	cur_equation;			/* current equation space number (origin 0) */

Modified: branches/vendor/mathomatic/lib/test.c
===================================================================
--- branches/vendor/mathomatic/lib/test.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/lib/test.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,11 +1,11 @@
 /*
- * This file contains a test for the Mathomatic library.
+ * This file contains a test for the Mathomatic symbolic math library.
  * Refer to this, if you are going to use the Mathomatic code in other projects.
  *
  * To run this, compile and link with the Mathomatic symbolic math library
  * and create an executable.
  *
- * Mathomatic Copyright (c) 1987-2005 George Gesslein II.
+ * Mathomatic Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include <stdio.h>
@@ -19,6 +19,7 @@
 	int	rv;
 	char	buf[1000];
 
+	printf("Mathomatic library test program.\n");
 	if (!matho_init()) {
 		fprintf(stderr, "Not enough memory.\n");
 		exit(1);
@@ -26,7 +27,7 @@
 	/* Mathomatic is ready for use. */
 	/* This is an input/output loop for testing. */
 	for (;;) {
-		printf("-> ");
+		printf("%d-> ", cur_equation + 1);
 		if ((cp = fgets(buf, sizeof(buf), stdin)) == NULL)
 			break;
 		rv = matho_process(cp, &ocp);

Modified: branches/vendor/mathomatic/list.c
===================================================================
--- branches/vendor/mathomatic/list.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/list.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,23 +1,33 @@
 /*
- * Algebraic manipulator expression and equation display routines.
+ * Mathomatic expression and equation display routines.
  * Color mode routines, too.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
 
+#define	EQUATE_STRING	" = "	/* string displayed between the LHS and RHS of equations */
+
+#define	APPEND(str)	{ if (string) { strcpy(&string[len], str); } len += strlen(str); }
+
 static int	flist();
 static int	flist_recurse();
 
 /* ANSI color code array */
 static int	carray[] = {
-	32, 33, 31, 35, 34, 36, 37
+	32,	/* green (default color) */
+	33,	/* yellow */
+	31,	/* red */
+	35,	/* magenta */
+	34,	/* blue */
+	36,	/* cyan */
+	37	/* white */
 };
 
 /* HTML color array */
 static char	*html_carray[] = {
-	"#00FF00",
+	"#00FF00",	/* bright green (default color) */
 	"#FFFF00",
 	"#FF9000",
 	"#FF0000",
@@ -26,6 +36,10 @@
 	"#0000FF"
 };
 
+/* global variables for flist() */
+int	cur_line;	/* current line */
+int	cur_pos;	/* current position in the current line on the screen */
+
 /*
  * Turn color off if color mode is on.
  */
@@ -39,6 +53,7 @@
 			printf("\033[0m");
 		}
 	}
+	fflush(NULL);	/* flush all output */
 }
 
 /*
@@ -78,13 +93,14 @@
 }
 
 /*
- * Display the expression or equation stored in equation space "n" in single line format.
+ * Display the expression or equation stored in equation space "n" in single-line format.
+ * The equation space is not modified.
  *
  * Return true if successful.
  */
 int
 list1_sub(n, export_flag)
-int	n;		/* equation number */
+int	n;		/* equation space number */
 int	export_flag;	/* true for exportable format (readable by other math programs) */
 			/* 1 for Maxima, 2 for other */
 {
@@ -95,7 +111,7 @@
 	}
 	list_proc(lhs[n], n_lhs[n], export_flag);
 	if (n_rhs[n]) {
-		fprintf(gfp, " = ");
+		fprintf(gfp, EQUATE_STRING);
 		list_proc(rhs[n], n_rhs[n], export_flag);
 	}
 	if (export_flag == 1) {
@@ -120,21 +136,21 @@
  */
 int
 list_sub(n)
-int	n;	/* equation number */
+int	n;	/* equation space number */
 {
 	if (n_lhs[n] <= 0)
 		return false;
-	if (groupall) {
-		group_sub(n);
+	if (display2d) {
+		/* display in fraction format */
+		make_fractions_and_group(n);
 		if (factor_int_flag) {
-			factor_int(lhs[n], &n_lhs[n]);
-			factor_int(rhs[n], &n_rhs[n]);
+			factor_int_sub(n);
 		}
 		return flist_sub(n);
 	} else {
+		/* display in single-line format */
 		if (factor_int_flag) {
-			factor_int(lhs[n], &n_lhs[n]);
-			factor_int(rhs[n], &n_rhs[n]);
+			factor_int_sub(n);
 		}
 		return list1_sub(n, false);
 	}
@@ -152,7 +168,7 @@
 		printf(_("level %d: "), level);
 		list_proc(p1, n1, false);
 		if (p2 && n2 > 0) {
-			printf(" = ");
+			printf(EQUATE_STRING);
 			list_proc(p2, n2, false);
 		}
 		printf("\n");
@@ -209,15 +225,15 @@
 		break;
 	case V_E:
 		switch (lang_code) {
-		case -2:
-			cp = "e";
-			break;
 		case -1:
 			cp = "%e";
 			break;
 		case 0:
 			cp = "e#";
 			break;
+		case 1:
+			cp ="M_E";
+			break;
 		case 2:
 			cp = "Math.E";
 			break;
@@ -225,7 +241,7 @@
 			cp = "math.e";
 			break;
 		default:
-			cp = "E";
+			cp = "e";
 			break;
 		}
 		break;
@@ -234,8 +250,11 @@
 		case -1:
 			cp = "%pi";
 			break;
+		case 0:
+			cp = "pi#";
+			break;
 		case 1:
-			cp = "PI";
+			cp = "M_PI";
 			break;
 		case 2:
 			cp = "Math.PI";
@@ -251,15 +270,6 @@
 	case MATCH_ANY:
 		cp = "all";
 		break;
-	case V_ANSWER:
-		cp = "answer";
-		break;
-	case V_TEMP:
-		cp = "temp";
-		break;
-	case V_INTEGER:
-		cp = "integer";
-		break;
 	default:
 		j = (v & VAR_MASK) - VAR_OFFSET;
 		if (j >= 0) {
@@ -277,19 +287,13 @@
 		snprintf(buf, sizeof(buf), "%d", j - 1);
 		strcat(var_str, buf);
 	}
-	if (lang_code > 0) {
-		for (cp = var_str; *cp; cp++) {
-			if (*cp == '\\') {
-				*cp = '_';
-			}
-		}
-	}
 	return(strlen(var_str));
 }
 
 /*
  * Display an expression in single line format.
  * Use color if available.
+ * The expression is not modified.
  *
  * Return number of characters output (excluding escape sequences).
  */
@@ -323,8 +327,11 @@
 		}
 		switch (equation[i].kind) {
 		case CONSTANT:
+			if (equation[i].token.constant == 0.0) {
+				equation[i].token.constant = 0.0; /* fix -0 */
+			}
 			if (high_prec || export_flag) {
-				if (equation[i].token.constant <= 0.0) {
+				if (equation[i].token.constant < 0.0) {
 					len += fprintf(gfp, "(%.20g)", equation[i].token.constant);
 				} else {
 					len += fprintf(gfp, "%.20g", equation[i].token.constant);
@@ -332,7 +339,7 @@
 			} else if (finance_option) {
 				len += fprintf(gfp, "%.2f", equation[i].token.constant);
 			} else {
-				len += fprintf(gfp, "%.12g", equation[i].token.constant);
+				len += fprintf(gfp, "%.*g", precision, equation[i].token.constant);
 			}
 			break;
 		case VARIABLE:
@@ -358,11 +365,7 @@
 				cp = " % ";
 				break;
 			case POWER:
-				if (starstar) {
-					cp = "**";
-				} else {
-					cp = "^";
-				}
+				cp = "^";
 				break;
 			case FACTORIAL:
 				cp = "!";
@@ -389,7 +392,7 @@
  */
 char *
 list_equation(n, export_flag)
-int	n;		/* equation number */
+int	n;		/* equation space number */
 int	export_flag;	/* flag for exportable format (usually false) */
 {
 	int	len;
@@ -397,16 +400,18 @@
 
 	len = list_string_sub(lhs[n], n_lhs[n], NULL, export_flag);
 	if (n_rhs[n]) {
-		len += 3;
+		len += strlen(EQUATE_STRING);
 		len += list_string_sub(rhs[n], n_rhs[n], NULL, export_flag);
 	}
 	len += 2;
 	cp = (char *) malloc(len);
-	if (cp == NULL)
+	if (cp == NULL) {
+		error(_("Out of memory (can't malloc(3))."));
 		return NULL;
+	}
 	list_string_sub(lhs[n], n_lhs[n], cp, export_flag);
 	if (n_rhs[n]) {
-		strcat(cp, " = ");
+		strcat(cp, EQUATE_STRING);
 		list_string_sub(rhs[n], n_rhs[n], &cp[strlen(cp)], export_flag);
 	}
 	if (export_flag == 1) {
@@ -415,7 +420,6 @@
 	return cp;
 }
 
-#if	false
 /*
  * Store an expression in a text string.
  * String should be freed with free() when done.
@@ -434,12 +438,13 @@
 	len = list_string_sub(equation, n, NULL, export_flag);
 	len++;
 	cp = (char *) malloc(len);
-	if (cp == NULL)
+	if (cp == NULL) {
+		error(_("Out of memory (can't malloc(3))."));
 		return NULL;
+	}
 	list_string_sub(equation, n, cp, export_flag);
 	return cp;
 }
-#endif
 
 /*
  * Convert an expression to a text string and store in "string" if
@@ -471,37 +476,33 @@
 		for (i1 = 1; i1 <= k; i1++) {
 			if (j > 0) {
 				cur_level--;
-				if (string)
-					strcat(string, ")");
-				len++;
+				APPEND(")");
 			} else {
 				cur_level++;
-				if (string)
-					strcat(string, "(");
-				len++;
+				APPEND("(");
 			}
 		}
 		switch (equation[i].kind) {
 		case CONSTANT:
+			if (equation[i].token.constant == 0.0) {
+				equation[i].token.constant = 0.0; /* fix -0 */
+			}
 			if (high_prec || export_flag) {
-				if (equation[i].token.constant <= 0.0) {
-					len += snprintf(buf, sizeof(buf), "(%.20g)", equation[i].token.constant);
+				if (equation[i].token.constant < 0.0) {
+					snprintf(buf, sizeof(buf), "(%.20g)", equation[i].token.constant);
 				} else {
-					len += snprintf(buf, sizeof(buf), "%.20g", equation[i].token.constant);
+					snprintf(buf, sizeof(buf), "%.20g", equation[i].token.constant);
 				}
 			} else if (finance_option) {
-				len += snprintf(buf, sizeof(buf), "%.2f", equation[i].token.constant);
+				snprintf(buf, sizeof(buf), "%.2f", equation[i].token.constant);
 			} else {
-				len += snprintf(buf, sizeof(buf), "%.12g", equation[i].token.constant);
+				snprintf(buf, sizeof(buf), "%.*g", precision, equation[i].token.constant);
 			}
-			if (string) {
-				strcat(string, buf);
-			}
+			APPEND(buf);
 			break;
 		case VARIABLE:
-			len += list_var(equation[i].token.variable, 0 - export_flag);
-			if (string)
-				strcat(string, var_str);
+			list_var(equation[i].token.variable, 0 - export_flag);
+			APPEND(var_str);
 			break;
 		case OPERATOR:
 			cp = _("(unknown operator)");
@@ -522,27 +523,19 @@
 				cp = " % ";
 				break;
 			case POWER:
-				if (starstar) {
-					cp = "**";
-				} else {
-					cp = "^";
-				}
+				cp = "^";
 				break;
 			case FACTORIAL:
 				cp = "!";
 				i++;
 				break;
 			}
-			len += strlen(cp);
-			if (string)
-				strcat(string, cp);
+			APPEND(cp);
 			break;
 		}
 	}
 	for (j = cur_level - min1; j > 0; j--) {
-		if (string)
-			strcat(string, ")");
-		len++;
+		APPEND(")");
 	}
 	return len;
 }
@@ -557,14 +550,11 @@
 int		n;		/* length of expression */
 {
 	int	i;
-	double	d;
 
 	for (i = 0; i < n; i++) {
-		if ((equation[i].kind == CONSTANT
-		    && fmod(equation[i].token.constant, 1.0) != 0.0)
-		    || (equation[i].kind == VARIABLE
-		    && var_is_const(equation[i].token.variable, &d))) {
-			return false;	/* non-integer constant */
+		if ((equation[i].kind == CONSTANT && fmod(equation[i].token.constant, 1.0))
+		    || (equation[i].kind == VARIABLE && equation[i].token.variable <= IMAGINARY)) {
+			return false;
 		}
 	}
 	return true;
@@ -573,32 +563,35 @@
 /*
  * Display an equation as C, Java, or Python code.
  */
-list_c_equation(en, java_flag, int_flag)
-int	en;		/* equation number */
-int	java_flag;
+list_c_equation(en, language, int_flag)
+int	en;		/* equation space number */
+int	language;
 int	int_flag;	/* integer arithmetic flag */
 {
 	if (n_lhs[en] <= 0)
 		return;
-	list_code(lhs[en], &n_lhs[en], java_flag, int_flag);
+	list_code(lhs[en], &n_lhs[en], language, int_flag);
 	if (n_rhs[en]) {
 		fprintf(gfp, " = ");
-		list_code(rhs[en], &n_rhs[en], java_flag, int_flag);
+		list_code(rhs[en], &n_rhs[en], language, int_flag);
 	}
-	fprintf(gfp, ";\n");
+	if (language != 2) {
+		fprintf(gfp, ";");
+	}
+	fprintf(gfp, "\n");
 }
 
 /*
  * Output C, Java, or Python code for an expression.
- * Expression may be modified.
+ * Expression might be modified by this function.
  *
  * Return length of output (number of characters).
  */
 int
-list_code(equation, np, java_flag, int_flag)
+list_code(equation, np, language, int_flag)
 token_type	*equation;	/* expression pointer */
 int		*np;		/* pointer to length of expression */
-int		java_flag;	/* if 1, generate Java code, if 2, generate Python code */
+int		language;	/* if 0, generate C code; if 1, generate Java code; if 2, generate Python code */
 int		int_flag;	/* integer arithmetic flag, should work with any language */
 {
 	int	i, j, k, i1, i2;
@@ -618,8 +611,7 @@
 		for (i1 = 1; i1 <= k; i1++) {
 			if (j > 0) {
 				cur_level--;
-				fprintf(gfp, ")");
-				len++;
+				len += fprintf(gfp, ")");
 			} else {
 				cur_level++;
 				for (i2 = i + 1; i2 < *np && equation[i2].level >= cur_level; i2 += 2) {
@@ -633,9 +625,9 @@
 								equation[i2].token.operatr = TIMES;
 								equation[i2+1] = equation[i2-1];
 							} else {
-								if (int_flag || java_flag > 1)
+								if (int_flag || language > 1)
 									break;
-								if (java_flag) {
+								if (language) {
 									cp = "Math.pow";
 								} else {
 									cp = "pow";
@@ -651,16 +643,18 @@
 						break;
 					}
 				}
-				fprintf(gfp, "(");
-				len++;
+				len += fprintf(gfp, "(");
 			}
 		}
 		switch (equation[i].kind) {
 		case CONSTANT:
+			if (equation[i].token.constant == 0.0) {
+				equation[i].token.constant = 0.0; /* fix -0 */
+			}
 			if (int_flag) {
 				snprintf(buf, sizeof(buf), "%.0f", equation[i].token.constant);
 			} else {
-				snprintf(buf, sizeof(buf), "%#.16g", equation[i].token.constant);
+				snprintf(buf, sizeof(buf), "%#.*g", MAX_PRECISION, equation[i].token.constant);
 				j = strlen(buf) - 1;
 				for (; j >= 0; j--) {
 					if (buf[j] == '0')
@@ -675,7 +669,7 @@
 			len += fprintf(gfp, "%s", buf);
 			break;
 		case VARIABLE:
-			len += list_var(equation[i].token.variable, java_flag + 1);
+			len += list_var(equation[i].token.variable, language + 1);
 			fprintf(gfp, "%s", var_str);
 			break;
 		case OPERATOR:
@@ -697,7 +691,7 @@
 				cp = " % ";
 				break;
 			case POWER:
-				if (int_flag || java_flag > 1) {
+				if (int_flag || language > 1) {
 					cp = " ** ";
 				} else {
 					cp = ", ";
@@ -718,20 +712,16 @@
 	return len;
 }
 
-int	cur_line;	/* current line */
-int	cur_pos;	/* current position in the current line on the screen */
-
 /*
- * Display an expression or equation in multi-line fraction format.
+ * Display an equation space in multi-line fraction format.
  * Use color if available.
  *
  * Return true if successful.
  */
 int
 flist_sub(n)
-int	n;	/* equation number */
+int	n;	/* equation space number */
 {
-	int	i;
 	int	sind;
 	char	buf[30];
 	int	len, len2, len3;
@@ -748,7 +738,7 @@
 	sind = n_rhs[n];
 	len += flist(lhs[n], n_lhs[n], false, 0, &max_line, &min_line);
 	if (n_rhs[n]) {
-		len += 3;
+		len += strlen(EQUATE_STRING);
 make_smaller:
 		len2 = flist(rhs[n], sind, false, 0, &high, &low);
 		if (screen_columns && gfp == stdout && (len + len2) >= screen_columns && sind > 0) {
@@ -777,27 +767,25 @@
 		return list1_sub(n, false);
 	}
 	fprintf(gfp, "\n");
-	for (i = max_line; i >= min_line; i--) {
-		cur_line = i;
-		cur_pos = 0;
-		if (i == 0) {
+	for (cur_line = max_line; cur_line >= min_line; cur_line--) {
+		pos = cur_pos = 0;
+		if (cur_line == 0) {
 			cur_pos += fprintf(gfp, "%s", buf);
 		}
-		pos = strlen(buf);
+		pos += strlen(buf);
 		pos += flist(lhs[n], n_lhs[n], true, pos, &high, &low);
 		if (n_rhs[n]) {
-			if (i == 0) {
-				cur_pos += fprintf(gfp, "%s", " = ");
+			if (cur_line == 0) {
+				cur_pos += fprintf(gfp, "%s", EQUATE_STRING);
 			}
-			pos += 3;
-			flist(rhs[n], sind, true, pos, &high, &low);
+			pos += strlen(EQUATE_STRING);
+			pos += flist(rhs[n], sind, true, pos, &high, &low);
 		}
 		fprintf(gfp, "\n");
 	}
 	if (sind < n_rhs[n]) {
 		fprintf(gfp, "\n");
-		for (i = max2_line; i >= min2_line; i--) {
-			cur_line = i;
+		for (cur_line = max2_line; cur_line >= min2_line; cur_line--) {
 			cur_pos = 0;
 			flist(&rhs[n][sind], n_rhs[n] - sind, true, 0, &high, &low);
 			fprintf(gfp, "\n");
@@ -942,7 +930,11 @@
 			if (oflag) {
 				set_color(level-1);
 				for (j = 0; j < len_div; j++) {
-					fprintf(gfp, "-");
+					if (html_flag) {
+						fprintf(gfp, "&mdash;");
+					} else {
+						fprintf(gfp, "-");
+					}
 				}
 				set_color(cur_level-1);
 			}
@@ -960,12 +952,13 @@
 		}
 		switch (equation[i].kind) {
 		case CONSTANT:
-			if (equation[i].token.constant == 0.0)
+			if (equation[i].token.constant == 0.0) {
 				equation[i].token.constant = 0.0; /* fix -0 */
+			}
 			if (finance_option) {
 				len += snprintf(buf, sizeof(buf), "%.2f", equation[i].token.constant);
 			} else {
-				len += snprintf(buf, sizeof(buf), "%.12g", equation[i].token.constant);
+				len += snprintf(buf, sizeof(buf), "%.*g", precision, equation[i].token.constant);
 			}
 			if (oflag)
 				fprintf(gfp, "%s", buf);
@@ -994,11 +987,7 @@
 				cp = " % ";
 				break;
 			case POWER:
-				if (starstar) {
-					cp = "**";
-				} else {
-					cp = "^";
-				}
+				cp = "^";
 				break;
 			case FACTORIAL:
 				cp = "!";

Modified: branches/vendor/mathomatic/main.c
===================================================================
--- branches/vendor/mathomatic/main.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/main.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,8 +1,8 @@
 /*
- * This file contains main() and startup code for Mathomatic.
+ * This file contains main() and the startup code for Mathomatic.
  * Leave this file out when compiling for the symbolic math library.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  *
  * Output to stderr is only done in this file.  The rest of the code
  * should not output to stderr.
@@ -28,6 +28,9 @@
  * Any number of TIMES and DIVIDE operators may be on the same
  * level, because they are simple multiplicative class operators.
  * The same for PLUS and MINUS, because they are additive class operators.
+ *
+ * See the file "am.h" to start understanding the Mathomatic code and
+ * to adjust memory usage.
  */
 
 #if	!LIBRARY
@@ -38,26 +41,6 @@
 static void usage();
 static int set_signals();
 
-#if	CYGWIN
-/*
- * dirname(3) function for Windows.
- */
-char	*
-dirname1(cp)
-char	*cp;
-{
-	int	i;
-
-	i = strlen(cp);
-	while (i >= 0 && cp[i] != '\\' && cp[i] != '/')
-		i--;
-	if (i < 0)
-		return(".");
-	cp[i] = '\0';
-	return(cp);
-}
-#endif
-
 int
 main(argc, argv)
 int	argc;
@@ -70,39 +53,44 @@
 	char		*cp;
 	double		numerator, denominator;
 	double		multiplier;
-	struct winsize	ws;
 	int		coption = false;
 
 #if	UNIX
-	prog_name = strdup(basename(argv[0]));	/* set prog_name to this executable's filename */
+	prog_name = strdup(basename(argv[0]));		/* set prog_name to this executable's filename */
 #endif
 #if	CYGWIN
-	dir_path = strdup(dirname1(argv[0]));	/* set dir_path to this executable's directory */
+	dir_path = strdup(dirname_win(argv[0]));	/* set dir_path to this executable's directory */
 #endif
 	/* initialize the global variables */
 	init_gvars();
 	gfp = stdout;
 
 	/* process command line options */
-	while ((i = getopt(argc, argv, "qtchuvm:")) >= 0) {
+	while ((i = getopt(argc, argv, "qrtchuvm:")) >= 0) {
 		switch (i) {
 		case 'c':
-			coption = true;
+			coption++;
 			break;
 		case 'h':
+			readline_enabled = false;
 			html_flag = true;
 			break;
 		case 'm':
-			multiplier = atof(optarg);
-			if (multiplier <= 0.0 || (n_tokens = (int) (multiplier * DEFAULT_N_TOKENS)) <= 0) {
-				fprintf(stderr, _("Invalid memory size multiplier specified!\n"));
-				usage();
+			multiplier = strtod(optarg, &cp) * DEFAULT_N_TOKENS;
+			if (*cp || multiplier < 100 || multiplier >= (INT_MAX / 3)) {
+				fprintf(stderr, _("%s: Invalid memory size multiplier specified.\n"), prog_name);
+				exit(1);
 			}
+			n_tokens = (int) multiplier;
 			break;
 		case 'q':
 			quiet_mode = true;
 			break;
+		case 'r':
+			readline_enabled = false;
+			break;
 		case 't':
+			readline_enabled = false;
 			test_mode = true;
 			break;
 		case 'u':
@@ -119,17 +107,7 @@
 		screen_columns = 0;
 		screen_rows = 0;
 	} else {
-		/* get the screen width and height */
-		ws.ws_col = 0;
-		ws.ws_row = 0;
-		if (ioctl(1, TIOCGWINSZ, &ws) >= 0) {
-			if (ws.ws_col) {
-				screen_columns = ws.ws_col;
-			}
-			if (ws.ws_row) {
-				screen_rows = ws.ws_row;
-			}
-		}
+		get_screen_size();
 	}
 	if (!init_mem()) {
 		fprintf(stderr, _("%s: Not enough memory.\n"), prog_name);
@@ -143,12 +121,14 @@
 		printf(_("Secure "));
 #endif
 		printf(_("Mathomatic version %s (www.mathomatic.org)\n"), VERSION);
-		printf(_("Copyright (C) 1987-2006 George Gesslein II.\n"));
-		printf(_("%d equation spaces available, %ldK per equation space.\n\n"),
-		    N_EQUATIONS, (long) n_tokens * sizeof(token_type) * 2L / 1000L);
+		printf(_("Copyright (C) 1987-2007 George Gesslein II.\n"));
+		printf(_("This is free software; see the source for copying conditions.  There is NO\n"));
+		printf(_("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
+		printf(_("%d equation spaces available, %lld kilobytes per equation space.\n"),
+		    N_EQUATIONS, (long long) n_tokens * sizeof(token_type) * 2LL / 1000LL);
 	}
 #if	!SECURE
-	/* read the options initialization file */
+	/* read the user options initialization file */
 	if (!test_mode && !load_rc()) {
 		fprintf(stderr, _("Error loading set options from \"%s\".\n"), RC_FILE);
 	}
@@ -156,9 +136,12 @@
 	if (test_mode) {
 		color_flag = false;
 	}
-	if (coption) {
+	if (coption & 1) {
 		color_flag = !color_flag;
 	}
+	if (!test_mode && !quiet_mode && color_flag) {
+		printf(_("%s color mode enabled.\n"), html_flag ? "HTML" : "ANSI");
+	}
 	if ((i = setjmp(jmp_save)) != 0) {
 		/* for error handling */
 		clean_up();
@@ -167,20 +150,20 @@
 			printf(_("Operation abruptly aborted.\n"));
 			break;
 		case 14:
-			error(_("Expression too big."));
+			error(_("Expression too large."));
 		default:
 			printf(_("Operation aborted.\n"));
 		}
 	} else {
 		if (!set_signals()) {
-			fprintf(stderr, _("Signal(2) setting failed.\n"));
+			fprintf(stderr, _("signal(2) setting failed.\n"));
 		}
 		if (!f_to_fraction(0.5, &numerator, &denominator)
 		    || !f_to_fraction(1.0/3.0, &numerator, &denominator)) {
 			fprintf(stderr, _("Cannot convert floating point values to fractions.\n"));
 		}
 #if	!SECURE
-		/* read in files on the command line */
+		/* read in files on the command line, exit if error */
 		for (i = optind; i < argc; i++) {
 			if (!read_cmd(argv[i])) {
 				exit_program(1);
@@ -209,12 +192,13 @@
 	fprintf(stderr, _("Usage: %s [ options ] [ input_files ]\n\n"), prog_name);
 	fprintf(stderr, _("Options:\n"));
 	fprintf(stderr, _("  -c               Toggle color mode.\n"));
-	fprintf(stderr, _("  -h               Enable HTML mode.\n"));
+	fprintf(stderr, _("  -h               Enable HTML output mode and disable readline.\n"));
 	fprintf(stderr, _("  -m number        Specify a memory size multiplier.\n"));
 	fprintf(stderr, _("  -q               Quiet mode (don't display prompts).\n"));
+	fprintf(stderr, _("  -r               Disable readline.\n"));
 	fprintf(stderr, _("  -t               Used when testing.\n"));
-	fprintf(stderr, _("  -u               Unbuffered output.\n"));
-	fprintf(stderr, _("  -v               Display version number and compile flags used.\n"));
+	fprintf(stderr, _("  -u               Set unbuffered output.\n"));
+	fprintf(stderr, _("  -v               Display version number, compile flags, and memory usage.\n"));
 	exit(1);
 }
 
@@ -242,6 +226,26 @@
 	return rv;
 }
 
+#if	CYGWIN
+/*
+ * dirname(3) function for Windows.
+ */
+char	*
+dirname_win(cp)
+char	*cp;
+{
+	int	i;
+
+	i = strlen(cp);
+	while (i >= 0 && cp[i] != '\\' && cp[i] != '/')
+		i--;
+	if (i < 0)
+		return(".");
+	cp[i] = '\0';
+	return(cp);
+}
+#endif
+
 #if	!SECURE
 /*
  * Load set options from "~/.mathomaticrc".
@@ -271,7 +275,7 @@
 	if (fp == NULL)
 		return true;
 #endif
-	while (cp = fgets(buf, sizeof(buf), fp)) {
+	while ((cp = fgets(buf, sizeof(buf), fp)) != NULL) {
 		set_error_level(cp);
 		if (!set_options(cp))
 			rv = false;
@@ -283,25 +287,24 @@
 
 /*
  * Floating point exception handler.
- * Seldom works.
+ * Usually doesn't work in most operating systems.
  */
 void
 fphandler(sig)
 int	sig;
 {
 	error(_("Floating point exception."));
-	signal(SIGFPE, fphandler);
-	longjmp(jmp_save, 2);
 }
 
 /*
- * Control-C handler.
- * Abruptly quits this program.
+ * Control-C (interrupt) handler.
+ * Abruptly quit this program.
  */
 void
 inthandler(sig)
 int	sig;
 {
+	printf(_("\nControl-C pressed, quitting...\n"));
 	exit_program(1);
 }
 
@@ -313,38 +316,46 @@
 alarmhandler(sig)
 int	sig;
 {
-	printf(_("\ntimeout\n"));
+	printf(_("\nTimeout, quitting...\n"));
 	exit_program(1);
 }
 #endif
 
 /*
- * Window resize handler.
+ * Get the screen (window) width and height.
  */
-void
-resizehandler(sig)
-int	sig;
+get_screen_size()
 {
 	struct winsize	ws;
 
 	ws.ws_col = 0;
 	ws.ws_row = 0;
 	if (ioctl(1, TIOCGWINSZ, &ws) >= 0) {
-		if (ws.ws_col && screen_columns) {
+		if (ws.ws_col > 0 && screen_columns) {
 			screen_columns = ws.ws_col;
 		}
-		if (ws.ws_row && screen_rows) {
+		if (ws.ws_row > 0 && screen_rows) {
 			screen_rows = ws.ws_row;
 		}
 	}
 }
 
 /*
+ * Window resize handler.
+ */
+void
+resizehandler(sig)
+int	sig;
+{
+	get_screen_size();
+}
+
+/*
  * Exit this program and return to the Operating System.
  */
 void
 exit_program(exit_value)
-int	exit_value;
+int	exit_value;	/* zero if OK, non-zero indicates error return */
 {
 	reset_attr();
 	printf("\n");

Modified: branches/vendor/mathomatic/makefile
===================================================================
--- branches/vendor/mathomatic/makefile	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/makefile	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,40 +1,43 @@
 # Makefile for compiling, testing, and installing Mathomatic under any UNIX like OS.
-# Currently uses gcc only options, just remove them for other C compilers.
+# Currently uses gcc only options in CFLAGS, just remove them for other C compilers.
 
 VERSION		= `cat VERSION`
-CFLAGS		+= -O -Wunused -Wshadow -DUNIX -DVERSION=\"$(VERSION)\"
-LDFLAGS		+= -s
-LIBS		+= -lm
+CFLAGS		+= -Wuninitialized -Wunused -Wshadow -Wformat -Wparentheses -Wcast-align
+CFLAGS		+= -O -DUNIX -DVERSION=\"$(VERSION)\"
+LDFLAGS		+= -s # The default linker flags.
+LIBS		+= -lm # The default libraries to link.
 
+# "make READLINE=1" to include readline support:
 CFLAGS		+= $(READLINE:1=-DREADLINE)
 LIBS		+= $(READLINE:1=-lreadline -lncurses)
 
+# Install directories:
 prefix		?= /usr/local
 bindir		?= $(prefix)/bin
 mandir		?= $(prefix)/man
 docdir		?= $(prefix)/share/doc
 
-AOUT		= mathomatic
+AOUT		= mathomatic # The name of the executable to create.
 TARGETS		= $(AOUT) doc/manpage.html
+
 OBJECTS		= main.o globals.o am.o solve.o help.o parse.o cmds.o simplify.o \
 		  factor.o super.o unfactor.o poly.o diff.o integrate.o \
 		  complex.o complex_lib.o list.o gcd.o factor_int.o
+
 MAN1		= mathomatic.1
-DOCS		= COPYING README.txt changes.txt doc/*
+DOCS		= COPYING README.txt changes.txt mathomatic.ico
 
 all: $(TARGETS)
-	@cd lib && make
 	@echo Make completed.
 
-check: test
-
-test: $(TARGETS)
-	cd tests && time ../$(AOUT) -t all >test.out && diff -u all.out test.out
+check test: $(TARGETS)
+	@echo Testing Mathomatic...
+	@cd tests && time ../$(AOUT) -t all >test.out && diff -u all.out test.out
 	@rm tests/test.out
 	@echo All tests passed.
 
 baseline: $(TARGETS)
-	cd tests && time ../$(AOUT) -t all >all.out
+	@cd tests && ../$(AOUT) -t all >all.out
 	@rm -f tests/test.out
 
 $(OBJECTS): includes.h am.h externs.h complex.h proto.h VERSION
@@ -49,13 +52,15 @@
 	install -d $(bindir)
 	install -d $(mandir)/man1
 	install -d $(docdir)/mathomatic
+	install -d $(docdir)/mathomatic/html
 	install -d $(docdir)/mathomatic/tests
-	install -d $(docdir)/mathomatic/fact
+	install -d $(docdir)/mathomatic/factorial
 	install -m 0755 $(AOUT) $(bindir)
 	install -m 0644 $(MAN1) $(mandir)/man1
 	install -m 0644 $(DOCS) $(docdir)/mathomatic
+	install -m 0644 doc/* $(docdir)/mathomatic/html
 	install -m 0644 tests/* $(docdir)/mathomatic/tests
-	install -m 0644 fact/* $(docdir)/mathomatic/fact
+	install -m 0644 factorial/* $(docdir)/mathomatic/factorial
 	@echo Install completed.
 
 uninstall:
@@ -65,5 +70,9 @@
 	@echo Uninstall completed.
 
 clean:
-	rm -f *.o
-	rm -f lib/*.o
+	rm -f *.o *.a
+	rm -f lib/*.o lib/*.a
+
+flush: clean
+	rm -f $(AOUT)
+	rm -f mathomatic_secure

Added: branches/vendor/mathomatic/makefile.lib

Modified: branches/vendor/mathomatic/mathomatic.1
===================================================================
--- branches/vendor/mathomatic/mathomatic.1	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/mathomatic.1	2007-06-24 11:58:26 UTC (rev 1806)
@@ -6,7 +6,7 @@
 .SH SYNOPSIS
 .B mathomatic
 [
-.B -chqtuv
+.B -chqrtuv
 ] [
 .B -m
 number
@@ -15,15 +15,19 @@
 ]
 
 .SH DESCRIPTION
-Mathomatic is a portable, general purpose CAS (Computer Algebra
-System) that can automatically solve, simplify,
-combine, and compare algebraic equations.
+Mathomatic is a portable, general purpose CAS (Computer Algebra System)
+that can symbolically solve, simplify, combine, and compare algebraic equations,
+perform complex number and polynomial arithmetic, etc.
 It does some calculus and handles all algebra, except trigonometry and logarithms.
-It is entirely hand-written in optimized C.
+
+Mathomatic is entirely hand-written in optimized C.
 It does not permit extremely large expressions, which can take a lot
 of memory and time.
 Instead reliability, ease of use, and speed are its features.
 
+All arithmetic is double precision floating point
+with 14 decimal digits accuracy.
+
 .SH OPTIONS
 .TP
 .B \-c
@@ -33,28 +37,39 @@
 
 .TP
 .B \-h
-Enable HTML mode (also valid XHTML).
+Enable HTML output mode (also valid XHTML) and disable readline input.
 This makes Mathomatic output suitable for inclusion in a web page.
 The color mode flag affects this mode, allowing HTML color output.
-It is recommended that the web page have a black background in color mode.
+By default, Mathomatic uses maximum brightness colors for HTML,
+so it is recommended that the web page have a dark background.
 
 .TP
 .B \-m number
 Change the memory size of equation spaces.
-It is followed by a floating point number which is a multiplier
+It is followed by a decimal floating point number which is a multiplier
 of the default equation size.
 Please don't set this higher than 10, unless you know what you are doing.
 
 .TP
 .B \-q
-Sets quiet mode.
-Prompts are not displayed.
+Set quiet mode.
+The startup message and prompts are not displayed.
+This is useful when piping or redirecting input into Mathomatic,
+because the input won't be displayed,
+so prompt output should be turned off.
 
 .TP
+.B \-r
+Completely disable readline input processing.
+Readline allows using the cursor keys and outputs terminal control codes
+which can be turned off with this option.
+
+.TP
 .B \-t
-Sets test mode.
+Set test mode.
 Used when testing and comparing output.
-Bypasses loading startup file, turns off color mode, etc.
+Bypasses loading startup file, turns off color mode and readline,
+sets infinite screen width and height, etc.
 
 .TP
 .B \-u
@@ -62,11 +77,12 @@
 
 .TP
 .B \-v
-Display version number and compile flags used and exit.
+Display version number, compile flags used, maximum memory usage, and then exit.
+The maximum memory usage displayed does not include stack size (which varies) or executable size.
 
 .SH GENERAL
 First you type in your algebraic equations in standard infix notation,
-then you can solve them by just typing in the variable, or
+then you can solve them by typing in the variable name at the prompt, or
 perform operations on them with simple English commands.
 Type "help" for the help command.
 If the command is longer than 4 letters, you only need
@@ -74,12 +90,12 @@
 Most commands operate on the current equation by default.
 
 Documentation is available in HTML format,
-see the web site "www.mathomatic.org".
+see the documentation directory or the web site "www.mathomatic.org".
 
 .SH ENVIRONMENT
 .TP
 .B EDITOR
-Editor to use for the edit command.
+This environment variable specifies the editor to use for the edit command.
 
 .SH FILES
 .TP
@@ -88,5 +104,8 @@
 It should be a text file with one set option per line.
 Do not include the word "set".
 
+.SH REPORTING BUGS
+Report bugs to <gesslein at panix.com>.
+
 .SH AUTHOR
-George Gesslein II
+George Gesslein II <gesslein at panix.com>

Modified: branches/vendor/mathomatic/parse.c
===================================================================
--- branches/vendor/mathomatic/parse.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/parse.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,14 +1,26 @@
 /*
  * Expression parsing routines for Mathomatic.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
 
-int	point_flag;	/* point to error if true */
+#define	INFINITY_NAME	"inf"	/* set this to the name of the infinity constant as displayed by printf(3) */
 
+int	point_flag;		/* point to location of parse error if true */
+
 /*
+ * Return true if character is a valid starting variable character.
+ */
+int
+isvarchar(ch)
+int	ch;
+{
+	return(ch == '_' || (special_variable_character && ch == special_variable_character) || isalpha(ch));
+}
+
+/*
  * Parse an equation string into equation space "n".
  *
  * Returns the new string position or NULL on error.
@@ -23,6 +35,8 @@
 	}
 	if ((cp = parse_section(lhs[n], &n_lhs[n], cp)) != NULL) {
 		if ((cp = parse_section(rhs[n], &n_rhs[n], cp)) != NULL) {
+			if (extra_characters(cp))
+				return NULL;
 			return cp;
 		}
 	}
@@ -39,15 +53,14 @@
  */
 char	*
 parse_section(equation, np, cp)
-token_type	*equation;	/* where the parsed expression is stored */
-int		*np;		/* pointer to parsed expression length */
+token_type	*equation;	/* where the parsed expression is stored (equation side) */
+int		*np;		/* pointer to the returned parsed expression length */
 char		*cp;		/* string to parse */
 {
 	int		n = 0;		/* position in equation[] */
 	int		cur_level = 1;	/* current level of parentheses */
 	int		operand;	/* flip-flop between operand and operator */
-	char		*cp_start;
-	char		*cp1;
+	char		*cp_start, *cp1;
 	double		d;
 	int		abs_count = 0;
 	int		abs_array[10];
@@ -129,13 +142,17 @@
 			if (operand) {
 				goto syntax_error;
 			}
+			if (cp[1] == '!') {
+				put_up_arrow((int) (cp - cp_start), _("Multifactorial not supported yet."));
+				return(NULL);
+			}
 			equation[n].level = cur_level;
 			equation[n].kind = OPERATOR;
 			equation[n].token.operatr = FACTORIAL;
 			n++;
 			equation[n].level = cur_level;
 			equation[n].kind = CONSTANT;
-			equation[n].token.constant = 0.0;
+			equation[n].token.constant = 1.0;
 			n++;
 			operand = true;
 			break;
@@ -222,7 +239,7 @@
 				equation[n].token.operatr = TIMES;
 				n++;
 			}
-			if (*cp == '-' && !((isascii(cp[1]) && isdigit(cp[1])) || cp[1] == '.')) {
+			if (*cp == '-' && !(isdigit(cp[1]) || cp[1] == '.')) {
 				equation[n].kind = CONSTANT;
 				equation[n].token.constant = -1.0;
 				equation[n].level = cur_level;
@@ -253,7 +270,7 @@
 			break;
 		default:
 			if (!isvarchar(*cp)) {
-				put_up_arrow((int) (cp - cp_start), _("Unsupported character encountered."));
+				put_up_arrow((int) (cp - cp_start), _("Unrecognized character."));
 				return(NULL);
 			}
 			if (!operand) {
@@ -263,16 +280,16 @@
 				equation[n].token.operatr = TIMES;
 				n++;
 			}
-			if (strncmp(cp, "inf", 3) == 0 && !isvarchar(cp[3])) {
+			if (strncmp(cp, INFINITY_NAME, strlen(INFINITY_NAME)) == 0
+			    && !isvarchar(cp[strlen(INFINITY_NAME)])) {
 				equation[n].kind = CONSTANT;
 				equation[n].token.constant = HUGE_VAL;	/* the infinity constant */
-				cp += 3;
+				cp += strlen(INFINITY_NAME);
 			} else {
 				equation[n].kind = VARIABLE;
 				cp1 = cp;
 				cp = parse_var(&equation[n].token.variable, cp);
 				if (cp == NULL) {
-					put_up_arrow((int) (cp1 - cp_start), _("Invalid variable."));
 					return(NULL);
 				}
 			}
@@ -292,9 +309,10 @@
 	}
 	if (*cp == '=')
 		cp++;
-	if (*np = n) {
-		handle_negate(equation, *np);
-		prior_sub(equation, *np);
+	*np = n;
+	if (n) {
+		handle_negate(equation, np);
+		prior_sub(equation, np);
 		organize(equation, np);
 	}
 	input_column += (cp - cp_start);
@@ -306,10 +324,13 @@
 }
 
 /*
- * Parse variable name pointed to by "cp".
- * Variable name is converted to Mathomatic format and stored in "*vp".
+ * Parse variable name string pointed to by "cp".
+ * The variable name is converted to Mathomatic format and stored in "*vp".
  *
- * Return new string position, or NULL on failure.
+ * If the variable is not special and never existed before, it is created.
+ *
+ * Return new string position if successful.
+ * Display error message and return NULL on failure.
  */
 char	*
 parse_var(vp, cp)
@@ -323,40 +344,32 @@
 	int	len;
 	int	(*strcmpfunc)();
 
+	*vp = V_NULL;
 	if (case_sensitive_flag) {
 		strcmpfunc = strcmp;
 	} else {
 		strcmpfunc = strcasecmp;
 	}
-	if (vp == NULL || cp == NULL) {
-		return(NULL);
-	}
 	if (!isvarchar(*cp)) {
+		error(_("Invalid variable."));
 		return(NULL);	/* variable name must start with a valid variable character */
 	}
-	cp1 = cp;
-	for (i = 0; *cp1;) {
+	for (cp1 = cp, i = 0; *cp1;) {
 		if (!isvarchar(*cp1)) {
 			break;
 		}
 		if (i >= MAX_VAR_LEN) {
+			error(_("Variable name too long."));
 			return(NULL);
 		}
 		buf[i++] = *cp1++;
 	}
 	buf[i] = '\0';
-	if ((*strcmpfunc)(buf, "sign") == 0) {
+	if ((*strcmpfunc)(buf, INFINITY_NAME) == 0) {
+		error(_("Invalid variable."));
+		return(NULL);
+	} else if ((*strcmpfunc)(buf, "sign") == 0) {
 		vtmp = SIGN;
-		cp += strlen(buf);
-	} else if ((*strcmpfunc)(buf, "integer") == 0) {
-		vtmp = V_INTEGER;
-		cp += strlen(buf);
-	} else if ((*strcmpfunc)(buf, "temp") == 0) {
-		vtmp = V_TEMP;
-		cp += strlen(buf);
-	} else if ((*strcmpfunc)(buf, "answer") == 0) {
-		vtmp = V_ANSWER;
-		cp += strlen(buf);
 	} else {
 		if (strncasecmp(cp, "i#", 2) == 0) {
 			*vp = IMAGINARY;
@@ -366,20 +379,33 @@
 			*vp = V_E;
 			return(cp + 2);
 		}
-		if ((*strcmpfunc)(buf, "pi") == 0) {
+		if (strncasecmp(cp, "pi#", 3) == 0) {
 			*vp = V_PI;
-			return(cp + 2);
+			return(cp + 3);
 		}
-		for (i = 0; *cp;) {
-			if (!isvarchar(*cp) && !(isascii(*cp) && isdigit(*cp))) {
+		for (cp1 = cp, i = 0; *cp1;) {
+			if (!isvarchar(*cp1) && !isdigit(*cp1)) {
 				break;
 			}
 			if (i >= MAX_VAR_LEN) {
+				error(_("Variable name too long."));
 				return(NULL);
 			}
-			buf[i++] = *cp++;
+			buf[i++] = *cp1++;
 		}
 		buf[i] = '\0';
+		if ((*strcmpfunc)(buf, "i") == 0) {
+			*vp = IMAGINARY;
+			return(cp1);
+		}
+		if ((*strcmpfunc)(buf, "e") == 0) {
+			*vp = V_E;
+			return(cp1);
+		}
+		if ((*strcmpfunc)(buf, "pi") == 0) {
+			*vp = V_PI;
+			return(cp1);
+		}
 		vtmp = 0;
 		for (i = 0; var_names[i]; i++) {
 			if ((*strcmpfunc)(buf, var_names[i]) == 0) {
@@ -398,17 +424,20 @@
 			len = strlen(buf) + 1;
 			var_names[i] = (char *) malloc(len);
 			if (var_names[i] == NULL) {
-				error(_("Out of memory!  (can't malloc())."));
+				error(_("Out of memory (can't malloc(3) variable name)."));
 				return(NULL);
 			}
 			blt(var_names[i], buf, len);
 			vtmp = i + VAR_OFFSET;
 			var_names[i+1] = NULL;
 		}
+		*vp = vtmp;
+		return cp1;
 	}
-	if (isascii(*cp) && isdigit(*cp)) {
-		j = strtol(cp, &cp, 10);
+	if (isdigit(*cp1)) {
+		j = strtol(cp1, &cp1, 10);
 		if (j < 0 || j > MAX_SUBSCRIPT) {
+			error(_("Maximum subscript exceeded in special variable name."));
 			return(NULL);
 		}
 		if (vtmp == SIGN) {
@@ -417,11 +446,12 @@
 		vtmp += ((long) (j + 1)) << VAR_SHIFT;
 	}
 	*vp = vtmp;
-	return cp;
+	return cp1;
 }
 
 /*
  * Set point_flag if pointing to the input error works for the passed string.
+ * Truncate string to the actual content.
  */
 set_error_level(cp)
 char	*cp;	/* input string */
@@ -429,21 +459,25 @@
 	char	*cp1;
 
 	point_flag = true;
-/* remove trailing newlines */
+/* handle comments */
+	for (cp1 = cp; *cp1; cp1++) {
+		if (*cp1 == ';') {
+			*cp1 = '\0';
+			break;
+		}
+	}
+/* remove trailing newlines, carriage returns, and spaces */
 	cp1 = &cp[strlen(cp)];
 	while (cp1 > cp) {
 		cp1--;
-		if (*cp1 == '\n' || *cp1 == '\r') {
+		if (*cp1 == '\n' || *cp1 == '\r' || isspace(*cp1)) {
 			*cp1 = '\0';
-		} else
+		} else {
 			break;
+		}
 	}
-/* handle comments */
+/* set point_flag to false if non-printable characters encountered */
 	for (cp1 = cp; *cp1; cp1++) {
-		if (*cp1 == ';') {
-			*cp1 = '\0';
-			break;
-		}
 		if (!isprint(*cp1)) {
 			point_flag = false;
 		}
@@ -481,10 +515,10 @@
 {
 	switch (v) {
 	case V_E:
-		*dp = E;
+		*dp = M_E;
 		return true;
 	case V_PI:
-		*dp = PI;
+		*dp = M_PI;
 		return true;
 	}
 	return false;
@@ -545,16 +579,16 @@
 /*
  * Handle and remove the special NEGATE operator.
  */
-handle_negate(equation, n)
+handle_negate(equation, np)
 token_type	*equation;
-int		n;
+int		*np;
 {
 	int	i;
 
-	for (i = 1; i < n; i += 2) {
+	for (i = 1; i < *np; i += 2) {
 		if (equation[i].token.operatr == NEGATE) {
 			equation[i].token.operatr = TIMES;
-			binary_parenthesize(equation, n, i);
+			binary_parenthesize(equation, *np, i);
 		}
 	}
 }
@@ -565,28 +599,28 @@
  *
  * organize() should be called after this.
  */
-prior_sub(equation, n)
+prior_sub(equation, np)
 token_type	*equation;
-int		n;
+int		*np;
 {
 	int	i;
 
-	for (i = 1; i < n; i += 2) {
+	for (i = 1; i < *np; i += 2) {
 		if (equation[i].token.operatr == FACTORIAL) {
-			binary_parenthesize(equation, n, i);
+			binary_parenthesize(equation, *np, i);
 		}
 	}
-	for (i = 1; i < n; i += 2) {
+	for (i = 1; i < *np; i += 2) {
 		if (equation[i].token.operatr == POWER) {
-			binary_parenthesize(equation, n, i);
+			binary_parenthesize(equation, *np, i);
 		}
 	}
-	for (i = 1; i < n; i += 2) {
+	for (i = 1; i < *np; i += 2) {
 		switch (equation[i].token.operatr) {
 		case TIMES:
 		case DIVIDE:
 		case MODULUS:
-			binary_parenthesize(equation, n, i);
+			binary_parenthesize(equation, *np, i);
 			break;
 		}
 	}
@@ -599,25 +633,11 @@
 char	*cp;
 {
 	for (; *cp; cp++) {
-		if (isascii(*cp) && isupper(*cp))
+		if (isupper(*cp))
 			*cp = tolower(*cp);
 	}
 }
 
-/*
- * Return true if character is a valid starting variable character.
- */
-int
-isvarchar(ch)
-int	ch;
-{
-	if (ch == '_' || ch == '\\')
-		return true;
-	if (isascii(ch) && isalpha(ch))
-		return true;
-	return false;
-}
-
 #ifndef	my_strlcpy
 /*
  * A very efficient strlcpy().

Modified: branches/vendor/mathomatic/poly.c
===================================================================
--- branches/vendor/mathomatic/poly.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/poly.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,22 +1,24 @@
 /*
- * Algebraic manipulator simplifying and polynomial routines.
+ * Mathomatic simplifying and polynomial routines.
  * Includes polynomial and smart division, polynomial factoring, etc.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * The polynomial division and GCD routines here are not recursive, due to static
+ * storage areas.  This limits the polynomial GCD to univariate operation.
+ *
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
 
 #define	REMAINDER_IS_ZERO()	(n_trhs == 1 && trhs[0].kind == CONSTANT && trhs[0].token.constant == 0.0)
 
-/* For smart_div() and poly_div(): */
-token_type	divisor[DIVISOR_SIZE];
+/* These are a non-standard size and must only be used for temp storage: */
+token_type	divisor[DIVISOR_SIZE];		/* static data areas for polynomial and smart division */
 int		n_divisor;
 token_type	quotient[DIVISOR_SIZE];
 int		n_quotient;
-/* These are a non-standard size and must only be used for temp storage. */
-token_type	gcd_divisor[DIVISOR_SIZE];
-int		len_d;
+token_type	gcd_divisor[DIVISOR_SIZE];	/* static data area for polynomial GCD routine */
+int		len_d;				/* length of expression in gcd_divisor[] */
 
 static int	do_gcd();
 static int	pf_recurse();
@@ -25,6 +27,7 @@
 static int	polydiv_recurse();
 static int	pdiv_recurse();
 static int	poly_div_sub();
+static void	save_factors();
 
 /*
  * Compare function for qsort(3).
@@ -37,14 +40,14 @@
 }
 
 /*
- * Return true if passed expression is strictly a single polynomial term in v.
+ * Return true if passed expression is strictly a single polynomial term in variable v.
  */
 static inline int
 poly_in_v_sub(equation, n, v, allow_divides)
-token_type	*equation;
-int		n;
-long		v;
-int		allow_divides;
+token_type	*equation;	/* expression pointer */
+int		n;		/* expression length */
+long		v;		/* variable */
+int		allow_divides;	/* allow division by variable */
 {
 	int	i, k;
 	int	level, vlevel;
@@ -90,9 +93,8 @@
 }
 
 /*
- * Return true if passed expression is a polynomial in
- * variable v.  The exponents may be anything, as long
- * as they don't contain the variable.
+ * Return true if passed expression is a polynomial in variable v.
+ * The exponents may be anything, as long as they don't contain the variable.
  */
 int
 poly_in_v(equation, n, v, allow_divides)
@@ -122,12 +124,12 @@
  * Factors repeated factor polynomials (like (x+1)^5)
  * and symbolic factor polynomials (like (x+a)*(x+b)).
  *
- * Return true if equation side was modified.
+ * Return true if equation side was modified (factored).
  */
 int
 poly_factor(equation, np)
-token_type	*equation;
-int		*np;
+token_type	*equation;	/* pointer to the beginning of equation side */
+int		*np;		/* pointer to length of equation side */
 {
 	return pf_recurse(equation, np, 0, 1);
 }
@@ -170,9 +172,10 @@
 
 /*
  * Polynomial factoring subroutine.
- * It can't factor everything,
- * but it usually can factor polynomials
+ * It can't factor everything, but it usually can factor polynomials
  * if it will make the expression size smaller.
+ *
+ * Return true if expression was modified (factored).
  */
 static int
 pf_sub(equation, np, loc, len, level)
@@ -180,10 +183,10 @@
 int		*np, loc, len, level;
 {
 	token_type	*p1;
-	int		modified = false, single_modified = false;
+	int		modified = false, symbolic_modified = false;
 	int		i, j, k;
 	long		v = 0, v1, last_v;
-	int		len_first;
+	int		len_first = 0;
 	int		loc1;
 	int		loc2, len2 = 0;
 	int		loct, lent;
@@ -195,29 +198,29 @@
 	double		d;
 
 	debug_string(3, "Entering pf_sub().");
-	loc1 = loc;
+	loc2 = loc1 = loc;
 	find_greatest_power(&equation[loc1], len, &v, &d, &j, &k, &div_flag);
 	if (v == 0)
 		return false;
 	blt(save_save, jmp_save, sizeof(jmp_save));
-	if ((i = setjmp(jmp_save)) != 0) {
+	if (setjmp(jmp_save) != 0) {
 		blt(jmp_save, save_save, sizeof(jmp_save));
-		if (i == 13) {
-			longjmp(jmp_save, i);
-		}
-		return(modified || single_modified);
+		return(modified || symbolic_modified);
 	}
-/* First factor polynomials with repeated factors. */
+/* First factor polynomials with repeated factors */
+/* using poly_gcd(polynomial, v * differentiate(polynomial, v)) to discover the factors: */
 	for (count = 1;; count++) {
 		blt(trhs, &equation[loc1], len * sizeof(token_type));
 		n_trhs = len;
 		uf_simp(trhs, &n_trhs);
-		if (level1_plus(trhs, n_trhs) < 2)
+		if (level1_plus_count(trhs, n_trhs) < 2) {
+/* must be at least 2 level 1 additive operators to be factorable */
 			goto skip_factor;
+		}
+/* create a variable list with counts of the number of times each variable occurs: */
 		last_v = 0;
 		for (vc = 0; vc < ARR_CNT(va); vc++) {
-			v1 = -1;
-			for (i = 0; i < n_trhs; i += 2) {
+			for (i = 0, cnt = 0, v1 = -1; i < n_trhs; i += 2) {
 				if (trhs[i].kind == VARIABLE && trhs[i].token.variable > last_v) {
 					if (v1 == -1 || trhs[i].token.variable < v1) {
 						v1 = trhs[i].token.variable;
@@ -234,6 +237,7 @@
 			va[vc].count = cnt;
 		}
 		side_debug(3, &equation[loc1], len);
+/* find a valid polynomial base variable "v": */
 		cnt = -1;
 		if (v) {
 			if (!poly_in_v(trhs, n_trhs, v, true)) {
@@ -282,7 +286,7 @@
 		uf_simp(tlhs, &n_tlhs);
 		if (poly_gcd(&equation[loc1], len, tlhs, n_tlhs, v) == 0)
 			break;
-		if (!level1_plus(tlhs, n_tlhs))
+		if (!level1_plus_count(tlhs, n_tlhs))
 			break;
 		save_factors(equation, np, loc1, len, level);
 		loc1 += n_tlhs + 1;
@@ -299,7 +303,7 @@
 		}
 		modified = true;
 	}
-/* Now try and factor polynomials with symbolic factors. */
+/* Now factor polynomials with symbolic factors by grouping: */
 	if (!modified) {
 		last_v = 0;
 next_v:
@@ -320,12 +324,17 @@
 				break;
 			}
 			last_v = v;
+			/* make sure there is more than one "v" raised to the highest power: */
 			if (find_greatest_power(trhs, n_trhs, &v, &d, &j, &k, &div_flag) <= 1) {
 				continue;
 			}
 			blt(tlhs, trhs, n_trhs * sizeof(token_type));
 			n_tlhs = n_trhs;
-			factorv(tlhs, &n_tlhs, v);
+			/* do the grouping: */
+			while (factor_plus(tlhs, &n_tlhs, v, 0.0)) {
+				simp_loop(tlhs, &n_tlhs);
+			}
+			/* extract the highest power group: */
 			if (find_greatest_power(tlhs, n_tlhs, &v, &d, &j, &k, &div_flag) != 1) {
 				continue;
 			}
@@ -340,7 +349,7 @@
 #endif
 			if (poly_gcd(&equation[loc1], len, tlhs, n_tlhs, 0L) == 0)
 				goto next_v;
-			if (!level1_plus(tlhs, n_tlhs))
+			if (!level1_plus_count(tlhs, n_tlhs))
 				goto next_v;
 			debug_string(1, "Symbolic polynomial factored.");
 			save_factors(equation, np, loc1, len, level);
@@ -348,7 +357,7 @@
 			len = n_trhs;
 			len_first = n_tlhs;
 			loc2 = loc1;
-			single_modified = true;
+			symbolic_modified = true;
 			break;
 		}
 	}
@@ -377,9 +386,10 @@
 			save_factors(equation, np, loc, len_first, level);
 		}
 	}
-	return(modified || single_modified);
+	return(modified || symbolic_modified);
 }
 
+static void
 save_factors(equation, np, loc1, len, level)
 token_type	*equation;
 int		*np, loc1, len, level;
@@ -413,8 +423,7 @@
 remove_factors()
 {
 	int	i, j, k;
-	int	plus_flag = false;
-	int	divide_flag = false;
+	int	plus_flag = false, divide_flag = false;
 	int	op;
 
 	debug_string(3, "Entering remove_factors() with:");
@@ -474,9 +483,9 @@
 
 /*
  * This is the Euclidean GCD algorithm applied to polynomials.
- * It needs to be made multi-variate.
+ * It needs to be made multivariate.
  *
- * Return number of iterations, if successful.
+ * Return the number of iterations (divisions), if successful.
  * Return 0 on failure.
  */
 static int
@@ -578,6 +587,7 @@
 int		llen, slen;
 long		v;
 {
+	jmp_buf		save_save;
 	int		count;
 
 	debug_string(3, "Entering poly2_gcd():");
@@ -589,9 +599,15 @@
 		return 0;
 	blt(tlhs, smaller, slen * sizeof(token_type));
 	n_tlhs = slen;
-	uf_simp_no_repeat(tlhs, &n_tlhs);
-	if (!level1_plus(tlhs, n_tlhs))
+	blt(save_save, jmp_save, sizeof(jmp_save));
+	if (setjmp(jmp_save) != 0) {
+		blt(jmp_save, save_save, sizeof(jmp_save));
 		return 0;
+	}
+	uf_simp(tlhs, &n_tlhs);
+	blt(jmp_save, save_save, sizeof(jmp_save));
+	if (!level1_plus_count(tlhs, n_tlhs))
+		return 0;
 	if (n_tlhs > ARR_CNT(gcd_divisor))
 		return 0;
 	blt(gcd_divisor, tlhs, n_tlhs * sizeof(token_type));
@@ -600,7 +616,7 @@
 	if (count == 0)
 		return 0;
 	if (count > 1) {
-		if (!level1_plus(gcd_divisor, len_d))
+		if (!level1_plus_count(gcd_divisor, len_d))
 			return 0;
 		if (poly_div(smaller, slen, gcd_divisor, len_d, &v) != 2) {
 			debug_string(0, "Polynomial GCD found, but smaller divide failed.");
@@ -624,8 +640,7 @@
 		n_trhs = 1;
 		trhs[0] = one_token;
 	}
-	uf_simp(tlhs, &n_tlhs);
-	uf_simp(trhs, &n_trhs);
+	debug_string(3, "poly2_gcd() successful.");
 	return count;
 }
 
@@ -640,16 +655,12 @@
 token_type	*equation;	/* expression pointer */
 int		n;		/* length of expression */
 {
-	int	i2;
-	double	d;
+	int	i;
 
-	for (i2 = 0; i2 < n; i2++) {
-		if ((equation[i2].kind == OPERATOR
-		    && equation[i2].token.operatr == DIVIDE)
-		    || (equation[i2].kind == CONSTANT
-		    && fmod(equation[i2].token.constant, 1.0))
-		    || (equation[i2].kind == VARIABLE
-		    && var_is_const(equation[i2].token.variable, &d))) {
+	for (i = 0; i < n; i++) {
+		if ((equation[i].kind == OPERATOR && equation[i].token.operatr == DIVIDE)
+		    || (equation[i].kind == CONSTANT && fmod(equation[i].token.constant, 1.0))
+		    || (equation[i].kind == VARIABLE && equation[i].token.variable <= IMAGINARY)) {
 			return false;
 		}
 	}
@@ -678,8 +689,7 @@
 	int	modified = false;
 	int	i, j, k;
 	int	i1, i2, i3, i4, i5;
-	int	op;
-	int	last_op2;
+	int	op, last_op2;
 	int	len1, len2, len3;
 	long	v;
 	int	diff_sign;
@@ -704,9 +714,7 @@
 			}
 			len1 = k - (i + 1);
 			last_op2 = 0;
-			for (j = loc;; j++) {
-				if (j >= *np || equation[j].level < level)
-					break;
+			for (j = loc; j < *np && equation[j].level >= level; j++) {
 				if (equation[j].level == level && equation[j].kind == OPERATOR) {
 					last_op2 = equation[j].token.operatr;
 					continue;
@@ -716,9 +724,7 @@
 				}
 				last_op2 = MODULUS;
 				op = 0;
-				for (k = j + 1;; k += 2) {
-					if (k >= *np || equation[k].level <= level)
-						break;
+				for (i1 = k = j + 1; k < *np && equation[k].level > level; k += 2) {
 					if (equation[k].level == (level + 1)) {
 						op = equation[k].token.operatr;
 						i1 = k;
@@ -808,19 +814,16 @@
 				v = 0;
 				if (poly_div(&equation[j], len2, &equation[i+1], len1, &v)) {
 					if (is_integer_expr(tlhs, n_tlhs)) {
+						if ((*np + (n_trhs - len2)) > n_tokens)
+							error_huge();
 #if	!SILENT
-						for (k = 0; k < n_tlhs; k += 2) {
-							if (tlhs[k].kind == VARIABLE) {
-								printf(_("Modulus simplification made some variables integer only.\n"));
-								break;
-							}
+						if (var_count(tlhs, n_tlhs)) {
+							printf(_("Modulus simplification made some variables integer only.\n"));
 						}
 #endif
 						for (k = 0; k < n_trhs; k++)
 							trhs[k].level += level;
-						if ((*np + (n_trhs - len2)) > n_tokens)
-							error_huge();
-						blt(&equation[j+n_trhs], &equation[j+len2], (*np - (j + len2)) * sizeof(*equation));
+						blt(&equation[j+n_trhs], &equation[j+len2], (*np - (j + len2)) * sizeof(token_type));
 						*np += n_trhs - len2;
 						blt(&equation[j], trhs, n_trhs * sizeof(token_type));
 						return true;
@@ -867,6 +870,7 @@
 		}
 		i++;
 	}
+start:
 	for (i = loc + 1; i < *np && equation[i].level >= level; i += 2) {
 		if (equation[i].level == level && equation[i].token.operatr == DIVIDE) {
 			for (k = i + 2;; k += 2) {
@@ -875,9 +879,7 @@
 			}
 			len1 = k - (i + 1);
 			last_op2 = 0;
-			for (j = loc;; j++) {
-				if (j >= *np || equation[j].level < level)
-					break;
+			for (j = loc; j < *np && equation[j].level >= level; j++) {
 				if (equation[j].level == level && equation[j].kind == OPERATOR) {
 					last_op2 = equation[j].token.operatr;
 					continue;
@@ -900,16 +902,17 @@
 					if (((*np + (n_trhs - len2)) > n_tokens)
 					    || ((*np + (n_trhs - len2) + (n_tlhs - len1)) > n_tokens))
 						error_huge();
-					blt(&equation[j+n_trhs], &equation[j+len2], (*np - (j + len2)) * sizeof(*equation));
+					blt(&equation[j+n_trhs], &equation[j+len2], (*np - (j + len2)) * sizeof(token_type));
 					*np += n_trhs - len2;
 					if (i > j)
 						i += n_trhs - len2;
 					blt(&equation[j], trhs, n_trhs * sizeof(token_type));
-					blt(&equation[i+n_tlhs+1], &equation[i+1+len1], (*np - (i + 1 + len1)) * sizeof(*equation));
+					blt(&equation[i+n_tlhs+1], &equation[i+1+len1], (*np - (i + 1 + len1)) * sizeof(token_type));
 					*np += n_tlhs - len1;
-					blt(&equation[i+1], tlhs, n_tlhs * sizeof(*equation));
-					debug_string(0, _("Found polynomial Greatest Common Divisor.  Division simplified."));
-					return true;
+					blt(&equation[i+1], tlhs, n_tlhs * sizeof(token_type));
+					debug_string(0, _("Division simplified with polynomial GCD."));
+					modified = true;
+					goto start;
 				}
 				if (poly2_gcd(&equation[j], len2, &equation[i+1], len1, 0L)) {
 					k = j - 1;
@@ -929,6 +932,7 @@
 /*
  * This routine is a division simplifier for equation sides.
  * Check for divides and do polynomial and smart division.
+ *
  * Return true if expression was simplified.
  */
 int
@@ -955,12 +959,11 @@
 {
 	int	modified = false;
 	int	i, j, k;
-	int	op, op2;
-	int	last_op2;
+	int	op, op2, last_op2;
 	int	len1, len2, real_len1;
 	long	v;
 	int	rv;
-	int	flag, power_flag;
+	int	flag, power_flag, zero_remainder;
 
 	for (i = loc + 1; i < *np && equation[i].level >= level; i += 2) {
 		if (equation[i].level == level && equation[i].token.operatr == DIVIDE) {
@@ -968,11 +971,9 @@
 				if (k >= *np || equation[k].level <= level)
 					break;
 			}
-			real_len1 = k - (i + 1);
+			len1 = real_len1 = k - (i + 1);
 			last_op2 = 0;
-			for (j = loc;; j++) {
-				if (j >= *np || equation[j].level < level)
-					break;
+			for (j = loc; j < *np && equation[j].level >= level; j++) {
 				if (equation[j].level == level && equation[j].kind == OPERATOR) {
 					last_op2 = equation[j].token.operatr;
 					continue;
@@ -982,11 +983,10 @@
 				}
 				last_op2 = DIVIDE;
 				op = 0;
-				for (k = j + 1;; k += 2) {
-					if (k >= *np || equation[k].level <= level)
-						break;
-					if (equation[k].level == level + 1)
+				for (k = j + 1; k < *np && equation[k].level > level; k += 2) {
+					if (equation[k].level == (level + 1)) {
 						op = equation[k].token.operatr;
+					}
 				}
 				if (op != PLUS && op != MINUS) {
 					continue;
@@ -996,9 +996,7 @@
 				power_flag = false;
 				op = 0;
 				op2 = 0;
-				for (k = i + 2;; k += 2) {
-					if (k >= *np || equation[k].level <= level)
-						break;
+				for (k = i + 2; k < *np && equation[k].level > level; k += 2) {
 					if (equation[k].level == level + 3) {
 						switch (equation[k].token.operatr) {
 						case PLUS:
@@ -1009,8 +1007,7 @@
 						op = equation[k].token.operatr;
 					} else if (equation[k].level == level + 1) {
 						if (equation[k].token.operatr == POWER
-						    && (op == PLUS || op == MINUS
-						    || (op == TIMES && op2 == PLUS))) {
+						    && (op == PLUS || op == MINUS || (op == TIMES && op2 == PLUS))) {
 							power_flag = true;
 							len1 = k - (i + 1);
 						}
@@ -1027,10 +1024,13 @@
 				} else {
 					rv = smart_div(&equation[j], len2, &equation[i+1], len1);
 				}
-				if (power_flag && !(rv > 0 && REMAINDER_IS_ZERO())) {
+				zero_remainder = (rv > 0 && REMAINDER_IS_ZERO());
+				if (power_flag && !zero_remainder) {
 					rv = 0;
 				}
-				if (rv > 0 && (n_tlhs + 2 + n_trhs + len1) <= n_tokens) {
+				if (rv > 0) {
+					if ((n_tlhs + 2 + n_trhs + len1) > n_tokens)
+						error_huge();
 					for (k = 0; k < n_tlhs; k++)
 						tlhs[k].level++;
 					tlhs[n_tlhs].level = 1;
@@ -1060,16 +1060,11 @@
 						k = (var_count(tlhs, n_tlhs) <= (var_count(&equation[j], len2) + var_count(&equation[i+1], len1)));
 					}
 					if (k) {
-						if (power_flag) {
-							if ((*np - len2 + n_tlhs + 2) > n_tokens)
-								error_huge();
-						} else {
-							if ((*np - (len1 + 1 + len2) + n_tlhs) > n_tokens)
-								error_huge();
-						}
 						for (k = 0; k < n_tlhs; k++)
 							tlhs[k].level += level;
 						if (power_flag) {
+							if ((*np - len2 + n_tlhs + 2) > n_tokens)
+								error_huge();
 							for (k = i + 2 + len1; k <= i + real_len1; k++) {
 								equation[k].level++;
 							}
@@ -1086,6 +1081,8 @@
 								j += 2;
 							}
 						} else {
+							if ((*np - (len1 + 1 + len2) + n_tlhs) > n_tokens)
+								error_huge();
 							blt(&equation[i], &equation[i+1+len1], (*np - (i + 1 + len1)) * sizeof(token_type));
 							*np -= len1 + 1;
 							if (i < j) {
@@ -1145,19 +1142,16 @@
 int		len2;		/* length of divisor */
 long		*vp;		/* variable pointer to base variable */
 {
-	int		i, j;
+	int		j;
 	int		old_partial;
 	jmp_buf		save_save;
 
 	old_partial = partial_flag;
 	partial_flag = false;	/* We want full unfactoring. */
 	blt(save_save, jmp_save, sizeof(jmp_save));
-	if ((i = setjmp(jmp_save)) != 0) {
+	if (setjmp(jmp_save) != 0) {
 		blt(jmp_save, save_save, sizeof(jmp_save));
 		partial_flag = old_partial;
-		if (i == 13) {
-			longjmp(jmp_save, i);
-		}
 		return false;
 	}
 	j = poly_div_sub(d1, len1, d2, len2, vp);
@@ -1364,12 +1358,12 @@
 {
 	int		i, j, k;
 	int		t1, len_t1;
-	int		t2, len_t2 = 0;
+	int		t2 = 0, len_t2 = 0;
 	int		sign;
 	int		old_n_quotient;
 	int		trhs_size;
-	int		term_size, term_count;
-	int		term_pos, skip_terms[100];
+	int		term_size = 0, term_count;
+	int		term_pos = 0, skip_terms[100];
 	int		skip_count;
 	token_type	*qp;
 	int		q_size;
@@ -1678,10 +1672,8 @@
 
 	last_v = 0;
 	for (vc = 0; vc < ARR_CNT(va); vc++) {
-		v1 = -1;
-		for (i = 0; i < n1; i += 2) {
-			if (p1[i].kind == VARIABLE
-			    && p1[i].token.variable > last_v) {
+		for (i = 0, cnt = 0, v1 = -1; i < n1; i += 2) {
+			if (p1[i].kind == VARIABLE && p1[i].token.variable > last_v) {
 				if (v1 == -1 || p1[i].token.variable < v1) {
 					v1 = p1[i].token.variable;
 					cnt = 1;
@@ -1729,7 +1721,7 @@
 {
 	int	i, j, k;
 	int	divide_flag = false;
-	int	level, div_level;
+	int	level, div_level = 0;
 	double	d, sub_count, sub_sum;
 
 	for (i = 0; i < VALUE_CNT; i++)
@@ -1808,12 +1800,10 @@
 				/* for example: for x^5 it is false, for 1/x^5 it is true */
 				/* if equal to 3, ignore */
 {
-	int		i, j, k;
-	int		ii;
+	int		i, j, k, ii;
 	double		d;
 	int		flag, divide_flag = false;
-	int		div_level;
-	int		level;
+	int		level, div_level = 0;
 	long		v = 0;
 	int		was_power = false;
 	double		last_va[VALUE_CNT];

Modified: branches/vendor/mathomatic/primes/README.txt
===================================================================
--- branches/vendor/mathomatic/primes/README.txt	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/primes/README.txt	2007-06-24 11:58:26 UTC (rev 1806)
@@ -7,10 +7,14 @@
 
 This will install:
 
-	matho-pascal - display Pascal's Triangle
+	matho-pascal - display Pascal's triangle
 	matho-primes - generate consecutive prime numbers
+	matho-sumsq - display minimum sum of the squares
 
-All work for up to 19 digits.  Man pages are included.
+Man pages are included.  These C programs are C++ compatible.
 
-		George Gesslein II
-		www.mathomatic.org
+The Python program "primorial" is included for calculating large primorials
+from "matho-primes".  To generate a list of all unique primorials from 2 to 97,
+type the following:
+
+	./primorial `matho-primes 2 97`

Added: branches/vendor/mathomatic/primes/lsqrt.c

Modified: branches/vendor/mathomatic/primes/makefile
===================================================================
--- branches/vendor/mathomatic/primes/makefile	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/primes/makefile	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,4 +1,4 @@
-# Makefile for compiling and installing the Mathomatic Prime Number Tools
+# Makefile for compiling and installing the Mathomatic Prime Number Tools under Linux and Unix.
 
 CFLAGS		+= -O2 -Wall
 LDFLAGS		+= -s -lm
@@ -7,17 +7,17 @@
 bindir		?= $(prefix)/bin
 mandir		?= $(prefix)/man
 
-TARGETS		= matho-primes matho-pascal
-MANPAGES1	= matho-primes.1 matho-pascal.1
+TARGETS		= matho-primes matho-pascal matho-sumsq
+MANPAGES1	= matho-primes.1 matho-pascal.1 matho-sumsq.1
 
 all: $(TARGETS)
 	@echo Make completed.
 
-check: test
+matho-sumsq: matho-sumsq.o lsqrt.o
 
-test: $(TARGETS)
-	time ./matho-primes 1000000000000000000 1000000000000600000 twin >test.out && diff twins.out test.out
-	rm test.out
+check test: $(TARGETS)
+	time ./matho-primes 1000000000000000000 1000000000000300000 twin >test.out && diff twins.out test.out
+	@rm test.out
 	@echo Test passed.
 
 install:

Modified: branches/vendor/mathomatic/primes/matho-pascal.1
===================================================================
--- branches/vendor/mathomatic/primes/matho-pascal.1	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/primes/matho-pascal.1	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,23 +1,32 @@
 .TH matho-pascal 1
 
 .SH NAME
-matho-pascal \- display Pascal's Triangle
+matho-pascal \- display Pascal's triangle
 
 .SH SYNOPSIS
 .B matho-pascal
 [number-of-lines]
 
 .SH DESCRIPTION
-This program calculates up to 100 lines of Pascal's Triangle
-and dumps it to standard output.
+This utility is part of the
+.B mathomatic(1)
+package and calculates up to 100 lines of Pascal's triangle,
+dumping them to standard output.
 The default is to center one screen full.
 
-Every number inside Pascal's Triangle is the sum of the two numbers
+Every number inside Pascal's triangle is the sum of the two numbers
 immediately above it.
-Pascal's Triangle is the same as binomial coefficients.
 
+Each line of Pascal's triangle is the same as binomial coefficients
+for a given power.
+
+The sum of all numbers in each line of Pascal's triangle is a power of 2.
+
 .SH SEE ALSO
-mathomatic(1), matho-primes(1)
+mathomatic(1), matho-primes(1), matho-sumsq(1)
 
+.SH REPORTING BUGS
+Report bugs to <gesslein at panix.com>.
+
 .SH AUTHOR
-George Gesslein II
+George Gesslein II <gesslein at panix.com>

Modified: branches/vendor/mathomatic/primes/matho-pascal.c
===================================================================
--- branches/vendor/mathomatic/primes/matho-pascal.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/primes/matho-pascal.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,23 +1,7 @@
 /*
- * Calculate and display Pascal's Triangle.
+ * Calculate and display Pascal's triangle.
  *
  * Copyright (C) 2005 George Gesslein II.
- *
- * This program 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 (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Usage: matho-pascal [number-of-lines]
  */
 
 #include <stdio.h>
@@ -58,16 +42,17 @@
 	struct winsize	ws;
 
         prog_name = strdup(basename(argv[0]));
+
 	ws.ws_col = 0;
 	ws.ws_row = 0;
 	ioctl(1, TIOCGWINSZ, &ws);
-	if (ws.ws_col) {
+	if (ws.ws_col > 0) {
 		screen_columns = ws.ws_col;
 	}
 	if (screen_columns >= sizeof(line_buf)) {
-		fprintf(stderr, "%s: Screen too wide!\n", prog_name);
-		exit(1);
+		screen_columns = sizeof(line_buf) - 1;
 	}
+
 	switch (argc) {
 	case 0:
 	case 1:
@@ -147,8 +132,8 @@
 
 /*
  * Create a line of output in line_buf[] for centering mode.
- * Return length if successful,
- * otherwise return 0.
+
+ * Return length if successful, otherwise return 0.
  */
 int
 center_buf(int line_number, int cell_size)
@@ -182,6 +167,6 @@
 usage()
 {
 	fprintf(stderr, "Usage: %s [number-of-lines]\n\n", prog_name);
-	fprintf(stderr, "Display up to %d lines of Pascal's Triangle.\n", MAX_LINES);
+	fprintf(stderr, "Display up to %d lines of Pascal's triangle.\n", MAX_LINES);
 	exit(1);
 }

Modified: branches/vendor/mathomatic/primes/matho-primes.1
===================================================================
--- branches/vendor/mathomatic/primes/matho-primes.1	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/primes/matho-primes.1	2007-06-24 11:58:26 UTC (rev 1806)
@@ -8,26 +8,35 @@
 [start [stop]] ["twin"] ["pal" [base]]
 
 .SH DESCRIPTION
-This program quickly computes any number of consecutive prime numbers using a memory efficient
-sieve algorithm and dumps them to standard output.
+This utility is part of the
+.B mathomatic(1)
+package and quickly computes any number of consecutive prime numbers using a memory efficient
+sieve of Eratosthenes algorithm, dumping them to standard output.
 Generates up to 19 digit primes.
-They are displayed one prime per line in ascending order.
+They are displayed one prime per line in ascending order,
+unless the "twin" option is specified,
+which displays two primes per line.
 
 A range may be
 specified on the command line, otherwise the starting number and
 the number of primes to output is prompted for.
 The range is "start" to "stop", inclusive, and "stop" must
-be greater than "start".
+be greater than or equal to "start".
 
 If "twin" is specified on the command line, only twin primes will be displayed.
 Twin primes are two primes that differ in value by 2.
-They are displayed together on the same line.
+Each twin pair is displayed together on the same line separated by a space character.
 
 If "pal" is specified at the end of the command line, only palindromic primes are displayed.
-The palindromic base may be specified, the default is base 10.
+Palindromes are symmetrical, they read exactly the same forward and backward.
+The palindromic number base may be specified, the default is base 10.
+The base can be any integer greater than 1.
 
 .SH SEE ALSO
-mathomatic(1), matho-pascal(1)
+mathomatic(1), matho-pascal(1), matho-sumsq(1)
 
+.SH REPORTING BUGS
+Report bugs to <gesslein at panix.com>.
+
 .SH AUTHOR
-George Gesslein II
+George Gesslein II <gesslein at panix.com>

Modified: branches/vendor/mathomatic/primes/matho-primes.c
===================================================================
--- branches/vendor/mathomatic/primes/matho-primes.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/primes/matho-primes.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,29 +1,29 @@
 /*
- * Generate consecutive prime numbers using a modified sieve algorithm
- * that doesn't use much memory by using a windowing sieve buffer.
- * Works with up to 19 digit numbers.
+ * Generate consecutive prime numbers using a modified sieve of Eratosthenes
+ * algorithm that doesn't use much memory by using a windowing sieve buffer.
  *
- * Copyright (C) 2006 George Gesslein II.
- *
- * This program 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 (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Usage: matho-primes [start [stop]] ["pal" [base]]
- *
- * If "pal" is specified, display only palindromic primes of base "base",
- * default base is 10.
- *
+ * Copyright (C) 2007 George Gesslein II.
+ */
+
+/*
+Usage: matho-primes [start [stop]] ["twin"] ["pal" [base]]
+
+Generate consecutive prime numbers up to 19 digits.
+If "twin" is specified, output only twin primes.
+If "pal" is specified, output only palindromic primes.
+The palindromic base may be specified, the default is base 10.
+
+or
+
+Usage: matho-primes [options] [start [stop]]
+
+Generate consecutive prime numbers up to 19 digits.
+Options:
+  -t               Output only twin primes.
+  -p base          Output only palindromic primes.
+ */
+
+/*
  * Changes:
  *
  * 11/22/05 - converted everything to long doubles.
@@ -56,21 +56,22 @@
 
 #define	MAX_K_INTEGER	1.0e19L		/* 19 digits for long doubles */
 
-/* memory usage in bytes; can be set to any size; the larger, the faster */
-#define BUFFER_SIZE	5000000
-#if	BUFFER_SIZE >= (INT_MAX / 2)
-#error	BUFFER_SIZE too big!
+/* Maximum memory usage in bytes; can be set to any size; the larger, the faster: */
+#define BUFFER_SIZE	2000000
+#if	BUFFER_SIZE >= (INT_MAX / 2) || BUFFER_SIZE <= 0
+#error	"BUFFER_SIZE too large."
 #endif
 
 void	generate_primes(void);
 int	test_pal(long double d, long double base);
 void	usage(void);
+void	usage2(void);
 int	get_long_double_int(char *cp, long double *dp);
 
 long double strtold(const char *nptr, char **endptr);
 
 long double start_value, number, end_value;
-long double sq[] = {			/* Additive array that skips over multiples of 2, 3, 5, and 7. */
+long double skip_multiples[] = {	/* Additive array that skips over multiples of 2, 3, 5, and 7. */
 	10, 2, 4, 2, 4, 6, 2, 6,
 	 4, 2, 4, 6, 6, 2, 6, 4,
 	 2, 6, 4, 6, 8, 4, 2, 4,
@@ -114,11 +115,11 @@
 		case 'p':
 			pal_flag = true;
 			if (!get_long_double_int(optarg, &pal_base)) {
-				usage();
+				usage2();
 			}
 			break;
 		default:
-			usage();
+			usage2();
 		}
 	}
 	if (argc > optind) {
@@ -169,8 +170,8 @@
 	if (argc > optind) {
 		usage();
 	}
-	if (pal_base < 2 || pal_base > 256) {
-		fprintf(stderr, "Palindromic base range is 2 to 256.\n");
+	if (pal_base < 2 || pal_base >= INT_MAX) {
+		fprintf(stderr, "Palindromic base must be >= 2.\n");
 		usage();
 	}
 	if (start_value < 0.0) {
@@ -207,7 +208,7 @@
 			}
 		}
 	}
-	buffer_size = min(BUFFER_SIZE, (end_value - start_value) + 1.0L);
+	buffer_size = (int) min(BUFFER_SIZE, (end_value - start_value) + 1.0L);
 	prime = (char *) malloc(buffer_size);
 	if (prime == NULL) {
 		fprintf(stderr, "%s: Not enough memory.\n", prog_name);
@@ -266,8 +267,8 @@
 		elim_factor(7.0L);
 		ii = 1.0;
 		for (;;) {
-			for (j = 0; j < ARR_CNT(sq); j++) {
-				ii += sq[j];
+			for (j = 0; j < ARR_CNT(skip_multiples); j++) {
+				ii += skip_multiples[j];
 				elim_factor(ii);
 			}
 			if (ii > vv)
@@ -300,9 +301,9 @@
 }
 
 /*
- * Parse an ASCII number in the string pointed to by "cp" and
- * return true with a floating point long double value
- * in "*dp" if a valid integer.
+ * Parse a space or null terminated ASCII number in the string pointed to by "cp" and
+ * return true with a floating point long double value in "*dp" if a valid integer,
+ * otherwise display an error message and return false.
  */
 int
 get_long_double_int(char *cp, long double *dp)
@@ -320,6 +321,9 @@
 	case '\n':
 		break;
 	default:
+		if (isspace(*cp1)) {
+			break;
+		}
 		fprintf(stderr, "Invalid number.\n");
 		return false;
 	}
@@ -351,10 +355,6 @@
 		digits[i] = (int) fmodl(d, base);
 		d /= base;
 	}
-	if (i <= 1) {
-		/* less than 2 digits */
-		return false;
-	}
 	/* compare the array of digits[] end to end */
 	for (j = 0, i--; j < i; j++, i--) {
 		if (digits[i] != digits[j])
@@ -368,8 +368,19 @@
 {
 	fprintf(stderr, "\nUsage: %s [start [stop]] [\"twin\"] [\"pal\" [base]]\n\n", prog_name);
 	fprintf(stderr, "Generate consecutive prime numbers up to 19 digits.\n");
-	fprintf(stderr, "If \"twin\" is specified, display only twin primes.\n");
-	fprintf(stderr, "If \"pal\" is specified, display only palindromic primes.\n");
+	fprintf(stderr, "If \"twin\" is specified, output only twin primes.\n");
+	fprintf(stderr, "If \"pal\" is specified, output only palindromic primes.\n");
 	fprintf(stderr, "The palindromic base may be specified, the default is base 10.\n");
 	exit(1);
 }
+
+void
+usage2()
+{
+	fprintf(stderr, "\nUsage: %s [options] [start [stop]]\n\n", prog_name);
+	fprintf(stderr, "Generate consecutive prime numbers up to 19 digits.\n");
+	fprintf(stderr, "Options:\n");
+	fprintf(stderr, "  -t               Output only twin primes.\n");
+	fprintf(stderr, "  -p base          Output only palindromic primes.\n");
+	exit(1);
+}

Added: branches/vendor/mathomatic/primes/matho-sumsq.1

Added: branches/vendor/mathomatic/primes/matho-sumsq.c

Added: branches/vendor/mathomatic/primes/mult

Added: branches/vendor/mathomatic/primes/primorial

Modified: branches/vendor/mathomatic/primes/twins.out
===================================================================
--- branches/vendor/mathomatic/primes/twins.out	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/primes/twins.out	2007-06-24 11:58:26 UTC (rev 1806)
@@ -234,209 +234,3 @@
 1000000000000295339 1000000000000295341
 1000000000000296467 1000000000000296469
 1000000000000297391 1000000000000297393
-1000000000000300469 1000000000000300471
-1000000000000305089 1000000000000305091
-1000000000000305749 1000000000000305751
-1000000000000310249 1000000000000310251
-1000000000000312097 1000000000000312099
-1000000000000315241 1000000000000315243
-1000000000000315661 1000000000000315663
-1000000000000316141 1000000000000316143
-1000000000000316969 1000000000000316971
-1000000000000321841 1000000000000321843
-1000000000000323851 1000000000000323853
-1000000000000328111 1000000000000328113
-1000000000000330391 1000000000000330393
-1000000000000331399 1000000000000331401
-1000000000000334351 1000000000000334353
-1000000000000334609 1000000000000334611
-1000000000000335707 1000000000000335709
-1000000000000335797 1000000000000335799
-1000000000000336589 1000000000000336591
-1000000000000338299 1000000000000338301
-1000000000000338749 1000000000000338751
-1000000000000339631 1000000000000339633
-1000000000000340231 1000000000000340233
-1000000000000340429 1000000000000340431
-1000000000000342217 1000000000000342219
-1000000000000342931 1000000000000342933
-1000000000000343891 1000000000000343893
-1000000000000347629 1000000000000347631
-1000000000000348379 1000000000000348381
-1000000000000348469 1000000000000348471
-1000000000000349669 1000000000000349671
-1000000000000349861 1000000000000349863
-1000000000000350299 1000000000000350301
-1000000000000350497 1000000000000350499
-1000000000000352621 1000000000000352623
-1000000000000352759 1000000000000352761
-1000000000000353167 1000000000000353169
-1000000000000353479 1000000000000353481
-1000000000000356737 1000000000000356739
-1000000000000360061 1000000000000360063
-1000000000000360991 1000000000000360993
-1000000000000361537 1000000000000361539
-1000000000000366049 1000000000000366051
-1000000000000368539 1000000000000368541
-1000000000000369451 1000000000000369453
-1000000000000371749 1000000000000371751
-1000000000000372409 1000000000000372411
-1000000000000374251 1000000000000374253
-1000000000000374671 1000000000000374673
-1000000000000375469 1000000000000375471
-1000000000000377119 1000000000000377121
-1000000000000378649 1000000000000378651
-1000000000000379267 1000000000000379269
-1000000000000381811 1000000000000381813
-1000000000000383521 1000000000000383523
-1000000000000385381 1000000000000385383
-1000000000000386029 1000000000000386031
-1000000000000387871 1000000000000387873
-1000000000000387931 1000000000000387933
-1000000000000388837 1000000000000388839
-1000000000000389077 1000000000000389079
-1000000000000392029 1000000000000392031
-1000000000000394201 1000000000000394203
-1000000000000395599 1000000000000395601
-1000000000000395827 1000000000000395829
-1000000000000397057 1000000000000397059
-1000000000000397399 1000000000000397401
-1000000000000397951 1000000000000397953
-1000000000000398611 1000000000000398613
-1000000000000400141 1000000000000400143
-1000000000000400459 1000000000000400461
-1000000000000400549 1000000000000400551
-1000000000000403111 1000000000000403113
-1000000000000404017 1000000000000404019
-1000000000000404131 1000000000000404133
-1000000000000404671 1000000000000404673
-1000000000000407821 1000000000000407823
-1000000000000408061 1000000000000408063
-1000000000000409537 1000000000000409539
-1000000000000411379 1000000000000411381
-1000000000000411769 1000000000000411771
-1000000000000416461 1000000000000416463
-1000000000000417259 1000000000000417261
-1000000000000423067 1000000000000423069
-1000000000000423139 1000000000000423141
-1000000000000424957 1000000000000424959
-1000000000000425791 1000000000000425793
-1000000000000426637 1000000000000426639
-1000000000000427441 1000000000000427443
-1000000000000430711 1000000000000430713
-1000000000000430717 1000000000000430719
-1000000000000430981 1000000000000430983
-1000000000000433099 1000000000000433101
-1000000000000433249 1000000000000433251
-1000000000000435127 1000000000000435129
-1000000000000435589 1000000000000435591
-1000000000000437851 1000000000000437853
-1000000000000442339 1000000000000442341
-1000000000000442759 1000000000000442761
-1000000000000442981 1000000000000442983
-1000000000000444061 1000000000000444063
-1000000000000447949 1000000000000447951
-1000000000000448561 1000000000000448563
-1000000000000450457 1000000000000450459
-1000000000000451141 1000000000000451143
-1000000000000452641 1000000000000452643
-1000000000000453211 1000000000000453213
-1000000000000458491 1000000000000458493
-1000000000000459739 1000000000000459741
-1000000000000460981 1000000000000460983
-1000000000000461869 1000000000000461871
-1000000000000462871 1000000000000462873
-1000000000000464371 1000000000000464373
-1000000000000465379 1000000000000465381
-1000000000000466471 1000000000000466473
-1000000000000468667 1000000000000468669
-1000000000000468697 1000000000000468699
-1000000000000468769 1000000000000468771
-1000000000000470449 1000000000000470451
-1000000000000476437 1000000000000476439
-1000000000000484321 1000000000000484323
-1000000000000485899 1000000000000485901
-1000000000000487531 1000000000000487533
-1000000000000488467 1000000000000488469
-1000000000000489529 1000000000000489531
-1000000000000491647 1000000000000491649
-1000000000000491977 1000000000000491979
-1000000000000494707 1000000000000494709
-1000000000000494749 1000000000000494751
-1000000000000496609 1000000000000496611
-1000000000000500221 1000000000000500223
-1000000000000500449 1000000000000500451
-1000000000000501991 1000000000000501993
-1000000000000503881 1000000000000503883
-1000000000000504757 1000000000000504759
-1000000000000505561 1000000000000505563
-1000000000000506941 1000000000000506943
-1000000000000510181 1000000000000510183
-1000000000000512149 1000000000000512151
-1000000000000512221 1000000000000512223
-1000000000000512629 1000000000000512631
-1000000000000513661 1000000000000513663
-1000000000000513667 1000000000000513669
-1000000000000513709 1000000000000513711
-1000000000000516127 1000000000000516129
-1000000000000516637 1000000000000516639
-1000000000000517807 1000000000000517809
-1000000000000518299 1000000000000518301
-1000000000000518929 1000000000000518931
-1000000000000519751 1000000000000519753
-1000000000000521437 1000000000000521439
-1000000000000521599 1000000000000521601
-1000000000000522151 1000000000000522153
-1000000000000524077 1000000000000524079
-1000000000000525091 1000000000000525093
-1000000000000526429 1000000000000526431
-1000000000000526891 1000000000000526893
-1000000000000527311 1000000000000527313
-1000000000000530731 1000000000000530733
-1000000000000535957 1000000000000535959
-1000000000000536209 1000000000000536211
-1000000000000540457 1000000000000540459
-1000000000000545629 1000000000000545631
-1000000000000547801 1000000000000547803
-1000000000000547891 1000000000000547893
-1000000000000548011 1000000000000548013
-1000000000000548179 1000000000000548181
-1000000000000548551 1000000000000548553
-1000000000000550849 1000000000000550851
-1000000000000551881 1000000000000551883
-1000000000000551917 1000000000000551919
-1000000000000552121 1000000000000552123
-1000000000000552781 1000000000000552783
-1000000000000553009 1000000000000553011
-1000000000000554809 1000000000000554811
-1000000000000555997 1000000000000555999
-1000000000000558391 1000000000000558393
-1000000000000558679 1000000000000558681
-1000000000000559531 1000000000000559533
-1000000000000561709 1000000000000561711
-1000000000000562357 1000000000000562359
-1000000000000562567 1000000000000562569
-1000000000000562861 1000000000000562863
-1000000000000563827 1000000000000563829
-1000000000000569569 1000000000000569571
-1000000000000569749 1000000000000569751
-1000000000000570337 1000000000000570339
-1000000000000575617 1000000000000575619
-1000000000000575857 1000000000000575859
-1000000000000576637 1000000000000576639
-1000000000000577039 1000000000000577041
-1000000000000577729 1000000000000577731
-1000000000000577759 1000000000000577761
-1000000000000578299 1000000000000578301
-1000000000000578959 1000000000000578961
-1000000000000582409 1000000000000582411
-1000000000000582937 1000000000000582939
-1000000000000583651 1000000000000583653
-1000000000000583837 1000000000000583839
-1000000000000585721 1000000000000585723
-1000000000000590737 1000000000000590739
-1000000000000590989 1000000000000590991
-1000000000000592711 1000000000000592713
-1000000000000596251 1000000000000596253
-1000000000000598549 1000000000000598551
-1000000000000599149 1000000000000599151

Modified: branches/vendor/mathomatic/proto.h
===================================================================
--- branches/vendor/mathomatic/proto.h	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/proto.h	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,24 +1,25 @@
 /*
  * Global function prototypes for Mathomatic.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 /* command function list */
 int		clear_cmd(), quit_cmd(), list_cmd(), simplify_cmd(), help_cmd(), eliminate_cmd();
-int		unfactor_cmd(), compare_cmd(), extrema_cmd();
-int		read_cmd(), flist_cmd(), calculate_cmd();
+int		fraction_cmd(), unfactor_cmd(), compare_cmd(), extrema_cmd();
+int		read_cmd(), display_cmd(), calculate_cmd(), solve_cmd();
 int		factor_cmd(), derivative_cmd(), replace_cmd();
-int		save_cmd(), print_cmd(), taylor_cmd(), limit_cmd();
+int		save_cmd(), taylor_cmd(), limit_cmd(), echo_cmd();
 int		copy_cmd(), divide_cmd(), pause_cmd(), version_cmd();
 int		edit_cmd(), real_cmd(), imaginary_cmd(), tally_cmd();
 int		roots_cmd(), set_cmd(), code_cmd(), optimize_cmd(), push_cmd();
 int		sum_cmd(), product_cmd(), integrate_cmd(), nintegrate_cmd(), laplace_cmd();
 
 /* various functions that don't return int */
+char		*dirname_win();
 char		*skip_space(), *skip_param();
 char		*get_string();
-char		*parse_equation(), *parse_section(), *parse_var(), *parse_var2();
+char		*parse_equation(), *parse_section(), *parse_var(), *parse_var2(), *parse_expr();
 char		*list_expression(), *list_equation();
 double		gcd(), my_round(), multiply_out_unique();
 long		decstrtol();

Modified: branches/vendor/mathomatic/simplify.c
===================================================================
--- branches/vendor/mathomatic/simplify.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/simplify.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,12 +1,13 @@
 /*
- * Algebraic manipulator simplifying routines.
+ * Mathomatic simplifying routines.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
 
-#define	MAX_COMPARE_TERMS	400	/* Max no. of terms on same level that can be compared.  Increases stack usage. */
+#define	MAX_COMPARE_TERMS	500	/* Max no. of terms on same level that can be compared, increases stack usage. */
+					/* MAX_COMPARE_TERMS should be approximately (sqrt(DEFAULT_N_TOKENS) * 3) */
 
 static int	org_recurse();
 static int	const_recurse();
@@ -14,20 +15,25 @@
 static int	order_recurse();
 
 /*
- * Minimally and very basically simplify an equation space.
+ * Quickly and very basically simplify an equation space.
+ * No factoring is done.
  */
 simp_sub(n)
-int	n;	/* equation number to simplify */
+int	n;	/* equation space number to simplify */
 {
+	if (n_lhs[n] <= 0)
+		return;
 	simp_loop(lhs[n], &n_lhs[n]);
-	simp_loop(rhs[n], &n_rhs[n]);
+	if (n_rhs[n]) {
+		simp_loop(rhs[n], &n_rhs[n]);
+	}
 }
 
 /*
  * For quick, mid-range simplification of an expression.
  */
 simp_side(equation, np)
-token_type	*equation;	/* equation side to simplify */
+token_type	*equation;	/* pointer to the beginning of equation side to simplify */
 int		*np;		/* pointer to length of equation side */
 {
 	simp_ssub(equation, np, 0L, 0.0, true, true, 1);
@@ -37,49 +43,65 @@
  * This function is the mid-range simplifier used by the solver.
  */
 simps_side(equation, np, zsolve)
-token_type	*equation;	/* equation side to simplify */
+token_type	*equation;	/* pointer to the beginning of equation side to simplify */
 int		*np;		/* pointer to length of equation side */
 int		zsolve;		/* true if we are solving for zero */
 {
 	do {
 		simp_ssub(equation, np, 0L, 0.0, !zsolve, true, 2);
-	} while (super_factor(equation, np, false));
+	} while (super_factor(equation, np, 0));
 }
 
 /*
  * This function is used by the "factor" command.
  */
 simpv_side(equation, np, v)
-token_type	*equation;	/* equation side to factor */
+token_type	*equation;	/* pointer to the beginning of equation side to factor */
 int		*np;		/* pointer to length of equation side */
 long		v;		/* variable to factor */
 {
 	if (*np == 0)
 		return;
-	simp_ssub(equation, np, v, 0.0, v == 0L, true, 2);
+	simp_ssub(equation, np, v, 0.0, v == 0, true, 2);
 }
 
 /*
+ * Convert expression with any algebraic fractions into a single fraction.
+ */
+frac_side(equation, np)
+token_type	*equation;	/* pointer to the beginning of equation side */
+int		*np;		/* pointer to length of equation side */
+{
+	if (*np == 0)
+		return;
+	do {
+		simpb_side(equation, np, false, 2);
+	} while (super_factor(equation, np, 2));
+}
+
+/*
  * Simplify and approximate for the calculate command.
- * Includes imaginary number simplification.
+ * Includes complex number simplification.
  */
 calc_simp(equation, np)
 token_type	*equation;
 int		*np;
 {
-	in_calc_cmd = true;
+	approximate_roots = true;
 	subst_constants(equation, np);
 	simp_side(equation, np);
+	factorv(equation, np, IMAGINARY);
 	ufactor(equation, np);
 	factorv(equation, np, IMAGINARY);
+	ufactor(equation, np);
+	factorv(equation, np, IMAGINARY);
 	simp_side(equation, np);
 	uf_simp(equation, np);
-	in_calc_cmd = false;
+	approximate_roots = false;
 }
 
 /*
- * Try to eliminate "i#" from an equation side,
- * by converting "i#*(b^.5)" to "(-1*b)^.5".
+ * Try to eliminate "i#" from an equation side by converting "i#*(b^.5)" to "(-1*b)^.5".
  */
 simp_i(equation, np)
 token_type	*equation;
@@ -129,23 +151,19 @@
  * This is the slowest and most thorough simplify of all.
  */
 simpa_side(equation, np, quick_flag)
-token_type	*equation;	/* pointer to equation side to simplify */
+token_type	*equation;	/* pointer to the beginning of equation side to simplify */
 int		*np;		/* pointer to length of the equation side */
 int		quick_flag;	/* "simplify quick" option */
 {
-	int		flag, poly_flag = false;
+	int		flag, poly_flag = true;
 	jmp_buf		save_save;
 
 	if (*np <= 1)	/* no need to simplify a constant or a variable */
 		return;
 	partial_flag = 2;
-#if	true
 	simp_loop(equation, np);
 	poly_factor(equation, np);
-#endif
-	do {
-		simp_ssub(equation, np, 0L, 0.0, false, true, 1);
-	} while (uf_power(equation, np));
+	simpb_side(equation, np, true, 1);
 	simp_ssub(equation, np, 0L, 0.0, true, true, 1);
 	rationalize(equation, np);
 	unsimp_power(equation, np);
@@ -183,7 +201,7 @@
 		do {
 			simp_ssub(equation, np, 0L, 1.0, false, true, 1);
 		} while (uf_power(equation, np));
-	} while (super_factor(equation, np, true));
+	} while (super_factor(equation, np, 2));
 	if (quick_flag) {
 do_quick:
 		uf_tsimp(equation, np);
@@ -206,7 +224,7 @@
 	}
 	partial_flag = false;
 	simpb_side(equation, np, true, 1);
-	debug_string(1, "Simplified result before applying polynomial operations:");
+	debug_string(1, "Simplify result before applying polynomial operations:");
 	side_debug(1, equation, *np);
 	for (flag = false;;) {
 		/* divide top and bottom of fractions by any polynomial GCD found */
@@ -244,14 +262,14 @@
 	while (div_remainder(equation, np, poly_flag, quick_flag)) {
 		simpb_side(equation, np, true, 3);
 	}
-	if (poly_factor(equation, np)) {
-		simpb_side(equation, np, true, 3);
-	}
+	poly_factor(equation, np);
 	simpb_side(equation, np, true, 2);
+	debug_string(1, "Result of complete simplify:");
+	side_debug(1, equation, *np);
 }
 
 /*
- * Compare function for qsort(3).
+ * Compare function for qsort(3) within simpb_side().
  */
 static int
 vcmp(p1, p2)
@@ -276,15 +294,15 @@
 }
 
 /*
+ * Beauty simplifier.
  * Neat simplify and factor routine.
- * Factors variables in order.
- * "sign" variables first, then by frequency.
+ * Factors variables in order: "sign" variables first, then by frequency.
  */
 simpb_side(equation, np, power_flag, fc_level)
-token_type	*equation;	/* equation side pointer */
+token_type	*equation;	/* pointer to the beginning of equation side */
 int		*np;		/* pointer to length of equation side */
-int		power_flag;	/* factor powers flag */
-int		fc_level;	/* factor constants code */
+int		power_flag;	/* factor_power() flag */
+int		fc_level;	/* factor constants code, passed to factor_constants() */
 {
 	int		i;
 	int		vc, cnt;
@@ -295,8 +313,7 @@
 	uf_allpower(equation, np);
 	last_v = 0;
 	for (vc = 0; vc < ARR_CNT(va); vc++) {
-		v1 = -1;
-		for (i = 0; i < *np; i += 2) {
+		for (i = 0, cnt = 0, v1 = -1; i < *np; i += 2) {
 			if (equation[i].kind == VARIABLE && equation[i].token.variable > last_v) {
 				if (v1 == -1 || equation[i].token.variable < v1) {
 					v1 = equation[i].token.variable;
@@ -312,25 +329,23 @@
 		va[vc].v = v1;
 		va[vc].count = cnt;
 	}
-	if (vc == 0) {
-		goto skip_factor;
-	}
-	qsort((char *) va, vc, sizeof(*va), vcmp);
-	simp2_divide(equation, np, va[0].v, fc_level);
-	for (i = 1; i < vc; i++) {
-		if (factor_divide(equation, np, va[i].v, 0.0))
-			simp2_divide(equation, np, va[i].v, fc_level);
-	}
-	simp2_divide(equation, np, 0L, fc_level);
-	for (i = 0; i < vc; i++) {
-		while (factor_plus(equation, np, va[i].v, 0.0)) {
+	if (vc) {
+		qsort((char *) va, vc, sizeof(*va), vcmp);
+		simp2_divide(equation, np, va[0].v, fc_level);
+		for (i = 1; i < vc; i++) {
+			if (factor_divide(equation, np, va[i].v, 0.0))
+				simp2_divide(equation, np, va[i].v, fc_level);
+		}
+		simp2_divide(equation, np, 0L, fc_level);
+		for (i = 0; i < vc; i++) {
+			while (factor_plus(equation, np, va[i].v, 0.0)) {
+				simp2_divide(equation, np, 0L, fc_level);
+			}
+		}
+		while (factor_plus(equation, np, MATCH_ANY, 0.0)) {
 			simp2_divide(equation, np, 0L, fc_level);
 		}
 	}
-	while (factor_plus(equation, np, MATCH_ANY, 0.0)) {
-		simp2_divide(equation, np, 0L, fc_level);
-	}
-skip_factor:
 	simp_ssub(equation, np, MATCH_ANY, 0.0, power_flag, true, fc_level);
 }
 
@@ -339,7 +354,7 @@
  * Just does constant simplification.
  */
 elim_loop(equation, np)
-token_type	*equation;	/* equation side to simplify */
+token_type	*equation;	/* pointer to the beginning of equation side to simplify */
 int		*np;		/* pointer to length of equation side */
 {
 	side_debug(6, equation, *np);
@@ -362,12 +377,12 @@
  * Configurable high level simplify routine.
  */
 simp_ssub(equation, np, v, d, power_flag, times_flag, fc_level)
-token_type	*equation;	/* equation side to simplify */
+token_type	*equation;	/* pointer to the beginning of equation side to simplify */
 int		*np;		/* pointer to length of equation side */
 long		v;		/* variable to factor, 0L or MATCH_ANY to factor all variables */
 double		d;		/* factor expressions raised to the power of this if v */
-int		power_flag;	/* factor power flag */
-int		times_flag;	/* factor times flag */
+int		power_flag;	/* factor_power() flag */
+int		times_flag;	/* factor_times() flag */
 int		fc_level;	/* factor constants code, passed to factor_constants() */
 {
 	do {
@@ -396,14 +411,12 @@
  */
 int
 simp_loop(equation, np)
-token_type	*equation;	/* equation side to simplify */
+token_type	*equation;	/* pointer to the beginning of equation side to simplify */
 int		*np;		/* pointer to length of equation side */
 {
 	int	i;
 	int	rv = false;
 
-	if (*np == 0)
-		return rv;
 	do {
 		do {
 			do {
@@ -424,7 +437,7 @@
  * If v is IMAGINARY, do complex number simplification.
  */
 factorv(equation, np, v)
-token_type	*equation;	/* equation side to factor */
+token_type	*equation;	/* pointer to the beginning of equation side to factor */
 int		*np;		/* pointer to equation side length */
 long		v;		/* variable to factor */
 {
@@ -455,7 +468,8 @@
 }
 
 /*
- * Combine all like denominators.  Don't factor times.
+ * Combine all like denominators containing variable "v".
+ * Don't call factor_times().
  */
 simp2_divide(equation, np, v, fc_level)
 token_type	*equation;
@@ -483,15 +497,15 @@
  * This is the inner-most loop in Mathomatic, make it fast.
  */
 organize(equation, np)
-token_type	*equation;
-int		*np;
+token_type	*equation;	/* equation side pointer */
+int		*np;		/* pointer to length of equation side */
 {
 	if (*np <= 0 || (*np & 1) != 1) {
-		error(_("Organize called with bad expression size!"));
+		error("Internal error: Organize called with bad expression size.");
 		longjmp(jmp_save, 13);
 	}
 	if (*np > n_tokens) {
-		error(_("Array overflow detected!  Expression larger than \"n_tokens\"."));
+		error("Internal error: Expression array overflow detected.");
 		longjmp(jmp_save, 13);
 	}
 	org_recurse(equation, np, 0, 1, NULL);
@@ -530,12 +544,14 @@
 }
 
 /*
- * Recursively organize an expression at "level" of parentheses.
+ * Recurse through every sub-expression in "equation", starting at "loc",
+ * moving up levels to "level" of parentheses.
  */
 static int
 org_recurse(equation, np, loc, level, elocp)
-token_type	*equation;
-int		*np, loc, level, *elocp;
+token_type	*equation;	/* equation side pointer */
+int		*np;		/* pointer to length of equation side */
+int		loc, level, *elocp;
 {
 	token_type	*p1, *bp, *ep;
 	int		op, sub_op;
@@ -761,7 +777,7 @@
 		if (*np + 2 > n_tokens) {
 			error_huge();
 		}
-		blt(&equation[j+2], &equation[j], (*np - j) * sizeof(*equation));
+		blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type));
 		*np += 2;
 		equation[j+1].level = level + 1;
 		equation[j+1].kind = CONSTANT;
@@ -838,7 +854,7 @@
 		k++;
 		for (i = k; i < j; i++)
 			equation[i].level++;
-		blt(&equation[k+2], &equation[k], (*np - k) * sizeof(*equation));
+		blt(&equation[k+2], &equation[k], (*np - k) * sizeof(token_type));
 		*np += 2;
 		equation[k].level = level;
 		equation[k].kind = CONSTANT;
@@ -881,7 +897,7 @@
  */
 int
 combine_constants(equation, np, iflag)
-token_type	*equation;	/* equation side pointer */
+token_type	*equation;	/* pointer to the beginning of equation side */
 int		*np;		/* pointer to length of equation side */
 int		iflag;		/* produce imaginary numbers flag */
 {
@@ -889,7 +905,7 @@
 }
 
 /*
- * Do the arithmetic.
+ * Do the floating point arithmetic for Mathomatic.
  *
  * Return true if successful.
  */
@@ -901,8 +917,7 @@
 double	k2;	/* operand 2 */
 {
 	int	op1;
-	double	d;
-	double	d1, d2;
+	double	d, d1, d2;
 
 	domain_check = false;
 	errno = 0;
@@ -948,13 +963,11 @@
 				*k1p = *k1p / k2;
 			}
 		}
-		d1 = fabs(*k1p) * small_epsilon;
-		d = my_round(*k1p);
-		if (d != 0.0 && fabs(d - *k1p) < d1) {
-			*k1p = d;
-		}
 		break;
 	case MODULUS:
+		if (k2 == 0) {
+			debug_string(0, _("Warning: modulo 0 encountered, might be considered undefined."));
+		}
 #if	false	/* If fmod() always works.  It doesn't. */
 		*k1p = fmod(*k1p, k2);
 #else
@@ -969,18 +982,16 @@
 			break;
 		}
 		if (*k1p == 0.0 && k2 < 0.0) {
-#if	!SILENT
 			error(_("Divide by zero error."));
-#endif
 			longjmp(jmp_save, 2);
 		}
 		domain_check = true;
 		if (*k1p == 0.0 && k2 == 0.0) {
-			debug_string(0, _("Warning: 0 raised to the power of 0."));
+			debug_string(0, _("Warning: 0^0 encountered, might be considered undefined."));
 			d = 1.0;	/* some people don't know 0^0 */
 		} else {
 			d = pow(*k1p, k2);
-			if (preserve_roots && !in_calc_cmd) {
+			if (preserve_roots && !approximate_roots) {
 				if (isfinite(k2) && fmod(k2, 1.0) != 0.0 && f_to_fraction(*k1p, &d1, &d2)) {
 					if (!f_to_fraction(d, &d1, &d2)) {
 						domain_check = false;
@@ -995,8 +1006,8 @@
 		break;
 	case FACTORIAL:
 #if	true	/* set this to false if lgamma() doesn't exist */
-		d = exp(lgamma(*k1p + 1.0));
-		if (errno) {	/* simply don't evaluate if error */
+		d = exp(lgamma(*k1p + 1.0)) * signgam;
+		if (errno) {	/* don't evaluate if overflow */
 			return false;
 		}
 #else
@@ -1028,7 +1039,7 @@
 	double		d, d1, d2, numerator, denominator;
 	complexs	cv, p;
 
-	old_loc = loc;
+	loc1 = old_loc = loc;
 	for (;; loc++) {
 beginning:
 		if (loc >= *np || equation[loc].level < level) {
@@ -1054,7 +1065,7 @@
 			if (calc((loc1 <= old_loc) ? &zero : &equation[loc1-1].token.operatr, &d, op, d2)) {
 				if (op == POWER && !domain_check) {
 					if (!f_to_fraction(d2, &numerator, &denominator)) {	/* if irrational power */
-						if (!iflag || (preserve_roots && !in_calc_cmd))
+						if (!iflag || (preserve_roots && !approximate_roots))
 							return modified;
 						cv.re = d;
 						cv.im = 0.0;
@@ -1064,7 +1075,7 @@
 						if (*np + 2 > n_tokens) {
 							error_huge();
 						}
-						blt(&equation[loc1+2], &equation[loc1], (*np - loc1) * sizeof(*equation));
+						blt(&equation[loc1+2], &equation[loc1], (*np - loc1) * sizeof(token_type));
 						*np += 2;
 						equation[loc1].level = level;
 						equation[loc1].kind = CONSTANT;
@@ -1102,7 +1113,7 @@
 					if (*np + 2 > n_tokens) {
 						error_huge();
 					}
-					blt(&equation[loc1+2], &equation[loc1], (*np - loc1) * sizeof(*equation));
+					blt(&equation[loc1+2], &equation[loc1], (*np - loc1) * sizeof(token_type));
 					*np += 2;
 					if (d2 == 0.5) {
 						equation[loc1].level = level + 1;
@@ -1150,7 +1161,7 @@
 					equation[loc1].token.constant = d;
 					modified = true;
 					domain_check = false;
-					blt(&equation[loc-1], &equation[loc+1], (*np - (loc + 1)) * sizeof(*equation));
+					blt(&equation[loc-1], &equation[loc+1], (*np - (loc + 1)) * sizeof(token_type));
 					*np -= 2;
 					loc -= 2;
 				}
@@ -1446,6 +1457,7 @@
 	int		last_op1, op1, op2;
 	int		diff_op;
 	double		d1, c1, c2;
+	double		compare_epsilon = epsilon;
 
 	*diff_signp = false;
 	if (n1 == 1 && n2 == 1) {
@@ -1469,7 +1481,7 @@
 				*diff_signp = true;
 				return true;
 			}
-			d1 = fabs(c1) * epsilon;
+			d1 = fabs(c1) * compare_epsilon;
 			if (fabs(c1 - c2) < d1) {
 				return true;
 			}
@@ -1525,7 +1537,7 @@
 	}
 	if (diff_op) {
 		if (p1->kind == CONSTANT && p1->level == l1 && op1 == TIMES) {
-			if (fabs(fabs(p1->token.constant) - 1.0) <= epsilon) {
+			if (fabs(fabs(p1->token.constant) - 1.0) <= compare_epsilon) {
 				if (!compare_recurse(p1 + 2, n1 - 2, min_level(p1 + 2, n1 - 2), p2, n2, l2, diff_signp)) {
 					return false;
 				}
@@ -1536,7 +1548,7 @@
 			}
 		}
 		if (p2->kind == CONSTANT && p2->level == l2 && op2 == TIMES) {
-			if (fabs(fabs(p2->token.constant) - 1.0) <= epsilon) {
+			if (fabs(fabs(p2->token.constant) - 1.0) <= compare_epsilon) {
 				if (!compare_recurse(p1, n1, l1, p2 + 2, n2 - 2, min_level(p2 + 2, n2 - 2), diff_signp)) {
 					return false;
 				}
@@ -1570,15 +1582,13 @@
 				break;
 		for (i = 0;; i++) {
 			if (i >= oc2) {
-				if ((op1 == TIMES || op1 == DIVIDE)
-				    && pv1->level == l1 && pv1->kind == CONSTANT) {
-					if (fabs(pv1->token.constant + 1.0) <= epsilon) {
-						*diff_signp ^= true;
+				if ((op1 == TIMES || op1 == DIVIDE) && pv1->level == l1 && pv1->kind == CONSTANT) {
+					if (fabs(fabs(pv1->token.constant) - 1.0) <= compare_epsilon) {
+						if (pv1->token.constant < 0.0) {
+							*diff_signp ^= true;
+						}
 						break;
 					}
-					if (fabs(pv1->token.constant - 1.0) <= epsilon) {
-						break;
-					}
 				}
 				return false;
 			}
@@ -1640,15 +1650,13 @@
 	}
 	for (i = 0; i < oc2; i++) {
 		if (!used[i]) {
-			if ((op2 == TIMES || op2 == DIVIDE)
-			    && opa2[i]->level == l2 && opa2[i]->kind == CONSTANT) {
-				if (fabs(opa2[i]->token.constant + 1.0) <= epsilon) {
-					*diff_signp ^= true;
+			if ((op2 == TIMES || op2 == DIVIDE) && opa2[i]->level == l2 && opa2[i]->kind == CONSTANT) {
+				if (fabs(fabs(opa2[i]->token.constant) - 1.0) <= compare_epsilon) {
+					if (opa2[i]->token.constant < 0.0) {
+						*diff_signp ^= true;
+					}
 					continue;
 				}
-				if (fabs(opa2[i]->token.constant - 1.0) <= epsilon) {
-					continue;
-				}
 			}
 			return false;
 		}
@@ -1658,8 +1666,9 @@
 
 /*
  * Take out meaningless "sign" variables and negative constants.
- * Simplify imaginary numbers raised to the power of some constants
- * (including simple division ((i#^-1) -> (-1*i#))).
+ * Simplify imaginary numbers raised to the power of some constants,
+ * including simple division (1/i# -> -1*i#).
+ *
  * Return true if equation side was modified.
  */
 int
@@ -1742,8 +1751,7 @@
 					}
 				}
 			} else {
-				if (equation[i-1].level == level
-				    && equation[i-1].kind == VARIABLE) {
+				if (equation[i-1].level == level && equation[i-1].kind == VARIABLE) {
 					if (equation[i-1].token.variable == IMAGINARY) {
 						d = fmod(equation[i+1].token.constant, 4.0);
 						if (d == 1.0) {
@@ -1756,8 +1764,7 @@
 							modified = true;
 						}
 					} else if ((equation[i-1].token.variable & VAR_MASK) == SIGN) {
-						d = fmod(equation[i+1].token.constant, 2.0);
-						equation[i+1].token.constant = d;
+						equation[i+1].token.constant = fmod(equation[i+1].token.constant, 2.0);
 					}
 				}
 			}
@@ -1924,10 +1931,10 @@
 	}
 	n1 = e1 - i1;
 	n2 = e2 - i2;
-	blt(scratch, &equation[i1], (e2 - i1) * sizeof(*equation));
-	blt(&equation[i1+n2], &equation[e1], (i2 - e1) * sizeof(*equation));
-	blt(&equation[i1], &scratch[i2-i1], n2 * sizeof(*equation));
-	blt(&equation[e2-n1], scratch, n1 * sizeof(*equation));
+	blt(scratch, &equation[i1], (e2 - i1) * sizeof(token_type));
+	blt(&equation[i1+n2], &equation[e1], (i2 - e1) * sizeof(token_type));
+	blt(&equation[i1], &scratch[i2-i1], n2 * sizeof(token_type));
+	blt(&equation[e2-n1], scratch, n1 * sizeof(token_type));
 }
 
 static int
@@ -2007,13 +2014,12 @@
 		}
 		for (k = j + 2; k < i;) {
 			if (equation[k].level == level && equation[k].token.operatr == TIMES) {
-				for (n = k + 2; n < i; n += 2)
-					if (equation[n].level <= level)
-						break;
+				for (n = k + 2; n < i && equation[n].level > level; n += 2)
+					;
 				n -= k;
-				blt(scratch, &equation[k], n * sizeof(*equation));
-				blt(&equation[j+n], &equation[j], (k - j) * sizeof(*equation));
-				blt(&equation[j], scratch, n * sizeof(*equation));
+				blt(scratch, &equation[k], n * sizeof(token_type));
+				blt(&equation[j+n], &equation[j], (k - j) * sizeof(token_type));
+				blt(&equation[j], scratch, n * sizeof(token_type));
 				j += n;
 				k += n;
 				modified = true;
@@ -2025,9 +2031,8 @@
 	}
 	return modified;
 corrupt:
-	error(_("Expression is corrupt!"));
+	error(_("Expression is corrupt!  Please file a bug report."));
 	longjmp(jmp_save, 13);
-
 }
 
 /*

Modified: branches/vendor/mathomatic/solve.c
===================================================================
--- branches/vendor/mathomatic/solve.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/solve.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
- * Algebraic manipulator solve routines.
+ * Mathomatic solve routines.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -35,7 +35,7 @@
 	n_lhs[want] = 0;
 	n_rhs[want] = 0;
 #if	!SILENT
-	if (!rv) {
+	if (rv <= 0) {
 		printf(_("Solve failed.\n"));
 	}
 #endif
@@ -43,19 +43,20 @@
 }
 
 /*
- * Main Mathomatic solve routine.
+ * Main Mathomatic symbolic solve routine.
  *
  * This works by moving everything containing the variable to solve for
  * to the LHS (via transposition), then moving everything not containing the variable to the
  * RHS.  Many tricks are used, and this routine works very well.
  *
- * "tlhs" and "trhs" are used by this routine.
+ * tlhs and trhs are used by this routine.
  *
  * Returns a positive integer if successful, with the result placed in the passed LHS and RHS.
  * Returns 1 for normal success.
  * Returns 2 if successful and a solution was zero and removed.
- * Returns 0 on failure.
+ * Returns 0 on failure.  Might succeed at a numeric solve.
  * Returns -1 if the equation is an identity.
+ * Returns -2 if unsolvable in all realms.
  */
 int
 solve_sub(wantp, wantn, leftp, leftnp, rightp, rightnp)
@@ -74,10 +75,10 @@
 	token_type	*p1, *b1, *ep;
 	long		v;
 	int		need_flip;
-	int		uf_flag = false;
+	int		uf_flag = false;	/* unfactor flag */
 	int		qtries = 0;
-	int		zflag;
-	int		zsolve;
+	int		zflag;			/* true if RHS is currently zero */
+	int		zsolve;			/* true if we are solving for zero */
 	int		inc_count = 0;
 	int		zero_solved = false;
 	double		numerator, denominator;
@@ -112,11 +113,10 @@
 		}
 		zsolve = true;
 	}
-#if	true
 	uf_power(tlhs, &n_tlhs);
 	uf_power(trhs, &n_trhs);
-#endif
 simp_again:
+	/* Make sure equation is a bit simplified. */
 	list_tdebug(2);
 	simps_side(tlhs, &n_tlhs, zsolve);
 	if (uf_flag) {
@@ -128,7 +128,7 @@
 	}
 	list_tdebug(1);
 no_simp:
-	/* Move from the RHS to the LHS. */
+	/* First selectively move subexpressions from the RHS to the LHS. */
 	op = 0;
 	ep = &trhs[n_trhs];
 	if (zsolve) {
@@ -193,7 +193,7 @@
 		simps_side(trhs, &n_trhs, zsolve);
 	}
 left_again:
-	worked = 1;
+	worked = true;
 	uf_flag = false;
 see_work:
 	/* See if we have solved the equation. */
@@ -214,7 +214,7 @@
 					do {
 						simp_ssub(trhs, &n_trhs, 0L, 0.0, false, true, 0);
 					} while (uf_power(trhs, &n_trhs));
-				} while (super_factor(trhs, &n_trhs, true));
+				} while (super_factor(trhs, &n_trhs, 1));
 				list_tdebug(3);
 				ep = &trhs[n_trhs];
 				op = 0;
@@ -348,8 +348,7 @@
 			if (p1 >= ep) {
 				if (found_count == 0) { /* if solve variable no longer in LHS */
 					for (i = 0; i < n_trhs; i += 2) {
-						if (trhs[i].kind == VARIABLE
-						    && trhs[i].token.variable == v) {
+						if (trhs[i].kind == VARIABLE && trhs[i].token.variable == v) {
 							/* solve variable in RHS */
 							return false;
 						}
@@ -359,7 +358,7 @@
 					if (se_compare(tlhs, n_tlhs, trhs, n_trhs, &diff_sign) && !diff_sign) {
 						error(_("This equation is an identity."));
 #if	!SILENT
-						printf(_("That is, the left equation side is identical to the right equation side.\n"));
+						printf(_("That is, the LHS is identical to the RHS.\n"));
 #endif
 						return -1;
 					}
@@ -383,14 +382,14 @@
 					} else {
 						error(_("There are no possible values for the solve variable."));
 					}
-					return false;
+					return -2;
 				}
 				zflag = (n_trhs == 1 && trhs[0].kind == CONSTANT && trhs[0].token.constant == 0.0);
+				if (zflag) {
+					/* overwrite -0.0 */
+					trhs[0].token.constant = 0.0;
+				}
 				if (need_flip >= found_count) {
-					if (zflag) {
-						/* overwrite -0.0 */
-						trhs[0].token.constant = 0.0;
-					}
 					if (!flip(tlhs, &n_tlhs, trhs, &n_trhs))
 						return false;
 					list_tdebug(2);
@@ -400,7 +399,7 @@
 					goto left_again;
 				}
 				if (worked && !uf_flag) {
-					worked--;
+					worked = false;
 					debug_string(1, _("Unfactoring..."));
 					partial_flag = false;
 					uf_simp(tlhs, &n_tlhs);
@@ -487,14 +486,15 @@
 						    || fabs(numerator) != 1.0 || denominator < 2.0) {
 							continue;
 						}
-						for (j = i - 1; (j >= 0) && tlhs[j].level >= tlhs[i].level; j--) {
+						for (j = i - 1; j >= 0 && tlhs[j].level >= tlhs[i].level; j--) {
 							if (tlhs[j].kind == VARIABLE && tlhs[j].token.variable == v) {
 								if (b1) {
 									if (fabs(b1->token.constant) < fabs(tlhs[i+1].token.constant)) {
 										b1 = &tlhs[i+1];
 									}
-								} else
+								} else {
 									b1 = &tlhs[i+1];
+								}
 								break;
 							}
 						}
@@ -528,9 +528,8 @@
 					return false;
 				if (zero_solved) {
 					qtries++;
-				} else {
-					zero_solved = true;
 				}
+				zero_solved = true;
 				if (quad_solve(v)) {
 					goto left_again;
 				} else {
@@ -681,30 +680,30 @@
  * where "x" is an expression containing passed variable "v",
  * and "n" is a constant.
  *
+ * The equation to solve is in tlhs and trhs, it must be solved for zero.
+ *
  * Return true if successful.
  */
 static int
 quad_solve(v)
-long	v;
+long	v;	/* solve variable */
 {
 	int		i, j, k;
 	token_type	*p1, *p2, *ep;
-	token_type	*x1p, *x2p;
-	token_type	*a1p, *a2p, *a2ep;
+	token_type	*x1p = NULL, *x2p;
+	token_type	*a1p = NULL, *a2p = NULL, *a2ep = NULL;
 	token_type	*b1p, *b2p, *b2ep;
 	token_type	*x1tp, *a1tp;
 	token_type	x1_storage[100];
-	int		nx1;
 	int		op, op2, opx1, opx2;
-	int		found;
-	int		diff_sign;
-	int		len;
-	int		alen, blen;
-	int		aloc;
+	int		found, diff_sign;
+	int		len, alen, blen, aloc, nx1;
 	double		high_power = 0.0;
 
 	uf_simp(trhs, &n_trhs);
-	factorv(trhs, &n_trhs, v);
+	while (factor_plus(trhs, &n_trhs, v, 0.0)) {
+		simp_loop(trhs, &n_trhs);
+	}
 	list_tdebug(1);
 
 	found = false;
@@ -995,7 +994,7 @@
 	} else if (high_power == 4.0) {
 		printf(_("Equation was biquadratic.\n"));
 	} else {
-		printf(_("Equation was a degree %g quadratic.\n"), high_power);
+		printf(_("Equation was a degree %.*g quadratic.\n"), precision, high_power);
 	}
 #endif
 	return true;
@@ -1020,10 +1019,8 @@
 token_type	*side2p;	/* equation side pointer */
 int		*side2np;	/* pointer to the length of "side2p" */
 {
-	int		i;
 	token_type	*p1, *p2, *ep;
-	int		oldn;
-	int		operandn;
+	int		oldn, operandn;
 	double		numerator, denominator;
 	static int	prev_n1, prev_n2;
 	double		d1, d2;
@@ -1048,17 +1045,6 @@
 	case POWER:
 	case MODULUS:
 		break;
-	case FACTORIAL:
-		i = oldn - 2;
-		if (i >= 0 && side1p[i].level == 1 && side1p[i].token.operatr == op) {
-			i = *side2np - 2;
-			if (i >= 0 && side2p[i].level == 1 && side2p[i].token.operatr == op) {
-				debug_string(1, _("Removing factorial from both sides of the equation:"));
-				*side1np -= 2;
-				*side2np -= 2;
-				return true;
-			}
-		}
 	default:
 		return false;
 	}
@@ -1151,7 +1137,7 @@
 		p2++;
 		p2->level = 2;
 		p2->kind = VARIABLE;
-		p2->token.variable = V_INTEGER;
+		parse_var(&p2->token.variable, "integer");
 		p2++;
 		p2->level = 2;
 		p2->kind = OPERATOR;

Modified: branches/vendor/mathomatic/super.c
===================================================================
--- branches/vendor/mathomatic/super.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/super.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
  * Group and combine denominators.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -14,21 +14,21 @@
  * Combine denominators in equation side.
  * This means converting "a/b+c/d" to "(a*d+c*b)/b/d".
  *
- * If start_flag is false, only combine denominators to simplify complex fractions.
+ * If start_flag is 0, only combine denominators to simplify complex fractions.
  *
- * If start_flag is true, always combine denominators.
+ * If start_flag is 1, always combine denominators.
  *
- * If start_flag is 2, combine denominators if they don't have a GCD in common.
- * Note that this wipes out tlhs and trhs.  This prevents making a more complicated
- * algebraic fraction.  This needs to be improved to combine denominators and remove
- * the GCD.
+ * If start_flag is 2, always combine denominators and remove any polynomial GCD between them.
+ * Note that this wipes out tlhs and trhs.  This simplifies all algebraic fractions
+ * into a single simple fraction and prevents making a more complicated (or larger)
+ * algebraic fraction.
  *
  * Return true if equation side was modified.
  */
 int
 super_factor(equation, np, start_flag)
-token_type	*equation;
-int		*np;
+token_type	*equation;	/* pointer to the beginning of the equation side */
+int		*np;		/* pointer to the length of the equation side */
 int		start_flag;
 {
 	int	rv;
@@ -51,8 +51,7 @@
 
 	if (!start_flag) {
 		for (i = loc + 1; i < *np && equation[i].level >= level; i += 2) {
-			if (equation[i].level == level
-			    && equation[i].token.operatr == DIVIDE) {
+			if (equation[i].level == level && equation[i].token.operatr == DIVIDE) {
 				start_flag = true;
 				break;
 			}
@@ -102,27 +101,23 @@
 token_type	*equation;
 int		*np, loc, i1, n1, i2, n2, level, check_flag;
 {
-	int	i, j, k;
-	int	b1, b2;
-	int	len;
-	int	e1, e2;
-	int	op1, op2;
-	int	div_flag1 = false, div_flag2 = false;
+	int		i, j, k;
+	int		b1, b2;
+	int		len;
+	int		e1, e2;
+	int		op1, op2;
+	token_type	*p1, *p2;
+	int		np1, np2;
+	int		div_flag1 = false, div_flag2 = false;
 
 	e1 = i1 + n1;
 	e2 = i2 + n2;
 	op2 = equation[i2-1].token.operatr;
-	switch (op2) {
-	case PLUS:
-	case MINUS:
-		break;
-	default:
-		return false;
-	}
 	if (i1 <= loc) {
 		op1 = PLUS;
-	} else
+	} else {
 		op1 = equation[i1-1].token.operatr;
+	}
 	for (i = i1 + 1; i < e1; i += 2) {
 		if (equation[i].level == level && equation[i].token.operatr == DIVIDE) {
 			div_flag1 = true;
@@ -152,14 +147,24 @@
 	if (!div_flag1 && !div_flag2)
 		return false;
 	if (check_flag && div_flag1 && div_flag2) {
-		if (poly2_gcd(&equation[b1], i - b1, &equation[b2], j - b2, 0L)
-		    || poly2_gcd(&equation[b2], j - b2, &equation[b1], i - b1, 0L)) {
-			return false;
+		if (poly2_gcd(&equation[b1], i - b1, &equation[b2], j - b2, 0L)) {
+			p1 = tlhs;
+			np1 = n_tlhs;
+			p2 = trhs;
+			np2 = n_trhs;
+			goto do_gcd;
 		}
+		if (poly2_gcd(&equation[b2], j - b2, &equation[b1], i - b1, 0L)) {
+			p1 = trhs;
+			np1 = n_trhs;
+			p2 = tlhs;
+			np2 = n_tlhs;
+			goto do_gcd;
+		}
 	}
-	if (n1 + n2 + (i - b1) + (j - b2) + 8 > n_tokens) {
-		error_huge();
-	}
+        if (n1 + n2 + (i - b1) + (j - b2) + 8 > n_tokens) {
+                error_huge();
+        } 
 	if (!div_flag1) {
 		for (k = i1; k < e1; k++)
 			equation[k].level++;
@@ -168,8 +173,8 @@
 		for (k = i2; k < e2; k++)
 			equation[k].level++;
 	}
-	len = (b1 - 1) - i1;
-	blt(scratch, &equation[i1], len * sizeof(*equation));
+	len = b1 - i1 - 1;
+	blt(scratch, &equation[i1], len * sizeof(token_type));
 	if (op1 == MINUS) {
 		scratch[len].level = level;
 		scratch[len].kind = OPERATOR;
@@ -181,7 +186,7 @@
 		len++;
 	}
 	if (div_flag1) {
-		blt(&scratch[len], &equation[i], (e1 - i) * sizeof(*equation));
+		blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
 		len += e1 - i;
 	}
 	if (div_flag2) {
@@ -189,7 +194,7 @@
 		scratch[len].kind = OPERATOR;
 		scratch[len].token.operatr = TIMES;
 		len++;
-		blt(&scratch[len], &equation[b2], (j - b2) * sizeof(*equation));
+		blt(&scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
 		len += j - b2;
 	}
 	for (k = 0; k < len; k++)
@@ -199,10 +204,10 @@
 	scratch[len].token.operatr = op2;
 	len++;
 	k = len;
-	blt(&scratch[len], &equation[i2], (b2 - i2 - 1) * sizeof(*equation));
+	blt(&scratch[len], &equation[i2], (b2 - i2 - 1) * sizeof(token_type));
 	len += b2 - i2 - 1;
 	if (div_flag2) {
-		blt(&scratch[len], &equation[j], (e2 - j) * sizeof(*equation));
+		blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
 		len += e2 - j;
 	}
 	if (div_flag1) {
@@ -210,7 +215,7 @@
 		scratch[len].kind = OPERATOR;
 		scratch[len].token.operatr = TIMES;
 		len++;
-		blt(&scratch[len], &equation[b1], (i - b1) * sizeof(*equation));
+		blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
 		len += i - b1;
 	}
 	for (; k < len; k++)
@@ -221,7 +226,7 @@
 	len++;
 	k = len;
 	if (div_flag1) {
-		blt(&scratch[len], &equation[b1], (i - b1) * sizeof(*equation));
+		blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
 		len += i - b1;
 	}
 	if (div_flag1 && div_flag2) {
@@ -231,29 +236,110 @@
 		len++;
 	}
 	if (div_flag2) {
-		blt(&scratch[len], &equation[b2], (j - b2) * sizeof(*equation));
+		blt(&scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
 		len += j - b2;
 	}
 	for (; k < len; k++)
 		scratch[k].level++;
+end_mess:
 	if (*np + len - n1 - (n2 + 1) > n_tokens) {
 		error_huge();
 	}
 	if (op1 == MINUS) {
 		equation[i1-1].token.operatr = PLUS;
 	}
-	blt(&equation[i2-1], &equation[e2], (*np - e2) * sizeof(*equation));
+	blt(&equation[i2-1], &equation[e2], (*np - e2) * sizeof(token_type));
 	*np -= n2 + 1;
-	blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(*equation));
+	blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(token_type));
 	*np += len - n1;
-	blt(&equation[i1], scratch, len * sizeof(*equation));
+	blt(&equation[i1], scratch, len * sizeof(token_type));
 	return true;
+
+do_gcd:
+	if (5 - i1 + e1 + (2*np2) + b2 - i2 + e2 - j + np1 > n_tokens) {
+		error_huge();
+	}
+	for (k = 0; k < np1; k++) {
+		p1[k].level += level;
+	}
+	for (k = 0; k < np2; k++) {
+		p2[k].level += level;
+	}
+	len = b1 - i1 - 1;
+	blt(scratch, &equation[i1], len * sizeof(token_type));
+	if (op1 == MINUS) {
+		scratch[len].level = level;
+		scratch[len].kind = OPERATOR;
+		scratch[len].token.operatr = TIMES;
+		len++;
+		scratch[len].level = level;
+		scratch[len].kind = CONSTANT;
+		scratch[len].token.constant = -1.0;
+		len++;
+	}
+/*	if (div_flag1) { */
+		blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
+		len += e1 - i;
+/*	} */
+/*	if (div_flag2) { */
+		scratch[len].level = level;
+		scratch[len].kind = OPERATOR;
+		scratch[len].token.operatr = TIMES;
+		len++;
+		blt(&scratch[len], p2, np2 * sizeof(token_type));
+		len += np2;
+/*	} */
+	for (k = 0; k < len; k++)
+		scratch[k].level += 2;
+	scratch[len].level = level + 1;
+	scratch[len].kind = OPERATOR;
+	scratch[len].token.operatr = op2;
+	len++;
+	k = len;
+	blt(&scratch[len], &equation[i2], (b2 - i2 - 1) * sizeof(token_type));
+	len += b2 - i2 - 1;
+/*	if (div_flag2) { */
+		blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
+		len += e2 - j;
+/*	} */
+/*	if (div_flag1) { */
+		scratch[len].level = level;
+		scratch[len].kind = OPERATOR;
+		scratch[len].token.operatr = TIMES;
+		len++;
+		blt(&scratch[len], p1, np1 * sizeof(token_type));
+		len += np1;
+/*	} */
+	for (; k < len; k++)
+		scratch[k].level += 2;
+	scratch[len].level = level;
+	scratch[len].kind = OPERATOR;
+	scratch[len].token.operatr = DIVIDE;
+	len++;
+	k = len;
+/*	if (div_flag1) { */
+		blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
+		len += (i - b1);
+/*	} */
+/*	if (div_flag1 && div_flag2) { */
+		scratch[len].level = level;
+		scratch[len].kind = OPERATOR;
+		scratch[len].token.operatr = TIMES;
+		len++;
+/*	} */
+/*	if (div_flag2) { */
+		blt(&scratch[len], p2, np2 * sizeof(token_type));
+		len += np2;
+/*	} */
+	for (; k < len; k++)
+		scratch[k].level++;
+	goto end_mess;
 }
 
 /*
- * This function is the guts of the "flist" command.
+ * This function is the guts of the display command.
  */
-group_sub(n)
+make_fractions_and_group(n)
 int	n;
 {
 	if (n_lhs[n] <= 0)
@@ -270,7 +356,7 @@
 }
 
 /*
- * Group denominators.
+ * Group denominators together.
  * Grouping here means converting "a/b/c" to "a/(b*c)".
  */
 group_proc(equation, np)
@@ -313,8 +399,7 @@
 				}
 				grouper = true;
 				for (len = i + 2; len < e1; len += 2) {
-					if (equation[len].level == level
-					    && equation[len].token.operatr != DIVIDE)
+					if (equation[len].level == level && equation[len].token.operatr != DIVIDE)
 						break;
 				}
 				len -= i;
@@ -323,9 +408,9 @@
 					edi = i;
 					continue;
 				}
-				blt(scratch, &equation[i], len * sizeof(*equation));
-				blt(&equation[di+len], &equation[di], (i - di) * sizeof(*equation));
-				blt(&equation[di], scratch, len * sizeof(*equation));
+				blt(scratch, &equation[i], len * sizeof(token_type));
+				blt(&equation[di+len], &equation[di], (i - di) * sizeof(token_type));
+				blt(&equation[di], scratch, len * sizeof(token_type));
 				edi += len;
 				i += len - 2;
 			} else {

Deleted: branches/vendor/mathomatic/tasks.txt

Modified: branches/vendor/mathomatic/tests/README.txt
===================================================================
--- branches/vendor/mathomatic/tests/README.txt	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/README.txt	2007-06-24 11:58:26 UTC (rev 1806)
@@ -4,6 +4,6 @@
  	To run all tests, type "mathomatic all".
 	For a short demo, type "mathomatic demo".
 	To play with trig functions, type "mathomatic trig".
+	To play with hyperbolic trig functions, type "mathomatic hypertrig".
 
-Look around and have fun!  Feel free to contribute your Mathomatic scripts, if
-you think they will be interesting to most people.
+Look around and have fun!  Feel free to contribute your Mathomatic scripts.

Modified: branches/vendor/mathomatic/tests/all.in
===================================================================
--- branches/vendor/mathomatic/tests/all.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/all.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,9 +1,9 @@
 read test.in
 read pie.in
 read demo.in
+read limits.in
 read poly.in
 read linear.in
-clear all
 read examples.in
 read test1.in
 read test2.in
@@ -11,12 +11,15 @@
 read simplify.in
 read radius.in
 clear all
+read trig.in
+simplify all
+clear all
 read pyth3d.in
 clear all
 read ellipse.in
 y
-simp
+simplify
 1
 y
-simp symbolic
+simplify symbolic
 quit

Modified: branches/vendor/mathomatic/tests/all.out
===================================================================
--- branches/vendor/mathomatic/tests/all.out	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/all.out	2007-06-24 11:58:26 UTC (rev 1806)
@@ -7,7 +7,7 @@
 #1: y = (x + -)^3
              x
 
-1-> y = (((((a+b)/(b-c))^0.25)+(((b-c)/(a+b))^0.25)+(((a-b)*i#/(b-c))^0.5))*(i#^0.5))^(1/n)
+1-> y = (((((a+b)/(b-c))^0.25)+(((b-c)/(a+b))^0.25)+(((a-b)*i/(b-c))^0.5))*(i^0.5))^(1/n)
 
            (a + b) 1     (b - c) 1     (a - b)*i# 1       1   1
 #2: y = (((-------^-) + (-------^-) + (----------^-))*(i#^-))^-
@@ -87,12 +87,17 @@
 7-> calc
 Solution #1 with sign1 = 1:
  x = 1
+
 Solution #2 with sign1 = -1:
  x = -1
-7-> (2i#)^.5+e#^(pi*i#)
+
+7-> (2i)^.5+e^(pi*i)
+Warning: complex number root approximated, result may be inaccurate.
  answer = i#
-7-> (1-2i#)/(3+4i#)
- answer = -0.2 - (0.4*i#)
+
+7-> (1-2i)/(3+4i)
+ answer = (-0.4*i#) - 0.2
+
 7-> y=x^3
 
 #8: y = x^3
@@ -119,19 +124,20 @@
 1
 Inverse Check: 1
 
-0 +1*i#
+0 +1*i
 Inverse Check: 1
 
 -1
 Inverse Check: 1
 
-0 -1*i#
+0 -1*i
 Inverse Check: 1
 
-11-> factor number -75 10000000000000 12146807
+11-> factor number -75 10000000000000 121468070
 -75 = 3 * 5^2 * -1
 10000000000000 = 2^13 * 5^13
-12146807 = 12146807
+121468070 = 2 * 5 * 12146807
+Finished reading file "fix1.in".
 11-> clear all
 1-> read fix2
 1-> b = (-1^(1/((-1*n)+1)*(2+n)))*(a^(1/((-1*n)+1)))
@@ -148,13 +154,13 @@
         ((y^-------)*((n^-------) - (n^-------)))
             (n - 1)      (n - 1)       (n - 1)
 
-2-> a = (x+(((1/x)+1)*((x^m)+((d+e)/(x^n)/(f+g)))))/(x+1)
+2-> (x+(((1/x)+1)*((x^m)+((a+b)/(x^n)/(c+d)))))/(x+1)
 
-               1                   (d + e)
-        (x + ((- + 1)*((x^m) + ---------------)))
-               x               ((x^n)*(f + g))
-#3: a = -----------------------------------------
-                         (x + 1)
+           1                   (a + b)
+    (x + ((- + 1)*((x^m) + ---------------)))
+           x               ((x^n)*(c + d))
+#3: -----------------------------------------
+                     (x + 1)
 
 3-> simp all
 
@@ -170,13 +176,13 @@
                  (n - 1)
 
 
-                               (1 + x)*(d + e)
-                      ((x^2) + ---------------)
-                               ((x^n)*(f + g))
-#3: a = (x^(m - 1)) + -------------------------
-                             ((x^2) + x)
+                           (b + a)*(x + 1)
+                  ((x^2) + ---------------)
+                           ((x^n)*(c + d))
+#3: (x^(m - 1)) + -------------------------
+                         ((x^2) + x)
 
-3-> #1
+3-> 1
 
                       1
 #1: b = ((-1^n)*a)^-------
@@ -194,7 +200,7 @@
 #1: a = -----------
           (-1^n)
 
-1-> #2
+1-> 2
 
                             1
         (((y^(n - 2))*n)^-------)
@@ -223,6 +229,7 @@
 #4: y = -------------------------
                  (2 - n)
 
+Finished reading file "fix2.in".
 4-> clear all
 1-> read fix5
 1-> a = (b+((c+1)^0.5))^3
@@ -288,69 +295,82 @@
 
 #6: a = (b^2)*((b - c)^3)
 
+Finished reading file "fix5.in".
 6-> clear all
 1-> read fix7
-1-> y = (c+a-b)/(b-a)
+1-> (c+a-b)/(b-a)
 
-        (c + a - b)
-#1: y = -----------
-          (b - a)
+    (c + a - b)
+#1: -----------
+      (b - a)
 
-1-> z = ((d*(b+c))+(a*(e+f)))/(e+f)/(b+c)
+1-> ((d*(b+c))+(a*(e1+f)))/(e1+f)/(b+c)
 
-        ((d*(b + c)) + (a*(e + f)))
-#2: z = ---------------------------
-             ((e + f)*(b + c))
+    ((d*(b + c)) + (a*(e1 + f)))
+#2: ----------------------------
+         ((e1 + f)*(b + c))
 
-2-> a = ((((e^2)+d)*b*((b^2)+2))-e-f)/b/((b^2)+2)/(e+f)
+2-> ((((e1^2)+d)*b*((b^2)+2))-e1-f)/b/((b^2)+2)/(e1+f)
 
-        ((((e^2) + d)*b*((b^2) + 2)) - e - f)
-#3: a = -------------------------------------
-               (b*((b^2) + 2)*(e + f))
+    ((((e1^2) + d)*b*((b^2) + 2)) - e1 - f)
+#3: ---------------------------------------
+           (b*((b^2) + 2)*(e1 + f))
 
-3-> a = ((b*((((e^2)+d)*((b^2)+2))+(b*(e+f))))+e+f)/(e+f)/b/((b^2)+2)
+3-> ((b*((((e1^2)+d)*((b^2)+2))+(b*(e1+f))))+e1+f)/(e1+f)/b/((b^2)+2)
 
-        ((b*((((e^2) + d)*((b^2) + 2)) + (b*(e + f)))) + e + f)
-#4: a = -------------------------------------------------------
-                        ((e + f)*b*((b^2) + 2))
+    ((b*((((e1^2) + d)*((b^2) + 2)) + (b*(e1 + f)))) + e1 + f)
+#4: ----------------------------------------------------------
+                     ((e1 + f)*b*((b^2) + 2))
 
-4-> a = ((1/(x^(1+n)))+(1/(x^n))+(x^(m-1))+(x^m)+x)/(x+1)
+4-> ((1/(x^(1+n)))+(1/(x^n))+(x^(m-1))+(x^m)+x)/(x+1)
 
-              1          1
-        (----------- + ----- + (x^(m - 1)) + (x^m) + x)
-         (x^(1 + n))   (x^n)
-#5: a = -----------------------------------------------
-                            (x + 1)
+          1          1
+    (----------- + ----- + (x^(m - 1)) + (x^m) + x)
+     (x^(1 + n))   (x^n)
+#5: -----------------------------------------------
+                        (x + 1)
 
-5-> simp all
+5-> (1/(a + b)) + (1/(b + c))
 
-           c
-#1: y = ------- - 1
-        (b - a)
+       1         1
+#6: ------- + -------
+    (a + b)   (b + c)
 
+6-> simp all
 
-           d         a
-#2: z = ------- + -------
-        (e + f)   (b + c)
+       c
+#1: ------- - 1
+    (b - a)
 
 
-        ((e^2) + d)          1
-#3: a = ----------- - ---------------
-          (e + f)     ((b^3) + (2*b))
+       d          a
+#2: -------- + -------
+    (e1 + f)   (b + c)
 
 
-        ((e^2) + d)     (1 + (b^2))
-#4: a = ----------- + ---------------
-          (e + f)     ((b^3) + (2*b))
+    (d + (e1^2))          1
+#3: ------------ - ---------------
+      (e1 + f)     ((b^3) + (2*b))
 
 
-           1
-        (----- + (x^m))
-         (x^n)               x
-#5: a = --------------- + -------
-               x          (x + 1)
+    (d + (e1^2))     (1 + (b^2))
+#4: ------------ + ---------------
+      (e1 + f)     ((b^3) + (2*b))
 
-5-> clear all
+
+       1
+    (----- + (x^m))
+     (x^n)               x
+#5: --------------- + -------
+           x          (x + 1)
+
+
+       1         1
+#6: ------- + -------
+    (b + c)   (b + a)
+
+Finished reading file "fix7.in".
+6-> clear all
 1-> read fix8
 1-> a = (((b^2)*(x^2))+(4*(b^2)*x)+(b^2)+(2*(b^3)*x)+(2*(b^3))+(b^4)+(2*b*(x^2))+(2*b*x)+(x^2))/(((b^3)*(x^2))+(2*(b^4)*x)+(b^5))
 
@@ -390,7 +410,7 @@
 #1: a = -----------
            (b^3)
 
-Found polynomial Greatest Common Divisor.  Division simplified.
+Division simplified with polynomial GCD.
 
 #2: a = (x^n) + (z^n)
 
@@ -411,6 +431,7 @@
 #5: a = ---------------------------------^-
                  ((b^n) + (b^m))          2
 
+Finished reading file "fix8.in".
 5-> clear all
 1-> read fix9
 1-> a = ((+/-1000*(b!^4)+/-x)^2)*((1/x)+x)*b
@@ -419,7 +440,7 @@
 #1: a = (((1000*sign1*((b!)^4)) + (sign2*x))^2)*(- + x)*b
                                                  x
 
-1-> a = ((b+(2*i#))^5)
+1-> a = ((b+(2*i))^5)
 
 #2: a = (b + (2*i#))^5
 
@@ -445,13 +466,13 @@
 
 #6: a = ((x^n) - (y^n))^3
 
-6-> val = (((e#*((2*(x^3)) + 24 + (x!) - zy)) - pi)/e#)^2
+6-> val = (((e*((2*(x^3)) + 24 + (x!) - zy)) - pi)/e)^2
 
-          ((e#*((2*(x^3)) + 24 + (x!) - zy)) - pi)
-#7: val = ----------------------------------------^2
+          ((e#*((2*(x^3)) + 24 + (x!) - zy)) - pi#)
+#7: val = -----------------------------------------^2
                              e#
 
-7-> simp all
+7-> simplify all
 
                                                      1
 #1: a = ((x + (1000*sign1*sign2*((b!)^4)))^2)*b*(x + -)
@@ -479,11 +500,11 @@
 #6: a = ((x^n) - (y^n))^3
 
 
-                                        pi
-#7: val = (zy - 24 - (x!) - (2*(x^3)) + --)^2
+                                        pi#
+#7: val = (zy - 24 - (x!) - (2*(x^3)) + ---)^2
                                         e#
 
-7-> flist factor all
+7-> display factor all
 
                                                                   1
 #1: a = ((x + (((2^3)*(5^3))*sign1*sign2*((b!)^(2^2))))^2)*b*(x + -)
@@ -511,11 +532,11 @@
 #6: a = ((x^n) - (y^n))^3
 
 
-                                               pi
-#7: val = (zy - ((2^3)*3) - (x!) - (2*(x^3)) + --)^2
+                                               pi#
+#7: val = (zy - ((2^3)*3) - (x!) - (2*(x^3)) + ---)^2
                                                e#
 
-7-> #2
+7-> 2
 
 #2: a = (b + (2*i#))^5
 
@@ -523,22 +544,24 @@
 
 #8: a = (b^5) - (40*(b^3)) + (80*b)
 
-8-> #2
+8-> 2
 
 #2: a = (b^5) + (10*i#*(b^4)) - (80*i#*(b^2)) + (32*i#) - (40*(b^3)) + (80*b)
 
-2-> imag
+2-> imaginary
 
 #9: a = (10*i#*(b^4)) - (80*i#*(b^2)) + (32*i#)
 
-9-> replace i# with 1
+9-> replace i with 1
 
 #9: a = (10*(b^4)) - (80*(b^2)) + 32
 
+Finished reading file "fix9.in".
+Finished reading file "test.in".
 9-> read pie.in
 9-> clear all
 1-> 
-1-> ; This is the famous Bailey-Borwein-Plouffe algorithm.
+1-> ; This is the famous Bailey-Borwein-Plouffe (BBP) algorithm.
 1-> ; Sum this n = 0 to infinity to compute pi.
 1-> ; This is especially useful for calculating pi in hexadecimal.
 1-> ; One hexadecimal digit of pi is generated with each iteration.
@@ -559,51 +582,55 @@
 
 1-> sum n 0 10 ; Sum as n goes from 0 to 10.
 
-#2: 3.14159265359
+#2: 3.1415926535898
 
 1-> pi ; Verify that the digits are the same.
- answer = 3.14159265359
-1-> 
-1-> ; Sum this n = 0 to infinity to compute (y=e^x):
-1-> 
-1-> x^n/n!
+ answer = 3.1415926535898
 
+1-> x^n/n! ; Sum this n = 0 to infinity to compute (e^x).
+
     (x^n)
 #3: -----
     (n!)
 
-3-> replace x with 1
+3-> replace x with 1 ; Sum this n = 0 to infinity to compute e:
 
      1
 #3: ----
     (n!)
 
-3-> 
-3-> ; Sum this n = 0 to infinity to compute e:
-3-> 
 3-> sum n 0 20 ; Sum as n goes from 0 to 20.
 
-#4: 2.71828182846
+#4: 2.718281828459
 
-3-> e# ; Verify that the digits are the same.
- answer = 2.71828182846
+3-> e ; Verify that the digits are the same.
+ answer = 2.718281828459
+
+Finished reading file "pie.in".
 3-> read demo.in
+3-> ; A small Mathomatic demonstration.
+3-> 
 3-> clear all
 1-> y=x_new^n
 
 #1: y = x_new^n
 
-1-> taylor x_new 1 x_old ; build the root approximation equation
+1-> 0 ; solve for zero
 
-#2: y = (x_old^n) + (n*(x_old^(n - 1))*(x_new - x_old))
+#1: 0 = (x_new^n) - y
 
+1-> taylor x_new 1 x_old ; build the nth root approximation equation
+1 derivative applied.
+
+#2: 0 = (x_old^n) - y + (n*(x_old^(n - 1))*(x_new - x_old))
+
 2-> x_new ; solve for the wanted variable
 
                    (y - (x_old^n))
 #2: x_new = x_old*(--------------- + 1)
                     ((x_old^n)*n)
 
-2-> simplify ; convergent, iterative root approximation equation:
+2-> simplify ; convergent nth root approximation equation:
 
                             y
                        (--------- - 1)
@@ -611,16 +638,8 @@
 #2: x_new = x_old*(1 + ---------------)
                               n
 
-2-> copy ; copy the equation to a new equation space
+2-> replace x_old x_new with x ; make old and new the same
 
-                            y
-                       (--------- - 1)
-                        (x_old^n)
-#3: x_new = x_old*(1 + ---------------)
-                              n
-
-2-> replace x_new x_old with x
-
                   y
                (----- - 1)
                 (x^n)
@@ -635,90 +654,145 @@
           n
 
 2-> 
-2-> ; find the derivative of (1/(x^.5)) the hard way:
-2-> a=(1/(x+l)^.5-1/x^.5)/l
+2-> y=x^(1/3)+x^(2/3) ; a quadratic, cubed root equation
 
-              1          1
-        (----------- - -----)
-                  1       1
-         ((x + l)^-)   (x^-)
-                  2       2
-#4: a = ---------------------
-                  l
-
-4-> limit l 0 ; take the limit as l goes to 0
-Raising both sides to the power of 2 and unfactoring...
-Removing possible solution: "l = 0".
-Equation was quadratic.
-Raising both sides to the power of 2 and unfactoring...
-
-           -1
-#4: a = ---------
-              3
-        (2*(x^-))
-              2
-
-4-> integrate x ; take the anti-derivative and see if it's right
-
-          1
-#5: a = -----
-           1
-        (x^-)
-           2
-
-5-> 
-5-> ; an inverse cubic equation:
-5-> y=x^(1/3)+x^(2/3)
-
            1       2
-#6: y = (x^-) + (x^-)
+#3: y = (x^-) + (x^-)
            3       3
 
-6-> x ; solve for x
-Equation was a degree 0.666667 quadratic.
+3-> x ; solve for x
+Equation was a degree 0.66666666666667 quadratic.
 
                               1
         -1*(1 + (((1 + (4*y))^-)*sign1))
                               2
-#6: x = --------------------------------^3
+#3: x = --------------------------------^3
                        2
 
-6-> simplify
+3-> expand
 
+                        1                                 3
+        -3*((1 + (4*y))^-)*sign1             ((1 + (4*y))^-)*sign1
+                        2          1   3*y                2
+#3: x = ------------------------ - - - --- - ---------------------
+                   8               2    2              8
+
+3-> simplify
+
                                 1
         -1*((sign1*((1 + (4*y))^-)*(y + 1)) + 1 + (3*y))
                                 2
-#6: x = ------------------------------------------------
+#3: x = ------------------------------------------------
                                2
 
-6-> 
-6-> e#^x
+3-> 
+3-> e^x ; exponential function
 
-#7: e#^x
+#4: e#^x
 
-7-> taylor x 10 0 ; generate a 10th order taylor series from the exponential function
+4-> taylor x 10 0 ; generate a 10th order taylor series of the exponential function
+10 derivatives applied.
 
             (x^2)   (x^3)   (x^4)   (x^5)   (x^6)   (x^7)   (x^8)   (x^9)    (x^10)
-#8: 1 + x + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------ + -------
+#5: 1 + x + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------ + -------
               2       6      24      120     720    5040    40320   362880   3628800
 
-8-> laplace x ; do a Laplace transform on it
+5-> laplace x ; do a Laplace transform on it
 
     1     1       1       1       1       1       1       1       1       1        1
-#9: - + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------ + ------
+#6: - + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------ + ------
     x   (x^2)   (x^3)   (x^4)   (x^5)   (x^6)   (x^7)   (x^8)   (x^9)   (x^10)   (x^11)
 
-9-> laplace inverse x ; undo the transform
+6-> laplace inverse x ; undo the transform
 
-             (x^2)   (x^3)   (x^4)   (x^5)   (x^6)   (x^7)   (x^8)   (x^9)    (x^10)
-#10: 1 + x + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------ + -------
-               2       6      24      120     720    5040    40320   362880   3628800
+            (x^2)   (x^3)   (x^4)   (x^5)   (x^6)   (x^7)   (x^8)   (x^9)    (x^10)
+#7: 1 + x + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------ + -------
+              2       6      24      120     720    5040    40320   362880   3628800
 
-10-> read poly.in
-10-> ; Combine 3 quadratic polynomials with 3 unknown coefficients (a, b, c).
-10-> ; Solve for a, b, and c.
-10-> 
-10-> clear all
+Finished reading file "demo.in".
+7-> read limits.in
+7-> ; Tests for the experimental limit command.
+7-> 
+7-> clear all
+1-> ; find the derivative of 1/(x^.5) using the difference quotient:
+1-> (1/(x+h)^.5-1/x^.5)/h
+
+          1          1
+    (----------- - -----)
+              1       1
+     ((x + h)^-)   (x^-)
+              2       2
+#1: ---------------------
+              h
+
+1-> limit h 0 ; take the limit as h goes to 0
+Raising both sides to the power of 2 and unfactoring...
+Removing possible solution: "h = 0".
+Equation was quadratic.
+Raising both sides to the power of 2 and unfactoring...
+
+                -1
+#2: answer = ---------
+                   3
+             (2*(x^-))
+                   2
+
+2-> integrate x ; take the anti-derivative to see if it's right
+
+               1
+#3: answer = -----
+                1
+             (x^-)
+                2
+
+3-> 
+3-> ; test infinity limits:
+3-> (3x+100-a)/(x-b)
+
+    ((3*x) + 100 - a)
+#4: -----------------
+         (x - b)
+
+4-> limit x inf ; answer should be 3
+
+#5: answer = 3
+
+5-> 
+5-> (((x^2) - (5*x) + 6)^(1/2)) - x
+
+                         1
+#6: (((x^2) - (5*x) + 6)^-) - x
+                         2
+
+6-> limit x inf ; answer should be -5/2
+Raising both sides to the power of 2 and unfactoring...
+Equation was quadratic.
+
+             -5
+#7: answer = --
+             2
+
+7-> 
+7-> x*((x^2+1)^.5-x)
+
+                    1
+#8: x*((((x^2) + 1)^-) - x)
+                    2
+
+8-> limit x inf ; answer should be 1/2
+Raising both sides to the power of 2 and unfactoring...
+Equation was biquadratic.
+
+             1
+#9: answer = -
+             2
+
+Finished reading file "limits.in".
+9-> read poly.in
+9-> ; Combine 3 quadratic polynomials with 3 unknown coefficients (a, b, c).
+9-> ; Solve for a, b, and c.
+9-> 
+9-> clear all
 1-> y1=a+b*x1+c*x1^2
 
 #1: y1 = a + (b*x1) + (c*(x1^2))
@@ -736,7 +810,7 @@
 #2: y2 = a + (b*x2) + (c*(x2^2))
 
 2-> eliminate a ; eliminate variable (a) from the current equation
-Solving equation #1 for (a)...
+Solving equation #1 for (a) and substituting into the current equation...
 
 #2: y2 = (b*x2) - (x1*(b + (c*x1))) + y1 + (c*(x2^2))
 
@@ -745,8 +819,8 @@
 #3: y3 = a + (b*x3) + (c*(x3^2))
 
 3-> eliminate a b ; eliminate variables (a) and (b)
-Solving equation #1 for (a)...
-Solving equation #2 for (b)...
+Solving equation #1 for (a) and substituting into the current equation...
+Solving equation #2 for (b) and substituting into the current equation...
 
          (y1 - y2 + (c*((x2^2) - (x1^2))))*x3        (y1 - y2 + (c*((x2^2) - (x1^2))))
 #3: y3 = ------------------------------------ - (x1*(--------------------------------- + (c*x1))) + y1 + (c*(x3^2))
@@ -765,7 +839,7 @@
                     (x1 - x2)
 
 2-> eliminate c using 3 ; eliminate (c) using equation number 3
-Solving equation #3 for (c)...
+Solving equation #3 for (c) and substituting into the current equation...
 
                    ((y2*(x1 - x3)) + (y1*(x3 - x2)) - (y3*(x1 - x2)))*((x2^2) - (x1^2))
         (y1 - y2 + --------------------------------------------------------------------)
@@ -778,30 +852,53 @@
 #1: a = -1*((x1*(b + (c*x1))) - y1)
 
 1-> eliminate b c ; the final elimination
-Solving equation #2 for (b)...
-Solving equation #3 for (c)...
+Solving equation #2 for (b) and substituting into the current equation...
+Solving equation #3 for (c) and substituting into the current equation...
 
                  ((((x1*((x2^2) + (x1*(x3 - x2)))) - (x3*((x2^2) + (x3*(x1 - x2)))))*(y1 - y2)) + (((y2*(x1 - x3)) + (y1*(x3 - x2)) - (y3*(x1 - x2)))*((x2^2) - (x1^2))))         ((y2*(x1 - x3)) + (y1*(x3 - x2)) - (y3*(x1 - x2)))*x1
 #1: a = -1*((x1*(-------------------------------------------------------------------------------------------------------------------------------------------------------- + -----------------------------------------------------------------)) - y1)
                                                       (((x1*((x2^2) + (x1*(x3 - x2)))) - (x3*((x2^2) + (x3*(x1 - x2)))))*(x1 - x2))                                         ((x1*((x2^2) + (x1*(x3 - x2)))) - (x3*((x2^2) + (x3*(x1 - x2)))))
 
-1-> simplify quick all ; list all solutions
-Found polynomial Greatest Common Divisor.  Division simplified.
+1-> simplify all ; list all solutions
+Division simplified with polynomial GCD.
 
-        (((x1^2)*((x3*y2) - (x2*y3))) + (x1*(((x2^2)*y3) - ((x3^2)*y2))) + (y1*((x2*(x3^2)) - ((x2^2)*x3))))
-#1: a = ----------------------------------------------------------------------------------------------------
-                                          ((x2 - x1)*(x3 - x1)*(x3 - x2))
+                       y1*((x2*(x3^2)) - ((x2^2)*x3))
+         ((x2*x1*y3) + ------------------------------)
+                                 (x2 - x1)               x3*x1*y2
+        (--------------------------------------------- - ---------)
+                           (x3 - x1)                     (x2 - x1)
+#1: a = -----------------------------------------------------------
+                                 (x3 - x2)
 
 
-        (((x1^2)*(y2 - y3)) + ((x2^2)*(y3 - y1)) + ((x3^2)*(y1 - y2)))
+        (((x1^2)*(y2 - y3)) + ((x3^2)*(y1 - y2)) + ((x2^2)*(y3 - y1)))
 #2: b = --------------------------------------------------------------
                        ((x2 - x1)*(x3 - x1)*(x2 - x3))
 
 
-        ((x1*(y2 - y3)) + (x3*(y1 - y2)) + (x2*(y3 - y1)))
-#3: c = --------------------------------------------------
-                 ((x2 - x1)*(x3 - x1)*(x3 - x2))
+         (y1 - y2)   (y3 - y2)
+        (--------- + ---------)
+         (x2 - x1)   (x3 - x2)
+#3: c = -----------------------
+               (x3 - x1)
 
+1-> fraction all ; convert to simple fractions
+
+        ((x1*((x2*y3*(x2 - x1)) - (x3*y2*(x3 - x1)))) + (y1*((x2*(x3^2)) - ((x2^2)*x3))))
+#1: a = ---------------------------------------------------------------------------------
+                                 ((x3 - x1)*(x2 - x1)*(x3 - x2))
+
+
+        (((x1^2)*(y2 - y3)) + ((x3^2)*(y1 - y2)) + ((x2^2)*(y3 - y1)))
+#2: b = --------------------------------------------------------------
+                       ((x2 - x1)*(x3 - x1)*(x2 - x3))
+
+
+        (((y1 - y2)*(x3 - x2)) + ((y3 - y2)*(x2 - x1)))
+#3: c = -----------------------------------------------
+                ((x2 - x1)*(x3 - x2)*(x3 - x1))
+
+Finished reading file "poly.in".
 1-> read linear.in
 1-> ; Combine 3 simultaneous linear equations with 3 unknowns (x, y, z).
 1-> ; Solve for all 3 unknowns using the "eliminate" command.
@@ -824,7 +921,7 @@
 #2: d2 = (a2*x) + (b2*y) + (c2*z)
 
 2-> eliminate x
-Solving equation #1 for (x)...
+Solving equation #1 for (x) and substituting into the current equation...
 
                   a2*((b1*y) + (c1*z) - d1)
 #2: d2 = (b2*y) - ------------------------- + (c2*z)
@@ -835,8 +932,8 @@
 #3: d3 = (a3*x) + (b3*y) + (c3*z)
 
 3-> eliminate x y
-Solving equation #1 for (x)...
-Solving equation #2 for (y)...
+Solving equation #1 for (x) and substituting into the current equation...
+Solving equation #2 for (y) and substituting into the current equation...
 
                                                                 b1*((z*((c2*a1) - (a2*c1))) + (a2*d1) - (d2*a1))
                                                             a3*(------------------------------------------------ + (c1*z) - d1)
@@ -850,14 +947,14 @@
 #3: z = --------------------------------------------------------------------------------
         ((b3*((c2*a1) - (a2*c1))) + (a3*((b2*c1) - (b1*c2))) + (c3*((a2*b1) - (a1*b2))))
 
-3-> 2
+3-> 2 ; select equation number 2
 
         ((z*((c2*a1) - (a2*c1))) + (a2*d1) - (d2*a1))
 #2: y = ---------------------------------------------
                      ((a2*b1) - (b2*a1))
 
 2-> eliminate z using 3
-Solving equation #3 for (z)...
+Solving equation #3 for (z) and substituting into the current equation...
 
          ((d3*((a2*b1) - (a1*b2))) + (b3*((d2*a1) - (a2*d1))) + (a3*((b2*d1) - (b1*d2))))*((c2*a1) - (a2*c1))
         (---------------------------------------------------------------------------------------------------- + (a2*d1) - (d2*a1))
@@ -865,15 +962,15 @@
 #2: y = --------------------------------------------------------------------------------------------------------------------------
                                                            ((a2*b1) - (b2*a1))
 
-2-> 1
+2-> 1 ; select equation number 1
 
         -1*((b1*y) + (c1*z) - d1)
 #1: x = -------------------------
                    a1
 
 1-> eliminate y z
-Solving equation #2 for (y)...
-Solving equation #3 for (z)...
+Solving equation #2 for (y) and substituting into the current equation...
+Solving equation #3 for (z) and substituting into the current equation...
 
             b1*((((d3*((a2*b1) - (a1*b2))) + (b3*((d2*a1) - (a2*d1))) + (a3*((b2*d1) - (b1*d2))))*((c2*a1) - (a2*c1))) + (((b3*((c2*a1) - (a2*c1))) + (a3*((b2*c1) - (b1*c2))) + (c3*((a2*b1) - (a1*b2))))*((a2*d1) - (d2*a1))))   c1*((d3*((a2*b1) - (a1*b2))) + (b3*((d2*a1) - (a2*d1))) + (a3*((b2*d1) - (b1*d2))))
         -1*(-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + ----------------------------------------------------------------------------------- - d1)
@@ -897,9 +994,11 @@
 #3: z = --------------------------------------------------------------------------------
         ((a1*((b3*c2) - (c3*b2))) + (c1*((a3*b2) - (b3*a2))) + (b1*((c3*a2) - (a3*c2))))
 
+Finished reading file "linear.in".
+1-> read examples.in
 1-> clear all
-1-> read examples.in
-1-> ; A semicolon ";" is the line comment character.
+1-> ; A semicolon is the line comment character.
+1-> 
 1-> c^2=a^2+b^2 ; The Pythagorean Theorem.  Equations are entered by just typing them in.
 
 #1: c^2 = (a^2) + (b^2)
@@ -910,13 +1009,13 @@
 #1: c = (((a^2) + (b^2))^-)*sign1
                          2
 
-1-> ; "sign" variables may be +1 or -1.
+1-> ; "sign" variables are special variables and may only be +1 or -1.
 1-> 
 1-> code c ; Generate C code.
 c = (pow(((a * a) + (b * b)), (1.0 / 2.0)) * sign1);
 1-> 
 1-> code python; Generate Python code.
-c = ((((a * a) + (b * b)) ** (1.0 / 2.0)) * sign1);
+c = ((((a * a) + (b * b)) ** (1.0 / 2.0)) * sign1)
 1-> 
 1-> b ; Solve for b.
 
@@ -924,51 +1023,68 @@
 #1: b = (((c^2) - (a^2))^-)*sign2
                          2
 
-1-> a=b+1/b ; a simple quadratic
+1-> y=x+1/x ; A simple quadratic.
 
             1
-#2: a = b + -
-            b
+#2: y = x + -
+            x
 
-2-> b ; Solve for b.
+2-> x ; Solve for x.
 Equation was quadratic.
 
                            1
-        (a - ((((a^2) - 4)^-)*sign1))
+        (y - ((((y^2) - 4)^-)*sign1))
                            2
-#2: b = -----------------------------
+#2: x = -----------------------------
                       2
 
-2-> a ; Solve for a.
+2-> y ; Solve for y to check the answer.
 Raising both sides to the power of 2 and unfactoring...
 
-        ((b^2) + 1)
-#2: a = -----------
-             b
+        ((x^2) + 1)
+#2: y = -----------
+             x
 
 2-> simplify
 
             1
-#2: a = b + -
-            b
+#2: y = x + -
+            x
 
-2-> 27^y=9 ; Mathomatic is also handy as an advanced calculator.
+2-> extrema x ; Determine the location of the maximums and minimums of this equation.
 
-#3: 27^y = 9
+#3: x = sign1
 
-3-> y ; Solve for y.
+3-> calculate ; Approximate numerical expressions and expand sign variables.
+Solution #1 with sign1 = 1:
+ x = 1
 
+Solution #2 with sign1 = -1:
+ x = -1
+
+3-> ; Mathomatic is also handy as an advanced calculator:
+3-> 1+2
+ answer = 3
+
+3-> 2^.5 ; the square root of 2, rounded to 14 digits
+ answer = 1.4142135623731
+
+3-> 27^y=9
+
+#4: 27^y = 9
+
+4-> y ; Solve for y.
+
         2
-#3: y = -
+#4: y = -
         3
 
-3-> e#^(pi*i#) ; Calculate e^(pi*i)
- answer = -1
-3-> read test1.in
-3-> clear all
+Finished reading file "examples.in".
+4-> read test1.in
+4-> clear all
 1-> y = .6666 - (4*(((10*(pi^2)*(r^3)/((d^2)*g*m*epsilon)) - 1)^(1/2))/15)
 
-                       10*(pi^2)*(r^3)        1
+                      10*(pi#^2)*(r^3)        1
                  4*((------------------- - 1)^-)
                      ((d^2)*g*m*epsilon)      2
 #1: y = 0.6666 - -------------------------------
@@ -976,23 +1092,24 @@
 
 1-> simp
 
-                         pi
-                     10*(--^2)*(r^3)
-                         d                1
-                 4*((--------------- - 1)^-)
-                      (g*m*epsilon)       2
-#1: y = 0.6666 - ---------------------------
-                             15
+                         pi#
+                     10*(---^2)*(r^3)
+                          d                1
+                 4*((---------------- - 1)^-)
+                      (g*m*epsilon)        2
+#1: y = 0.6666 - ----------------------------
+                              15
 
 1-> simp symbolic
 
-                     10*(pi^2)*(r^3)          1
-                 4*((--------------- - (d^2))^-)
-                      (g*m*epsilon)           2
-#1: y = 0.6666 - -------------------------------
-                             (15*d)
+                     10*(pi#^2)*(r^3)          1
+                 4*((---------------- - (d^2))^-)
+                      (g*m*epsilon)            2
+#1: y = 0.6666 - --------------------------------
+                              (15*d)
 
 1-> 
+Finished reading file "test1.in".
 1-> read test2.in
 1-> clear all
 1-> y=(a/2)^2/b/4
@@ -1024,10 +1141,10 @@
             2
 
 5-> elim l m n y
-Solving equation #2 for (l)...
-Solving equation #3 for (m)...
-Solving equation #4 for (n)...
-Solving equation #1 for (y)...
+Solving equation #2 for (l) and substituting into the current equation...
+Solving equation #3 for (m) and substituting into the current equation...
+Solving equation #4 for (n) and substituting into the current equation...
+Solving equation #1 for (y) and substituting into the current equation...
 
                  (a^2)                                1                            1
         ((f*(b - ------)) + (z*(a - f)))*(-------------------------- - --------------------------)
@@ -1070,7 +1187,7 @@
 #5: f = ---------------------------------------------------------------------------------------------------------------------------------------
                                                                            2
 
-5-> #6
+5-> 6
 
            4*((f*((16*(b^3)) - (b*(a^2)))) + (16*(b^2)*z*(a - f)))*(a - f)
 #6: o = ---------------------------------------------------------------------
@@ -1096,10 +1213,19 @@
 
 7-> simp symb
 
+                               1            (a^2)
+            sign2*((o + (o^2))^-)*((16*b) - -----)
+                               2              b
+#7: f = a + --------------------------------------
+                         (8*(1 + o))
+
+7-> simp symb
+
                        o    1           (a^2)
 #7: f = a + (sign2*(-------^-)*((2*b) - -----))
                     (1 + o) 2           (8*b)
 
+Finished reading file "test2.in".
 7-> read test3.in
 7-> ; Combine 3 linear equations in 3 unknowns (x, y, z)
 7-> ; and solve for every variable to test Mathomatic.
@@ -1117,24 +1243,24 @@
 
 #3: b3 = (a6*x) + (a7*y) + (a8*z)
 
-3-> #2
+3-> 2
 
 #2: b2 = (a3*x) + (a4*y) + (a5*z)
 
 2-> eliminate x using 1
-Solving equation #1 for (x)...
+Solving equation #1 for (x) and substituting into the current equation...
 
                   a3*((a1*y) + (a2*z) - b1)
 #2: b2 = (a4*y) - ------------------------- + (a5*z)
                              a0
 
-2-> #3
+2-> 3
 
 #3: b3 = (a6*x) + (a7*y) + (a8*z)
 
 3-> eliminate x y
-Solving equation #1 for (x)...
-Solving equation #2 for (y)...
+Solving equation #1 for (x) and substituting into the current equation...
+Solving equation #2 for (y) and substituting into the current equation...
 
                                                                 a1*((z*((a5*a0) - (a3*a2))) + (a3*b1) - (b2*a0))
                                                             a6*(------------------------------------------------ + (a2*z) - b1)
@@ -1157,7 +1283,7 @@
 4-> compare 3 with 4
 Comparing #3 with #4...
 Equations are identical.
-4-> #3
+4-> 3
 
         ((b3*((a3*a1) - (a0*a4))) + (a7*((b2*a0) - (a3*b1))) + (a6*((a4*b1) - (a1*b2))))
 #3: z = --------------------------------------------------------------------------------
@@ -1244,6 +1370,7 @@
 3-> compare 3 with 4
 Comparing #3 with #4...
 Equations are identical.
+Finished reading file "test3.in".
 3-> read simplify.in
 3-> ; Some simplification tests Mathomatic has always been able to do.
 3-> 
@@ -1263,9 +1390,11 @@
     ((a - b)*(a - c))   ((b - c)*(b - a))   ((c - a)*(c - b))
 
 2-> simplify
-Found polynomial Greatest Common Divisor.  Division simplified.
+Division simplified with polynomial GCD.
+Division simplified with polynomial GCD.
+Division simplified with polynomial GCD.
 
-#2: a + b + c
+#2: b + a + c
 
 2-> (x^6+a^6)*(x+1)/((x^6+a^6)*(x^2-a^2)+a^2*x^2*(x^4-a^4))+a^2*x^2*(x+1)/(x^6-a^6-a^2*x^2*(x^2-a^2))
 
@@ -1274,8 +1403,7 @@
     ((((x^6) + (a^6))*((x^2) - (a^2))) + ((a^2)*(x^2)*((x^4) - (a^4))))   ((x^6) - (a^6) - ((a^2)*(x^2)*((x^2) - (a^2))))
 
 3-> simplify
-Found polynomial Greatest Common Divisor.  Division simplified.
-Found polynomial Greatest Common Divisor.  Division simplified.
+Division simplified with polynomial GCD.
 
         (x + 1)
 #3: ---------------
@@ -1300,7 +1428,7 @@
     ((((p*(x^2)) + ((k + t)*x) + r)^2) - (((p*(x^2)) + ((k - t)*x) + r)^2))
 
 5-> simplify
-Found polynomial Greatest Common Divisor.  Division simplified.
+Division simplified with polynomial GCD.
 
     -1*s
 #5: ----
@@ -1324,8 +1452,8 @@
                     (1 + -----------)
                          (y - x + 1)
 
-6-> simplify
-Found polynomial Greatest Common Divisor.  Division simplified.
+6-> simplify ; Any complex fraction can be reduced to a simple fraction.
+Division simplified with polynomial GCD.
 
                         1
 #6: -----------------------------------------
@@ -1349,6 +1477,7 @@
     (((x^2) - 1)^-)
                  2
 
+Finished reading file "simplify.in".
 7-> read radius.in
 7-> clear all
 1-> ; Some more fun formulas.  These are very similar to Heron's formula
@@ -1370,7 +1499,7 @@
                        s
 
 2-> elim s using 1
-Solving equation #1 for (s)...
+Solving equation #1 for (s) and substituting into the current equation...
 
                         (a + b + c)       (a + b + c)       (a + b + c)
            (a + b + c)*(----------- - a)*(----------- - b)*(----------- - c)
@@ -1406,7 +1535,7 @@
                                         2
 
 3-> elim s using 1
-Solving equation #1 for (s)...
+Solving equation #1 for (s) and substituting into the current equation...
 
                                           a*b*c
 #3: r = -------------------------------------------------------------------------
@@ -1424,7 +1553,99 @@
         (((2*(((a^2)*((b^2) + (c^2))) + ((b*c)^2))) - (a^4) - (b^4) - (c^4))^-)
                                                                              2
 
+Finished reading file "radius.in".
 3-> clear all
+1-> read trig.in
+1-> ; Trigonometric functions as complex exponentials.
+1-> ; Based on Euler's identity: e^(i*x) = cos(x) + i*sin(x)
+1-> ; "x" is an angle in radians.
+1-> 
+1-> ; Unity relationship: sin(x)^2 + cos(x)^2 = 1
+1-> 
+1-> ; sin(x) (sine of x) = cos(pi/2 - x)
+1-> sin=(e^(i*x)-e^(-i*x))/(2i)
+
+          ((e#^(i#*x)) - (e#^(-1*i#*x)))
+#1: sin = ------------------------------
+                      (2*i#)
+
+1-> 
+1-> ; cos(x) (cosine of x) = sin(pi/2 - x)
+1-> cos=(e^(i*x)+e^(-i*x))/2
+
+          ((e#^(i#*x)) + (e#^(-1*i#*x)))
+#2: cos = ------------------------------
+                        2
+
+2-> 
+2-> ; tan(x) (tangent of x) = sin(x)/cos(x) = cot(pi/2 - x)
+2-> tan=(e^(i*x)-e^(-i*x))/(i*(e^(i*x)+e^(-i*x)))
+
+            ((e#^(i#*x)) - (e#^(-1*i#*x)))
+#3: tan = -----------------------------------
+          (i#*((e#^(i#*x)) + (e#^(-1*i#*x))))
+
+3-> 
+3-> ; cot(x) (cotangent of x) = cos(x)/sin(x) = tan(pi/2 - x)
+3-> cot=i*(e^(i*x)+e^(-i*x))/(e^(i*x)-e^(-i*x))
+
+          i#*((e#^(i#*x)) + (e#^(-1*i#*x)))
+#4: cot = ---------------------------------
+           ((e#^(i#*x)) - (e#^(-1*i#*x)))
+
+4-> 
+4-> ; sec(x) (secant of x) = 1/cos(x) = csc(pi/2 - x)
+4-> sec=2/(e^(i*x)+e^(-i*x))
+
+                        2
+#5: sec = ------------------------------
+          ((e#^(i#*x)) + (e#^(-1*i#*x)))
+
+5-> 
+5-> ; csc(x) (cosecant of x) = 1/sin(x) = sec(pi/2 - x)
+5-> csc=2i/(e^(i*x)-e^(-i*x))
+
+                       2*i#
+#6: csc = ------------------------------
+          ((e#^(i#*x)) - (e#^(-1*i#*x)))
+
+Finished reading file "trig.in".
+6-> simplify all
+
+                   1
+          i#*(----------- - (e#^(i#*x)))
+              (e#^(i#*x))
+#1: sin = ------------------------------
+                        2
+
+
+                              1
+          ((e#^(i#*x)) + -----------)
+                         (e#^(i#*x))
+#2: cos = ---------------------------
+                       2
+
+
+                       2
+#3: tan = i#*(------------------- - 1)
+              ((e#^(2*i#*x)) + 1)
+
+
+                           2
+#4: cot = i#*(1 + -------------------)
+                  ((e#^(2*i#*x)) - 1)
+
+
+             2*(e#^(i#*x))
+#5: sec = -------------------
+          ((e#^(2*i#*x)) + 1)
+
+
+           2*i#*(e#^(i#*x))
+#6: csc = -------------------
+          ((e#^(2*i#*x)) - 1)
+
+6-> clear all
 1-> read pyth3d.in
 1-> ; This input to Mathomatic arrives at the distance between two points
 1-> ; in 3D space from the Pythagorean theorem (distance between two points
@@ -1439,7 +1660,7 @@
 #2: d^2 = (l^2) + ((z1 - z2)^2)
 
 2-> eliminate l ; Combine the two equations.
-Solving equation #1 for (l)...
+Solving equation #1 for (l) and substituting into the current equation...
 
 #2: d^2 = ((x1 - x2)^2) + ((y1 - y2)^2) + ((z1 - z2)^2)
 
@@ -1450,12 +1671,13 @@
                                                          2
 
 2-> ; The coordinate of point 1 is (x1, y1, z1) and point 2 is (x2, y2, z2).
+Finished reading file "pyth3d.in".
 2-> clear all
 1-> read ellipse.in
-1-> ; This is a general equation for an ellipse that was
-1-> ; created using the rule that the sum of the distances (k)
-1-> ; from any point on the perimeter (x, y) to the two foci,
-1-> ; (x1, y1) and (x2, y2), is a constant.
+1-> ; This is a general equation for an ellipse that was created using the rule
+1-> ; that the sum of the distances (k) from any point on the perimeter (x, y)
+1-> ; to the two foci: (x1, y1) and (x2, y2), is a constant (k).  This can
+1-> ; represent any ellipse of any orientation on the Cartesian plane.
 1-> 
 1-> k = ((((x1-x)^2)+((y1-y)^2))^0.5)+((((x2-x)^2)+((y2-y)^2))^0.5)
 
@@ -1464,7 +1686,7 @@
                                        2                                   2
 
 1-> 
-1-> ; The equation for an ellipse centered at the origin:
+1-> ; The equation for an ellipse centered at the origin of the Cartesian plane:
 1-> 
 1-> 1=x^2/radius1^2+y^2/radius2^2
 
@@ -1472,13 +1694,14 @@
 #2: 1 = ----------- + -----------
         (radius1^2)   (radius2^2)
 
+Finished reading file "ellipse.in".
 2-> y
 
                   x             1
 #2: y = ((-1*((-------^2) - 1))^-)*sign1*radius2
                radius1          2
 
-2-> simp
+2-> simplify
 
                   x        1
 #2: y = ((1 - (-------^2))^-)*sign1*radius2
@@ -1503,10 +1726,10 @@
 #1: y = -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                          (4*((y1*(y1 - (2*y2))) - (k^2) + (y2^2)))
 
-1-> simp symbolic
+1-> simplify symbolic
 
                                                                                                                                                                                                        1
-                   ((k*((((y1^2) + (2*((x1*(x2 - (2*x))) - (y1*y2))) - (k^2) + (x1^2) + (4*((x^2) - (x*x2))) + (x2^2) + (y2^2))*((y1^2) - (2*((y1*y2) + (x1*x2))) + (y2^2) + (x1^2) - (k^2) + (x2^2)))^-)*sign2) + ((y2 - y1)*((2*x) - x1 - x2)*(x1 - x2)))
+                   ((k*((((y1^2) + (2*((x1*(x2 - (2*x))) - (y1*y2))) - (k^2) + (x1^2) + (4*((x^2) - (x*x2))) + (x2^2) + (y2^2))*((y1^2) - (2*((y1*y2) + (x1*x2))) + (y2^2) + (x1^2) + (x2^2) - (k^2)))^-)*sign2) + ((y2 - y1)*((2*x) - x1 - x2)*(x1 - x2)))
                                                                                                                                                                                                        2
         (y1 + y2 + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------)
                                                                                                                     ((y1^2) - (k^2) + (y2^2) - (2*y1*y2))

Modified: branches/vendor/mathomatic/tests/cubic.in
===================================================================
--- branches/vendor/mathomatic/tests/cubic.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/cubic.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,22 +1,14 @@
 clear all
-; The book says this is the general cubic equation,
-; but I have found it doesn't work unless there is exactly one
-; real root and 2 complex roots.
+; The 3 solutions for x in the cubic equation:
+0 = x^3 + a1 x^2 + a2 x + a3
 
-; Solutions for (x) in the cubic equation:
-0 = x^3 + a1x^2 + a2x + a3
-
 q=(3a2-a1^2)/9
 r=(9a1*a2-27a3-2a1^3)/54
 s=(r+(q^3+r^2)^.5)^(1/3)
 t=(r-(q^3+r^2)^.5)^(1/3)
-x1=s+t-a1/3
-elim s t q r
-x2=-(s+t)/2-a1/3+sign*i#*3^.5*(s-t)/2
-elim s t q r
+real_root=s+t-a1/3
+eliminate s t q r
+; Next determine the other 2 roots from the real root:
+other_roots=(-a1-real_root+sign*(-3*real_root^2-2*a1*real_root+a1^2-4*a2)^.5)/2
+eliminate real_root
 clear 2-5
-; x1 = the real root
-; x2 = the 2 complex roots
-
-; The optimize command works well with these equations.
-; Try "optimize all".

Added: branches/vendor/mathomatic/tests/cyclic_heron.in

Modified: branches/vendor/mathomatic/tests/demo.in
===================================================================
--- branches/vendor/mathomatic/tests/demo.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/demo.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,23 +1,20 @@
+; A small Mathomatic demonstration.
+
 clear all
 y=x_new^n
-taylor x_new 1 x_old ; build the root approximation equation
+0 ; solve for zero
+taylor x_new 1 x_old ; build the nth root approximation equation
 x_new ; solve for the wanted variable
-simplify ; convergent, iterative root approximation equation:
-copy ; copy the equation to a new equation space
-replace x_new x_old with x
+simplify ; convergent nth root approximation equation:
+replace x_old x_new with x ; make old and new the same
 x ; make sure it is correct by solving for x
 
-; find the derivative of (1/(x^.5)) the hard way:
-a=(1/(x+l)^.5-1/x^.5)/l
-limit l 0 ; take the limit as l goes to 0
-integrate x ; take the anti-derivative and see if it's right
-
-; an inverse cubic equation:
-y=x^(1/3)+x^(2/3)
+y=x^(1/3)+x^(2/3) ; a quadratic, cubed root equation
 x ; solve for x
+expand
 simplify
 
-e#^x
-taylor x 10 0 ; generate a 10th order taylor series from the exponential function
+e^x ; exponential function
+taylor x 10 0 ; generate a 10th order taylor series of the exponential function
 laplace x ; do a Laplace transform on it
 laplace inverse x ; undo the transform

Modified: branches/vendor/mathomatic/tests/ellipse.in
===================================================================
--- branches/vendor/mathomatic/tests/ellipse.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/ellipse.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,10 +1,10 @@
-; This is a general equation for an ellipse that was
-; created using the rule that the sum of the distances (k)
-; from any point on the perimeter (x, y) to the two foci,
-; (x1, y1) and (x2, y2), is a constant.
+; This is a general equation for an ellipse that was created using the rule
+; that the sum of the distances (k) from any point on the perimeter (x, y)
+; to the two foci: (x1, y1) and (x2, y2), is a constant (k).  This can
+; represent any ellipse of any orientation on the Cartesian plane.
 
 k = ((((x1-x)^2)+((y1-y)^2))^0.5)+((((x2-x)^2)+((y2-y)^2))^0.5)
 
-; The equation for an ellipse centered at the origin:
+; The equation for an ellipse centered at the origin of the Cartesian plane:
 
 1=x^2/radius1^2+y^2/radius2^2

Modified: branches/vendor/mathomatic/tests/examples.in
===================================================================
--- branches/vendor/mathomatic/tests/examples.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/examples.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,17 +1,23 @@
-; A semicolon ";" is the line comment character.
+clear all
+; A semicolon is the line comment character.
+
 c^2=a^2+b^2 ; The Pythagorean Theorem.  Equations are entered by just typing them in.
 c ; Solve for c.  Equations are solved by typing in the variable.
-; "sign" variables may be +1 or -1.
+; "sign" variables are special variables and may only be +1 or -1.
 
 code c ; Generate C code.
 
 code python; Generate Python code.
 
 b ; Solve for b.
-a=b+1/b ; a simple quadratic
-b ; Solve for b.
-a ; Solve for a.
+y=x+1/x ; A simple quadratic.
+x ; Solve for x.
+y ; Solve for y to check the answer.
 simplify
-27^y=9 ; Mathomatic is also handy as an advanced calculator.
+extrema x ; Determine the location of the maximums and minimums of this equation.
+calculate ; Approximate numerical expressions and expand sign variables.
+; Mathomatic is also handy as an advanced calculator:
+1+2
+2^.5 ; the square root of 2, rounded to 14 digits
+27^y=9
 y ; Solve for y.
-e#^(pi*i#) ; Calculate e^(pi*i)

Modified: branches/vendor/mathomatic/tests/finance.in
===================================================================
--- branches/vendor/mathomatic/tests/finance.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/finance.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,18 +1,17 @@
 ; Here are some financial formulas that can be "read" into Mathomatic:
 
 ; Compound Interest Future Value Formula:
-f_v1 = p_v*(1+i)^n
+f_v1 = p_v*(1+interest_rate)^n
 
 ; Annuity Formula:
-f_v2 = p*(((1+i)^n-1)/i)
+f_v2 = payment*(((1+interest_rate)^n-1)/interest_rate)
 ; Next we will combine these to produce that Amortized Loan Formula.
 pause
 ; Amortized Loan Formula (Mortgage Formula):
 f_v1 = f_v2
 eliminate all
-p ; solve for p
+payment ; solve for payment per period
 ; p_v = present value
 ; f_v = future value (maturity value)
-; i = interest rate per period
+; interest_rate = interest rate per period (1 = 100%)
 ; n = number of periods
-; p = payment per period

Deleted: branches/vendor/mathomatic/tests/fix1

Added: branches/vendor/mathomatic/tests/fix1.in

Deleted: branches/vendor/mathomatic/tests/fix2

Added: branches/vendor/mathomatic/tests/fix2.in

Deleted: branches/vendor/mathomatic/tests/fix5

Added: branches/vendor/mathomatic/tests/fix5.in

Deleted: branches/vendor/mathomatic/tests/fix7

Added: branches/vendor/mathomatic/tests/fix7.in

Deleted: branches/vendor/mathomatic/tests/fix8

Added: branches/vendor/mathomatic/tests/fix8.in

Deleted: branches/vendor/mathomatic/tests/fix9

Added: branches/vendor/mathomatic/tests/fix9.in

Modified: branches/vendor/mathomatic/tests/heron.in
===================================================================
--- branches/vendor/mathomatic/tests/heron.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/heron.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,6 +1,9 @@
 ; This is Heron's formula for the area
 ; of any triangle, given side lengths a, b, and c.
 
+; See the files "cyclic_heron.in" and "trapezoid_heron.in"
+; for two derivations of this formula.
+
 2s = a+b+c
 area = (s*(s-a)*(s-b)*(s-c))^.5
 eliminate s

Modified: branches/vendor/mathomatic/tests/hypertrig.in
===================================================================
--- branches/vendor/mathomatic/tests/hypertrig.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/hypertrig.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,19 +1,19 @@
 ; Definitions for hyperbolic trigonometry.
 
 ; sinh(x); hyperbolic sine of x
-sinh=(e#^x-e#^-x)/2
+sinh=(e^x-e^-x)/2
 
 ; cosh(x); hyperbolic cosine of x
-cosh=(e#^x+e#^-x)/2
+cosh=(e^x+e^-x)/2
 
 ; tanh(x); hyperbolic tangent of x
-tanh=(e#^x-e#^-x)/(e#^x+e#^-x)
+tanh=(e^x-e^-x)/(e^x+e^-x)
 
 ; coth(x); hyperbolic cotangent of x
-coth=(e#^x+e#^-x)/(e#^x-e#^-x)
+coth=(e^x+e^-x)/(e^x-e^-x)
 
 ; sech(x); hyperbolic secant of x
-sech=2/(e#^x+e#^-x)
+sech=2/(e^x+e^-x)
 
 ; csch(x); hyperbolic cosecant of x
-csch=2/(e#^x-e#^-x)
+csch=2/(e^x-e^-x)

Added: branches/vendor/mathomatic/tests/limits.in

Modified: branches/vendor/mathomatic/tests/linear.in
===================================================================
--- branches/vendor/mathomatic/tests/linear.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/linear.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -10,8 +10,8 @@
 3 ; select equation number 3
 eliminate x y
 z ; solve for z
-2
+2 ; select equation number 2
 eliminate z using 3
-1
+1 ; select equation number 1
 eliminate y z
 simplify all ; list all solutions

Modified: branches/vendor/mathomatic/tests/pie.in
===================================================================
--- branches/vendor/mathomatic/tests/pie.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/pie.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,6 +1,6 @@
 clear all
 
-; This is the famous Bailey-Borwein-Plouffe algorithm.
+; This is the famous Bailey-Borwein-Plouffe (BBP) algorithm.
 ; Sum this n = 0 to infinity to compute pi.
 ; This is especially useful for calculating pi in hexadecimal.
 ; One hexadecimal digit of pi is generated with each iteration.
@@ -9,13 +9,7 @@
 simplify
 sum n 0 10 ; Sum as n goes from 0 to 10.
 pi ; Verify that the digits are the same.
-
-; Sum this n = 0 to infinity to compute (y=e^x):
-
-x^n/n!
-replace x with 1
-
-; Sum this n = 0 to infinity to compute e:
-
+x^n/n! ; Sum this n = 0 to infinity to compute (e^x).
+replace x with 1 ; Sum this n = 0 to infinity to compute e:
 sum n 0 20 ; Sum as n goes from 0 to 20.
-e# ; Verify that the digits are the same.
+e ; Verify that the digits are the same.

Modified: branches/vendor/mathomatic/tests/poly.in
===================================================================
--- branches/vendor/mathomatic/tests/poly.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/poly.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -14,4 +14,5 @@
 eliminate c using 3 ; eliminate (c) using equation number 3
 1 ; select equation number 1
 eliminate b c ; the final elimination
-simplify quick all ; list all solutions
+simplify all ; list all solutions
+fraction all ; convert to simple fractions

Modified: branches/vendor/mathomatic/tests/simplify.in
===================================================================
--- branches/vendor/mathomatic/tests/simplify.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/simplify.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -12,6 +12,6 @@
 ((p*x^2+(k-s)*x+r)^2-(p*x^2+(k+s)*x+r)^2)/((p*x^2+(k+t)*x+r)^2-(p*x^2+(k-t)*x+r)^2)
 simplify
 (1 - (1-(y+1)/(x+y+1)) / (1-x/(x+y+1))) / ((y+1)^2 - x / (1+x/(y-x+1))*(x*(y+1)/(y-x+1) - x))
-simplify
+simplify ; Any complex fraction can be reduced to a simple fraction.
 ((2*((x*(x + (((x^2) - 1)^(1/2)))) - 1)) + 1)/((2*x*((x^2) - 1)) + ((((x^2) - 1)^(1/2))*((2*(x^2)) - 1)))
 simplify ; A good simplification resulting from trying to rationalize the denominator.

Modified: branches/vendor/mathomatic/tests/test2.in
===================================================================
--- branches/vendor/mathomatic/tests/test2.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/test2.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -9,7 +9,8 @@
 copy
 f
 simp symb
-#6
+6
 deri z
 f
 simp symb
+simp symb

Modified: branches/vendor/mathomatic/tests/test3.in
===================================================================
--- branches/vendor/mathomatic/tests/test3.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/test3.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -5,14 +5,14 @@
 b1=a0*x+a1*y+a2*z
 b2=a3*x+a4*y+a5*z
 b3=a6*x+a7*y+a8*z
-#2
+2
 eliminate x using 1
-#3
+3
 eliminate x y
 z
 z = ((((a0*a4)-(a1*a3))*b3)+(a6*((-1.0*a4*b1)+(a1*b2)))+(a7*((a3*b1)-(a0*b2))))/((a6*((-1.0*a4*a2)+(a1*a5)))+(a8*((a0*a4)-(a1*a3)))+(a7*((a3*a2)-(a0*a5))))
 compare 3 with 4
-#3
+3
 b1
 b2
 b3

Added: branches/vendor/mathomatic/tests/trapezoid_heron.in

Modified: branches/vendor/mathomatic/tests/trig.in
===================================================================
--- branches/vendor/mathomatic/tests/trig.in	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/tests/trig.in	2007-06-24 11:58:26 UTC (rev 1806)
@@ -5,19 +5,19 @@
 ; Unity relationship: sin(x)^2 + cos(x)^2 = 1
 
 ; sin(x) (sine of x) = cos(pi/2 - x)
-sin=(e#^(i#*x)-e#^(-i#*x))/(2i#)
+sin=(e^(i*x)-e^(-i*x))/(2i)
 
 ; cos(x) (cosine of x) = sin(pi/2 - x)
-cos=(e#^(i#*x)+e#^(-i#*x))/2
+cos=(e^(i*x)+e^(-i*x))/2
 
-; tan(x) (tangent of x) = sin(x)/cos(x)
-tan=(e#^(i#*x)-e#^(-i#*x))/(i#*(e#^(i#*x)+e#^(-i#*x)))
+; tan(x) (tangent of x) = sin(x)/cos(x) = cot(pi/2 - x)
+tan=(e^(i*x)-e^(-i*x))/(i*(e^(i*x)+e^(-i*x)))
 
-; cot(x) (cotangent of x) = 1/tan(x)
-cot=i#*(e#^(i#*x)+e#^(-i#*x))/(e#^(i#*x)-e#^(-i#*x))
+; cot(x) (cotangent of x) = cos(x)/sin(x) = tan(pi/2 - x)
+cot=i*(e^(i*x)+e^(-i*x))/(e^(i*x)-e^(-i*x))
 
-; sec(x) (secant of x) = 1/cos(x)
-sec=2/(e#^(i#*x)+e#^(-i#*x))
+; sec(x) (secant of x) = 1/cos(x) = csc(pi/2 - x)
+sec=2/(e^(i*x)+e^(-i*x))
 
-; csc(x) (cosecant of x) = 1/sin(x)
-csc=2i#/(e#^(i#*x)-e#^(-i#*x))
+; csc(x) (cosecant of x) = 1/sin(x) = sec(pi/2 - x)
+csc=2i/(e^(i*x)-e^(-i*x))

Modified: branches/vendor/mathomatic/unfactor.c
===================================================================
--- branches/vendor/mathomatic/unfactor.c	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/unfactor.c	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 /*
- * Algebraic manipulator unfactorizing (expanding) routines.
+ * Mathomatic unfactorizing (expanding) routines.
  *
- * Copyright (c) 1987-2005 George Gesslein II.
+ * Copyright (C) 1987-2007 George Gesslein II.
  */
 
 #include "includes.h"
@@ -12,7 +12,7 @@
  * Totally unfactor equation side and simplify.
  */
 uf_simp(equation, np)
-token_type	*equation;	/* equation side pointer */
+token_type	*equation;	/* pointer to beginning of equation side */
 int		*np;		/* pointer to length of equation side */
 {
 	if (*np == 0)
@@ -285,8 +285,8 @@
 	double		d1, d2;
 
 	switch (equation[loc].token.operatr) {
+	case TIMES:
 	case DIVIDE:
-	case TIMES:
 		if (ii != 1)
 			break;
 		for (i = b1 + 1; i < e1; i += 2) {
@@ -315,14 +315,14 @@
 				if (len + (eb1 - b1) + (i - b2) + (e1 - be1) + 1 > n_tokens) {
 					error_huge();
 				}
-				blt(&scratch[len], &equation[b1], (eb1 - b1) * sizeof(*equation));
+				blt(&scratch[len], &equation[b1], (eb1 - b1) * sizeof(token_type));
 				j = len;
 				len += (eb1 - b1);
 				for (; j < len; j++)
 					scratch[j].level++;
-				blt(&scratch[len], &equation[b2], (i - b2) * sizeof(*equation));
+				blt(&scratch[len], &equation[b2], (i - b2) * sizeof(token_type));
 				len += (i - b2);
-				blt(&scratch[len], &equation[be1], (e1 - be1) * sizeof(*equation));
+				blt(&scratch[len], &equation[be1], (e1 - be1) * sizeof(token_type));
 				j = len;
 				len += (e1 - be1);
 				for (; j < len; j++)
@@ -341,9 +341,9 @@
 					if (*np - (e1 - b1) + len > n_tokens) {
 						error_huge();
 					}
-					blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(*equation));
+					blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(token_type));
 					*np += len - (e1 - b1);
-					blt(&equation[b1], scratch, len * sizeof(*equation));
+					blt(&equation[b1], scratch, len * sizeof(token_type));
 					return true;
 				}
 			}
@@ -367,9 +367,9 @@
 				if (len + (i - b2) + (e1 - loc) + 1 > n_tokens) {
 					error_huge();
 				}
-				blt(&scratch[len], &equation[b2], (i - b2) * sizeof(*equation));
+				blt(&scratch[len], &equation[b2], (i - b2) * sizeof(token_type));
 				len += (i - b2);
-				blt(&scratch[len], &equation[loc], (e1 - loc) * sizeof(*equation));
+				blt(&scratch[len], &equation[loc], (e1 - loc) * sizeof(token_type));
 				j = len;
 				len += (e1 - loc);
 				for (; j < len; j++)
@@ -388,9 +388,9 @@
 					if (*np - (e1 - b1) + len > n_tokens) {
 						error_huge();
 					}
-					blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(*equation));
+					blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(token_type));
 					*np += len - (e1 - b1);
-					blt(&equation[b1], scratch, len * sizeof(*equation));
+					blt(&equation[b1], scratch, len * sizeof(token_type));
 					return true;
 				}
 			}
@@ -414,11 +414,11 @@
 					error_huge();
 				}
 				j = len;
-				blt(&scratch[len], &equation[b1], (loc + 1 - b1) * sizeof(*equation));
+				blt(&scratch[len], &equation[b1], (loc + 1 - b1) * sizeof(token_type));
 				len += (loc + 1 - b1);
 				for (; j < len; j++)
 					scratch[j].level++;
-				blt(&scratch[len], &equation[b2], (i - b2) * sizeof(*equation));
+				blt(&scratch[len], &equation[b2], (i - b2) * sizeof(token_type));
 				len += (i - b2);
 				if (i < e1) {
 					scratch[len].level = level;
@@ -438,9 +438,9 @@
 					if (*np - (e1 - b1) + len > n_tokens) {
 						error_huge();
 					}
-					blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(*equation));
+					blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(token_type));
 					*np += len - (e1 - b1);
-					blt(&equation[b1], scratch, len * sizeof(*equation));
+					blt(&equation[b1], scratch, len * sizeof(token_type));
 					return true;
 				}
 			}
@@ -519,7 +519,7 @@
 		equation[j].level++;
 	}
 	i++;
-	blt(&equation[i+2], &equation[i], (*np - i) * sizeof(*equation));
+	blt(&equation[i+2], &equation[i], (*np - i) * sizeof(token_type));
 	*np += 2;
 	equation[i].level = level + 1;
 	equation[i].kind = CONSTANT;
@@ -607,7 +607,7 @@
 	for (k = j; k < i; k++) {
 		equation[k].level++;
 	}
-	blt(&equation[j+2], &equation[j], (*np - j) * sizeof(*equation));
+	blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type));
 	*np += 2;
 	equation[j].level = level + 1;
 	equation[j].kind = CONSTANT;
@@ -641,7 +641,7 @@
 					if ((*np + 2) > n_tokens) {
 						error_huge();
 					}
-					blt(&equation[i+3], &equation[i+1], (*np - (i + 1)) * sizeof(*equation));
+					blt(&equation[i+3], &equation[i+1], (*np - (i + 1)) * sizeof(token_type));
 					*np += 2;
 					equation[i].token.constant = -equation[i].token.constant;
 					i++;
@@ -693,10 +693,11 @@
 					equation[i+3].token.constant -= 1.0;
 					blt(&equation[i+2], &equation[i], (*np - i) * sizeof(token_type));
 					*np += 2;
-					equation[i+1].level = level - 1;
-					equation[i+1].kind = CONSTANT;
-					equation[i+1].token.constant = equation[i+3].token.constant;
-					i += 2;
+					i++;
+					equation[i].level = level - 1;
+					equation[i].kind = CONSTANT;
+					equation[i].token.constant = equation[i+2].token.constant;
+					i++;
 				} else {
 					equation[i].token.operatr = TIMES;
 					equation[i+1].token.constant = 1.0 / equation[i+1].token.constant;

Modified: branches/vendor/mathomatic/zipsrc
===================================================================
--- branches/vendor/mathomatic/zipsrc	2007-06-24 11:42:36 UTC (rev 1805)
+++ branches/vendor/mathomatic/zipsrc	2007-06-24 11:58:26 UTC (rev 1806)
@@ -1,7 +1,7 @@
 #!/bin/sh
-# Create a zip file containing the Mathomatic source distribution.
+# Create a zip file containing the Mathomatic source distribution with no object files and no binary executables.
 
 rm -f ~/am.zip
-rm -f lib/*.o
-zip -r ~/am.zip *.c *.h makefile* compile* *.txt VERSION COPYING mathomatic.* zipsrc doc primes tests lib fact >/dev/null
+rm -f lib/*.o lib/*.a factorial/*.pyc
+zip -r ~/am.zip *.c *.h makefile* compile* *.txt VERSION COPYING mathomatic.* zipsrc doc primes tests lib factorial hard_stuff >/dev/null
 echo ~/am.zip created.




More information about the dslinux-commit mailing list