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 "—".
-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 (>) may be appended to any command line,
-followed by a file name. This will redirect command output
-to a file. Two greater-than symbols (>>) next to each other
+A greater-than character (>) 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 (>>) next to each other
will <strong>append</strong> command output to a file.
For example:
-<pre>
+<pre class="indent">
list export all >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-> 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-> 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-> 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-> 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-> 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->
</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: ";>".
+
+<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-> ; This input to Mathomatic arrives at the distance between two points
1-> ; in 3D space from the Pythagorean theorem (distance between two points
1-> ; 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-> 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-> 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-> 1/x+1/y+1/z
+
+ 1 1 1
+#1: - + - + -
+ x y z
+
+1-> fraction
+
+ (((y + x)*z) + (x*y))
+#1: ---------------------
+ (x*y*z)
+
+1-> simplify
+
+ 1 1 1
+#1: - + - + -
+ x y z
+
+1->
+</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 >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-> (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-> 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-> 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-> ; Compute the derivative of (x^.5) using limits:
-1-> a=((x+h)^.5-x^.5)/h
+<pre class="sample">
+1-> 2x/(x+1)
- 1 1
- (((x + h)^-) - (x^-))
- 2 2
-#1: a = ---------------------
- h
+ 2*x
+#1: -------
+ (x + 1)
-1-> limit h 0
-Raising both sides to the power of 2 and unfactoring...
-Removing possible solution: "h = 0".
+1-> limit x inf ; take the limit as x goes to infinity
- 1
-#1: a = ---------
- 1
- (2*(x^-))
- 2
+#2: answer = 2
-1->
+2->
</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-> 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-> 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-> 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-> 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-> (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-> 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->
@@ -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-> (x+2^.5)^3 ; an irrational polynomial with repeated factors
+
+ 1
+#1: (x + (2^-))^3
+ 2
+
+1-> unfactor ; multiply it out
+
+ 1 1
+#1: (x^3) + (3*(x^2)*(2^-)) + (6*x) + (2*(2^-))
+ 2 2
+
+1-> simplify ; put it back together, since factored is its simplest form
+
+ 1
+#1: (x + (2^-))^3
+ 2
+
+1->
+</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-> 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-> 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-> 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 © 2005 George Gesslein II
-</font>
+<font color="red">Copyright © 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’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’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’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>−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>−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 "help" 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 "help" 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 "www.mathomatic.org".</p>
+<p>Documentation is available in HTML format, see the
+documentation directory or the web site
+"www.mathomatic.org".</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 "set".</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 <gesslein at panix.com>.</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 <gesslein at panix.com></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-> 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 ±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 ±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-> 170!
+ answer = 7.2574156153081e+306
+
+1-> 171!
+ answer = 171!
+
+1->
+</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 © 2005 George Gesslein II
-</font>
+<font color="red">Copyright © 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, "—");
+ } 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