Made reentrant by moving all globals/static variables to a struct and passing it where needed

This commit is contained in:
mingodad 2019-09-22 19:09:46 +02:00
parent 6eb4cc1674
commit 0b512b8c06
27 changed files with 5723 additions and 5976 deletions

746
am.c

File diff suppressed because it is too large Load Diff

28
am.h
View File

@ -170,20 +170,20 @@ enum language_list {
/* Debugging macros: */
#if SILENT
#define list_esdebug(level, en) { ; } /* Display an equation space. */
#define list_tdebug(level) { ; } /* Display the temporary equation (e.g.: when solving). */
#define side_debug(level, p1, n1) { ; } /* Display any expression. */
#define debug_string(level, str) { ; } /* Display any ASCII string. */
#define list_esdebug(mathomatic, level, en) { ; } /* Display an equation space. */
#define list_tdebug(mathomatic, level) { ; } /* Display the temporary equation (e.g.: when solving). */
#define side_debug(mathomatic, level, p1, n1) { ; } /* Display any expression. */
#define debug_string(mathomatic, level, str) { ; } /* Display any ASCII string. */
#else
#define list_esdebug(level, en) list_debug(level, lhs[en], n_lhs[en], rhs[en], n_rhs[en])
#define list_tdebug(level) list_debug(level, tlhs, n_tlhs, trhs, n_trhs)
#define side_debug(level, p1, n1) list_debug(level, p1, n1, NULL, 0)
#define debug_string(level, str) { if (debug_level >= (level)) fprintf(gfp, "%s\n", str); }
#define list_esdebug(mathomatic, level, en) list_debug(mathomatic, level, mathomatic->lhs[en], mathomatic->n_lhs[en], mathomatic->rhs[en], mathomatic->n_rhs[en])
#define list_tdebug(mathomatic, level) list_debug(mathomatic, level, mathomatic->tlhs, mathomatic->n_tlhs, mathomatic->trhs, mathomatic->n_trhs)
#define side_debug(mathomatic, level, p1, n1) list_debug(mathomatic, level, p1, n1, NULL, 0)
#define debug_string(mathomatic, level, str) { if (mathomatic->debug_level >= (level)) fprintf(mathomatic->gfp, "%s\n", str); }
#endif
/* The correct ways to determine if equation number "en" (origin 0) contains an expression or equation. */
#define empty_equation_space(en) ((en) < 0 || (en) >= n_equations || n_lhs[(en)] <= 0)
#define equation_space_is_equation(en) ((en) >= 0 && (en) < n_equations && n_lhs[(en)] > 0 && n_rhs[(en)] > 0)
#define empty_equation_space(mathomatic, en) ((en) < 0 || (en) >= mathomatic->n_equations || mathomatic->n_lhs[(en)] <= 0)
#define equation_space_is_equation(mathomatic, en) ((en) >= 0 && (en) < mathomatic->n_equations && mathomatic->n_lhs[(en)] > 0 && mathomatic->n_rhs[(en)] > 0)
/*
* The following are macros for displaying help text.
@ -192,10 +192,10 @@ enum language_list {
* This is helpful when the output device has less than 80 text character columns.
*/
#if NOT80COLUMNS
#define SP(str) fprintf(gfp, "%s ", str) /* display part of a paragraph, separated with spaces (Space Paragraph) */
#define EP(str) fprintf(gfp, "%s\n", str) /* display the end of a paragraph (End Paragraph) */
#define SP(mathomatic, str) fprintf(mathomatic->gfp, "%s ", str) /* display part of a paragraph, separated with spaces (Space Paragraph) */
#define EP(mathomatic, str) fprintf(mathomatic->gfp, "%s\n", str) /* display the end of a paragraph (End Paragraph) */
#else /* Otherwise the following only works nicely with 80 column or wider screens; */
/* all strings passed to it should be less than 80 columns if possible, so it doesn't wrap around. */
#define SP(str) fprintf(gfp, "%s\n", str)
#define EP(str) fprintf(gfp, "%s\n", str)
#define SP(mathomatic, str) fprintf(mathomatic->gfp, "%s\n", str)
#define EP(mathomatic, str) fprintf(mathomatic->gfp, "%s\n", str)
#endif

2
blt.h
View File

@ -40,7 +40,7 @@ int cnt;
if (cnt == 0) {
return dest;
} else {
error_bug("blt() cnt < 0");
error_bug(mathomatic, "blt() cnt < 0");
}
}
if (src == dest) {

2777
cmds.c

File diff suppressed because it is too large Load Diff

125
complex.c
View File

@ -41,8 +41,7 @@ double x, y, *radiusp, *thetap;
* The roots command.
*/
int
roots_cmd(cp)
char *cp;
roots_cmd(MathoMatic * mathomatic, char *cp)
{
#define MAX_ROOT 10000.0 /* Root limit needed because more roots become more inaccurate and take longer to check. */
@ -56,40 +55,40 @@ char *cp;
do_repeat:
if (*cp == '\0') {
my_strlcpy(prompt_str, _("Enter root (positive integer): "), sizeof(prompt_str));
if ((cp = get_string(buf, sizeof(buf))) == NULL)
my_strlcpy(mathomatic->prompt_str, _("Enter root (positive integer): "), sizeof(mathomatic->prompt_str));
if ((cp = get_string(mathomatic, buf, sizeof(buf))) == NULL)
return false;
}
root = strtod(cp, &cp);
if ((*cp && *cp != ',' && !isspace(*cp)) || !isfinite(root) || root < 0.0 || root > MAX_ROOT || fmod(root, 1.0) != 0.0) {
error(_("Root invalid or out of range."));
error(mathomatic, _("Root invalid or out of range."));
printf(_("Root must be a positive integer less than or equal to %.0f.\n"), MAX_ROOT);
return false;
}
cp = skip_comma_space(cp);
if (*cp == '\0') {
my_strlcpy(prompt_str, _("Enter real part (X): "), sizeof(prompt_str));
if ((cp = get_string(buf, sizeof(buf))) == NULL)
my_strlcpy(mathomatic->prompt_str, _("Enter real part (X): "), sizeof(mathomatic->prompt_str));
if ((cp = get_string(mathomatic, buf, sizeof(buf))) == NULL)
return false;
}
c.re = strtod(cp, &cp);
if (*cp && *cp != ',' && !isspace(*cp)) {
error(_("Number expected."));
error(mathomatic, _("Number expected."));
return false;
}
cp = skip_comma_space(cp);
if (*cp == '\0') {
my_strlcpy(prompt_str, _("Enter imaginary part (Y): "), sizeof(prompt_str));
if ((cp = get_string(buf, sizeof(buf))) == NULL)
my_strlcpy(mathomatic->prompt_str, _("Enter imaginary part (Y): "), sizeof(mathomatic->prompt_str));
if ((cp = get_string(mathomatic, buf, sizeof(buf))) == NULL)
return false;
}
c.im = strtod(cp, &cp);
if (*cp) {
error(_("Number expected."));
error(mathomatic, _("Number expected."));
return false;
}
if (c.re == 0.0 && c.im == 0.0) {
return repeat_flag;
return mathomatic->repeat_flag;
}
/* convert to polar coordinates */
errno = 0;
@ -97,14 +96,14 @@ do_repeat:
if (root) {
radius_root = pow(radius, 1.0 / root);
}
check_err();
fprintf(gfp, _("\nThe polar coordinates are:\n%.*g amplitude and\n%.*g radians (%.*g degrees).\n\n"),
precision, radius, precision, theta, precision, theta * 180.0 / M_PI);
check_err(mathomatic);
fprintf(mathomatic->gfp, _("\nThe polar coordinates are:\n%.*g amplitude and\n%.*g radians (%.*g degrees).\n\n"),
mathomatic->precision, radius, mathomatic->precision, theta, mathomatic->precision, 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);
fprintf(mathomatic->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(mathomatic->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 */
@ -112,14 +111,14 @@ do_repeat:
c2.im = radius_root * sin((theta + 2.0 * k * M_PI) / root);
complex_fixup(&c2);
if (c2.re || c2.im == 0.0) {
fprintf(gfp, "%.12g ", c2.re);
fprintf(mathomatic->gfp, "%.12g ", c2.re);
}
if (c2.im) {
fprintf(gfp, "%+.12g*i", c2.im);
fprintf(mathomatic->gfp, "%+.12g*i", c2.im);
}
fprintf(gfp, "\n");
fprintf(mathomatic->gfp, "\n");
#if !SILENT
if (debug_level <= 0) {
if (mathomatic->debug_level <= 0) {
continue;
}
check = c2;
@ -138,7 +137,7 @@ do_repeat:
#endif
}
}
if (repeat_flag)
if (mathomatic->repeat_flag)
goto do_repeat;
return true;
}
@ -152,9 +151,9 @@ do_repeat:
* Return true if the equation side was modified.
*/
int
complex_root_simp(equation, np)
token_type *equation; /* equation side pointer */
int *np; /* pointer to length of equation side */
complex_root_simp(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* equation side pointer */
//int *np; /* pointer to length of equation side */
{
int i, j;
int level;
@ -170,12 +169,12 @@ start_over:
for (j = i + 2; j < *np && equation[j].level >= level; j += 2)
;
len = j - (i + 1);
if (!parse_complex(&equation[i+1], len, &p))
if (!parse_complex(mathomatic, &equation[i+1], len, &p))
continue;
for (j = i - 1; j >= 0 && equation[j].level >= level; j--)
;
j++;
if (!parse_complex(&equation[j], i - j, &c))
if (!parse_complex(mathomatic, &equation[j], i - j, &c))
continue;
if (c.im == 0.0 && p.im == 0.0)
continue;
@ -186,8 +185,8 @@ start_over:
printf("(%.14g+%.14gi)^(%.14g+%.14gi) = %.14g+%.14gi\n", c.re, c.im, p.re, p.im, r.re, r.im);
#endif
if (*np + 5 - (i - j) > n_tokens) {
error_huge();
if (*np + 5 - (i - j) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
if ((j + 5) != i) {
blt(&equation[j+5], &equation[i], (*np - i) * sizeof(token_type));
@ -217,7 +216,7 @@ start_over:
goto start_over;
}
if (modified) {
debug_string(1, _("Complex number roots approximated."));
debug_string(mathomatic, 1, _("Complex number roots approximated."));
}
return modified;
}
@ -228,15 +227,15 @@ start_over:
* Return true if anything was approximated.
*/
int
approximate_complex_roots(equation, np)
token_type *equation; /* equation side pointer */
int *np; /* pointer to length of equation side */
approximate_complex_roots(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* equation side pointer */
//int *np; /* pointer to length of equation side */
{
int rv = false;
for (;;) {
elim_loop(equation, np);
if (!complex_root_simp(equation, np))
elim_loop(mathomatic, equation, np);
if (!complex_root_simp(mathomatic, equation, np))
break;
rv = true;
}
@ -250,10 +249,10 @@ int *np; /* pointer to length of equation side */
* Return true if successful, with the floating point constant returned in *dp.
*/
int
get_constant(p1, n, dp)
token_type *p1; /* expression pointer */
int n; /* length of expression */
double *dp; /* pointer to returned double */
get_constant(MathoMatic* mathomatic, token_type *p1, int n, double *dp)
//token_type *p1; /* expression pointer */
//int n; /* length of expression */
//double *dp; /* pointer to returned double */
{
int i, j;
int level;
@ -262,7 +261,7 @@ double *dp; /* pointer to returned double */
#if DEBUG
if (n < 1 || (n & 1) != 1) {
error_bug("Call to get_constant() has invalid expression length.");
error_bug(mathomatic, "Call to get_constant() has invalid expression length.");
}
#endif
if (n == 1) {
@ -280,30 +279,30 @@ double *dp; /* pointer to returned double */
}
} else if (n >= 3) {
level = p1[1].level;
if (!get_constant(p1, 1, &d1))
if (!get_constant(mathomatic, p1, 1, &d1))
return false;
for (i = 1; i < n; i = j) {
if (p1[i].kind != OPERATOR || p1[i].level > level) {
#if DEBUG
error_bug("Possible error in get_constant().");
error_bug(mathomatic, "Possible error in get_constant().");
#endif
return false;
}
level = p1[i].level;
for (j = i + 2; j < n && p1[j].level > level; j += 2)
;
if (!get_constant(&p1[i+1], j - (i + 1), &d2))
if (!get_constant(mathomatic, &p1[i+1], j - (i + 1), &d2))
return false;
prev_approx_flag = approximate_roots;
approximate_roots = true;
if (calc(NULL, &d1, p1[i].token.operatr, d2)) {
approximate_roots = prev_approx_flag;
if (p1[i].token.operatr == POWER && !domain_check)
prev_approx_flag = mathomatic->approximate_roots;
mathomatic->approximate_roots = true;
if (calc(mathomatic, NULL, &d1, p1[i].token.operatr, d2)) {
mathomatic->approximate_roots = prev_approx_flag;
if (p1[i].token.operatr == POWER && !mathomatic->domain_check)
return false;
domain_check = false;
mathomatic->domain_check = false;
} else {
approximate_roots = prev_approx_flag;
domain_check = false;
mathomatic->approximate_roots = prev_approx_flag;
mathomatic->domain_check = false;
return false;
}
}
@ -323,10 +322,10 @@ double *dp; /* pointer to returned double */
* If successful, return true with complex number in *cp.
*/
int
parse_complex(p1, n, cp)
token_type *p1; /* expression pointer */
int n; /* length of expression */
complexs *cp; /* pointer to returned complex number */
parse_complex(MathoMatic* mathomatic, token_type *p1, int n, complexs *cp)
//token_type *p1; /* expression pointer */
//int n; /* length of expression */
//complexs *cp; /* pointer to returned complex number */
{
int j, k;
int imag_cnt = 0, times_cnt = 0;
@ -336,14 +335,14 @@ complexs *cp; /* pointer to returned complex number */
if (!exp_is_numeric(p1, n)) {
return false;
}
if (get_constant(p1, n, &c.re)) {
if (get_constant(mathomatic, p1, n, &c.re)) {
c.im = 0.0;
*cp = c;
return true;
}
if (found_var(p1, n, IMAGINARY) != 1)
return false;
level = min_level(p1, n);
level = min_level(mathomatic, p1, n);
c.re = 0.0;
c.im = 1.0;
j = n - 1;
@ -353,13 +352,13 @@ complexs *cp; /* pointer to returned complex number */
if (k > 0) {
#if DEBUG
if (p1[k].level != level || p1[k].kind != OPERATOR) {
error_bug("Error in parse_complex().");
error_bug(mathomatic, "Error in parse_complex().");
}
#endif
switch (p1[k].token.operatr) {
case MINUS:
case PLUS:
if (get_constant(&p1[k+1], j - k, &tmp.re)) {
if (get_constant(mathomatic, &p1[k+1], j - k, &tmp.re)) {
if (p1[k].token.operatr == MINUS)
c.re -= tmp.re;
else
@ -394,7 +393,7 @@ complexs *cp; /* pointer to returned complex number */
if (p1[k-1].level != level2)
return false;
if (!(p1[k+1].kind == VARIABLE && p1[k+1].token.variable == IMAGINARY)) {
if (get_constant(&p1[k+1], 1, &tmp.im)) {
if (get_constant(mathomatic, &p1[k+1], 1, &tmp.im)) {
if (p1[k].token.operatr == DIVIDE)
c.im /= tmp.im;
else
@ -420,7 +419,7 @@ complexs *cp; /* pointer to returned complex number */
}
}
if (!(p1[k+1].kind == VARIABLE && p1[k+1].token.variable == IMAGINARY)) {
if (get_constant(&p1[k+1], 1, &tmp.im)) {
if (get_constant(mathomatic, &p1[k+1], 1, &tmp.im)) {
c.im *= tmp.im;
} else
return false;
@ -434,7 +433,7 @@ complexs *cp; /* pointer to returned complex number */
case PLUS:
if (level != level2)
return false;
if (get_constant(p1, j, &tmp.re)) {
if (get_constant(mathomatic, p1, j, &tmp.re)) {
c.re += tmp.re;
goto done;
}
@ -447,7 +446,7 @@ complexs *cp; /* pointer to returned complex number */
done:
if (imag_cnt != 1) {
#if DEBUG
error_bug("Imaginary count wrong in parse_complex().");
error_bug(mathomatic, "Imaginary count wrong in parse_complex().");
#else
return false;
#endif

521
diff.c
View File

@ -24,7 +24,7 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#include "includes.h"
static int d_recurse(token_type *equation, int *np, int loc, int level, long v);
static int d_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, long v);
/*
* Compute the derivative of an equation side, with respect to variable "v",
@ -36,14 +36,14 @@ static int d_recurse(token_type *equation, int *np, int loc, int level, long v);
* The result must be simplified by the caller.
*/
int
differentiate(equation, np, v)
token_type *equation; /* pointer to source and destination equation side */
int *np; /* pointer to the length of the equation side */
long v; /* differentiation variable */
differentiate(MathoMatic* mathomatic, token_type *equation, int *np, long v)
//token_type *equation; /* pointer to source and destination equation side */
//int *np; /* pointer to the length of the equation side */
//long v; /* differentiation variable */
{
int i;
organize(equation, np);
organize(mathomatic, equation, np);
/* First put every times and divide on a level by itself. */
for (i = 1; i < *np; i += 2) {
switch (equation[i].token.operatr) {
@ -52,7 +52,7 @@ long v; /* differentiation variable */
binary_parenthesize(equation, *np, i);
}
}
return d_recurse(equation, np, 0, 1, v);
return d_recurse(mathomatic, equation, np, 0, 1, v);
}
/*
@ -67,10 +67,7 @@ long v; /* differentiation variable */
* Return false if it is beyond this program's capabilities or an error was encountered.
*/
static int
d_recurse(equation, np, loc, level, v)
token_type *equation;
int *np, loc, level;
long v;
d_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, long v)
{
int i, j;
int n;
@ -102,7 +99,7 @@ long v;
break;
default:
/* Oops. More than one operator on the same level in this expression. */
error_bug("Internal error in d_recurse(): differentiating with unparenthesized operators is not allowed.");
error_bug(mathomatic, "Internal error in d_recurse(): differentiating with unparenthesized operators is not allowed.");
return false;
}
op = equation[endloc].token.operatr;
@ -144,7 +141,7 @@ long v;
/* 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))
if (!d_recurse(mathomatic, equation, np, i, level + 1, v))
return false;
i++;
for (; i < *np && equation[i].level > level; i += 2)
@ -157,8 +154,8 @@ long v;
d_times:
/* Differentiate TIMES operator. */
/* Use product rule: d(u*v) = u*d(v) + v*d(u). */
if (*np + 1 + (endloc - loc) > n_tokens) {
error_huge();
if (*np + 1 + (endloc - loc) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
for (i = loc; i < endloc; i++)
equation[i].level++;
@ -167,14 +164,14 @@ d_times:
equation[endloc].level = level;
equation[endloc].kind = OPERATOR;
equation[endloc].token.operatr = PLUS;
if (!d_recurse(equation, np, endloc + (oploc - loc) + 2, level + 2, v))
if (!d_recurse(mathomatic, equation, np, endloc + (oploc - loc) + 2, level + 2, v))
return false;
return(d_recurse(equation, np, loc, level + 2, v));
return(d_recurse(mathomatic, equation, np, loc, level + 2, v));
d_divide:
/* Differentiate DIVIDE operator. */
/* 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();
if (*np + 3 + (endloc - loc) + (endloc - oploc) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
for (i = loc; i < endloc; i++)
equation[i].level += 2;
@ -200,9 +197,9 @@ d_divide:
equation[j].level = level + 1;
equation[j].kind = CONSTANT;
equation[j].token.constant = 2.0;
if (!d_recurse(equation, np, endloc + (oploc - loc) + 2, level + 3, v))
if (!d_recurse(mathomatic, equation, np, endloc + (oploc - loc) + 2, level + 3, v))
return false;
return(d_recurse(equation, np, loc, level + 3, v));
return(d_recurse(mathomatic, equation, np, loc, level + 3, v));
d_power:
/* Differentiate POWER operator. */
/* Since we don't have symbolic logarithms, do all we can without them. */
@ -210,11 +207,11 @@ d_power:
if (equation[i].kind == VARIABLE
&& ((v == MATCH_ANY && (equation[i].token.variable & VAR_MASK) > SIGN)
|| equation[i].token.variable == v)) {
if (parse_complex(&equation[loc], oploc - loc, &c)) {
if (parse_complex(mathomatic, &equation[loc], oploc - loc, &c)) {
c = complex_log(c);
n = (endloc - oploc) + 6;
if (*np + n > n_tokens) {
error_huge();
if (*np + n > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[endloc+n], &equation[endloc], (*np - endloc) * sizeof(token_type));
*np += n;
@ -251,61 +248,60 @@ d_power:
for (i = loc; i < endloc; i++) {
equation[i].level++;
}
return(d_recurse(equation, np, n, level + 1, v));
return(d_recurse(mathomatic, equation, np, n, level + 1, v));
}
return false;
}
}
blt(scratch, &equation[oploc+1], (endloc - (oploc + 1)) * sizeof(token_type));
blt(mathomatic->scratch, &equation[oploc+1], (endloc - (oploc + 1)) * sizeof(token_type));
n = endloc - (oploc + 1);
scratch[n].level = level;
scratch[n].kind = OPERATOR;
scratch[n].token.operatr = TIMES;
mathomatic->scratch[n].level = level;
mathomatic->scratch[n].kind = OPERATOR;
mathomatic->scratch[n].token.operatr = TIMES;
n++;
if (n + (endloc - loc) + 2 > n_tokens) {
error_huge();
if (n + (endloc - loc) + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&scratch[n], &equation[loc], (endloc - loc) * sizeof(token_type));
blt(&mathomatic->scratch[n], &equation[loc], (endloc - loc) * sizeof(token_type));
i = n;
n += oploc + 1 - loc;
for (; i < n; i++)
scratch[i].level++;
mathomatic->scratch[i].level++;
n += endloc - (oploc + 1);
for (; i < n; i++)
scratch[i].level += 2;
scratch[n].level = level + 2;
scratch[n].kind = OPERATOR;
scratch[n].token.operatr = MINUS;
mathomatic->scratch[i].level += 2;
mathomatic->scratch[n].level = level + 2;
mathomatic->scratch[n].kind = OPERATOR;
mathomatic->scratch[n].token.operatr = MINUS;
n++;
scratch[n].level = level + 2;
scratch[n].kind = CONSTANT;
scratch[n].token.constant = 1.0;
mathomatic->scratch[n].level = level + 2;
mathomatic->scratch[n].kind = CONSTANT;
mathomatic->scratch[n].token.constant = 1.0;
n++;
if (n + (oploc - loc) + 1 > n_tokens) {
error_huge();
if (n + (oploc - loc) + 1 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
scratch[n].level = level;
scratch[n].kind = OPERATOR;
scratch[n].token.operatr = TIMES;
mathomatic->scratch[n].level = level;
mathomatic->scratch[n].kind = OPERATOR;
mathomatic->scratch[n].token.operatr = TIMES;
n++;
j = n;
blt(&scratch[n], &equation[loc], (oploc - loc) * sizeof(token_type));
blt(&mathomatic->scratch[n], &equation[loc], (oploc - loc) * sizeof(token_type));
n += oploc - loc;
if (*np - (endloc - loc) + n > n_tokens) {
error_huge();
if (*np - (endloc - loc) + n > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[loc+n], &equation[endloc], (*np - endloc) * sizeof(token_type));
*np += loc + n - endloc;
blt(&equation[loc], scratch, n * sizeof(token_type));
return(d_recurse(equation, np, loc + j, level + 1, v));
blt(&equation[loc], mathomatic->scratch, n * sizeof(token_type));
return(d_recurse(mathomatic, equation, np, loc + j, level + 1, v));
}
/*
* The derivative command.
*/
int
derivative_cmd(cp)
char *cp;
derivative_cmd(MathoMatic* mathomatic, char *cp)
{
int i, len;
long v = 0; /* Mathomatic variable */
@ -314,28 +310,28 @@ char *cp;
int n1, *nps, *np;
int simplify_flag = true, solved;
if (current_not_defined()) {
if (current_not_defined(mathomatic)) {
return false;
}
solved = solved_equation(cur_equation);
solved = solved_equation(mathomatic, mathomatic->cur_equation);
if (strcmp_tospace(cp, "nosimplify") == 0) {
simplify_flag = false;
cp = skip_param(cp);
}
i = next_espace();
if (n_rhs[cur_equation]) {
i = next_espace(mathomatic);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
if (!solved) {
warning(_("Not a solved equation. Only the RHS will be differentiated."));
warning(mathomatic, _("Not a solved equation. Only the RHS will be differentiated."));
}
source = rhs[cur_equation];
nps = &n_rhs[cur_equation];
dest = rhs[i];
np = &n_rhs[i];
source = mathomatic->rhs[mathomatic->cur_equation];
nps = &mathomatic->n_rhs[mathomatic->cur_equation];
dest = mathomatic->rhs[i];
np = &mathomatic->n_rhs[i];
} else {
source = lhs[cur_equation];
nps = &n_lhs[cur_equation];
dest = lhs[i];
np = &n_lhs[i];
source = mathomatic->lhs[mathomatic->cur_equation];
nps = &mathomatic->n_lhs[mathomatic->cur_equation];
dest = mathomatic->lhs[i];
np = &mathomatic->n_lhs[i];
}
/* parse the command line or prompt: */
if (*cp) {
@ -343,8 +339,8 @@ char *cp;
cp = skip_param(cp);
v = MATCH_ANY;
} else {
if (isvarchar(*cp)) {
cp = parse_var2(&v, cp);
if (isvarchar(mathomatic, *cp)) {
cp = parse_var2(mathomatic, &v, cp);
if (cp == NULL) {
return false;
}
@ -354,44 +350,44 @@ char *cp;
order = decstrtol(cp, &cp);
}
if (order <= 0) {
error(_("The order must be a positive integer."));
error(mathomatic, _("The order must be a positive integer."));
return false;
}
if (extra_characters(cp))
if (extra_characters(mathomatic, cp))
return false;
}
if (no_vars(source, *nps, &v)) {
warning(_("Current expression contains no variables; the derivative will be zero."));
warning(mathomatic, _("Current expression contains no variables; the derivative will be zero."));
} else {
if (v == 0) {
if (!prompt_var(&v)) {
if (!prompt_var(mathomatic, &v)) {
return false;
}
}
if (v && v != MATCH_ANY && !found_var(source, *nps, v)) {
warning(_("Specified variable not found; the derivative will be zero."));
warning(mathomatic, _("Specified variable not found; the derivative will be zero."));
}
}
if (v == 0) {
error(_("No differentiation variable specified."));
error(mathomatic, _("No differentiation variable specified."));
return false;
}
#if !SILENT
list_var(v, 0);
if (n_rhs[cur_equation]) {
fprintf(gfp, _("Differentiating the RHS with respect to %s"), var_str);
list_var(mathomatic, v, 0);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
fprintf(mathomatic->gfp, _("Differentiating the RHS with respect to %s"), mathomatic->var_str);
} else {
fprintf(gfp, _("Differentiating with respect to %s"), var_str);
fprintf(mathomatic->gfp, _("Differentiating with respect to %s"), mathomatic->var_str);
}
if (order != 1) {
fprintf(gfp, _(" %ld times"), order);
fprintf(mathomatic->gfp, _(" %ld times"), order);
}
if (simplify_flag) {
fprintf(gfp, _(" and simplifying"));
fprintf(mathomatic->gfp, _(" and simplifying"));
} else {
fprintf(gfp, _(" and not simplifying"));
fprintf(mathomatic->gfp, _(" and not simplifying"));
}
fprintf(gfp, "...\n");
fprintf(mathomatic->gfp, "...\n");
#endif
blt(dest, source, *nps * sizeof(token_type));
n1 = *nps;
@ -399,46 +395,45 @@ char *cp;
for (l1 = 0; l1 < order; l1++) {
if (order != 1) {
if (n1 == 1 && dest[0].kind == CONSTANT && dest[0].token.constant == 0.0) {
fprintf(gfp, _("0 reached after %ld derivatives taken.\n"), l1);
fprintf(mathomatic->gfp, _("0 reached after %ld derivatives taken.\n"), l1);
order = l1;
break;
}
}
if (!differentiate(dest, &n1, v)) {
error(_("Differentiation failed."));
if (!differentiate(mathomatic, dest, &n1, v)) {
error(mathomatic, _("Differentiation failed."));
return false;
}
if (simplify_flag) {
simpa_repeat_side(dest, &n1, true, false);
simpa_repeat_side(mathomatic, dest, &n1, true, false);
} else {
elim_loop(dest, &n1);
elim_loop(mathomatic, dest, &n1);
}
}
*np = n1;
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];
if (solved && isvarchar('\'')) {
len = list_var(lhs[i][0].token.variable, 0);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
blt(mathomatic->lhs[i], mathomatic->lhs[mathomatic->cur_equation], mathomatic->n_lhs[mathomatic->cur_equation] * sizeof(token_type));
mathomatic->n_lhs[i] = mathomatic->n_lhs[mathomatic->cur_equation];
if (solved && isvarchar(mathomatic, '\'')) {
len = list_var(mathomatic, mathomatic->lhs[i][0].token.variable, 0);
for (l1 = 0; l1 < order && len < (MAX_VAR_LEN - 1); l1++) {
var_str[len++] = '\'';
mathomatic->var_str[len++] = '\'';
}
var_str[len] = '\0';
mathomatic->var_str[len] = '\0';
if (l1 == order) {
parse_var(&lhs[i][0].token.variable, var_str);
parse_var(mathomatic, &mathomatic->lhs[i][0].token.variable, mathomatic->var_str);
}
}
}
cur_equation = i;
return return_result(cur_equation);
mathomatic->cur_equation = i;
return return_result(mathomatic, mathomatic->cur_equation);
}
/*
* The extrema command.
*/
int
extrema_cmd(cp)
char *cp;
extrema_cmd(MathoMatic* mathomatic, char *cp)
{
int i;
long v = 0; /* Mathomatic variable */
@ -447,24 +442,24 @@ char *cp;
token_type *source;
int n;
if (current_not_defined()) {
if (current_not_defined(mathomatic)) {
return false;
}
i = next_espace();
if (n_rhs[cur_equation]) {
if (!solved_equation(cur_equation)) {
error(_("The current equation is not solved for a variable."));
i = next_espace(mathomatic);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
if (!solved_equation(mathomatic, mathomatic->cur_equation)) {
error(mathomatic, _("The current equation is not solved for a variable."));
return false;
}
source = rhs[cur_equation];
n = n_rhs[cur_equation];
source = mathomatic->rhs[mathomatic->cur_equation];
n = mathomatic->n_rhs[mathomatic->cur_equation];
} else {
source = lhs[cur_equation];
n = n_lhs[cur_equation];
source = mathomatic->lhs[mathomatic->cur_equation];
n = mathomatic->n_lhs[mathomatic->cur_equation];
}
if (*cp) {
if (isvarchar(*cp)) {
cp = parse_var2(&v, cp);
if (isvarchar(mathomatic, *cp)) {
cp = parse_var2(mathomatic, &v, cp);
if (cp == NULL) {
return false;
}
@ -473,62 +468,61 @@ char *cp;
order = decstrtol(cp, &cp);
}
if (order <= 0) {
error(_("The order must be a positive integer."));
error(mathomatic, _("The order must be a positive integer."));
return false;
}
if (extra_characters(cp))
if (extra_characters(mathomatic, cp))
return false;
}
show_usage = false;
mathomatic->show_usage = false;
if (no_vars(source, n, &v)) {
error(_("Current expression contains no variables."));
error(mathomatic, _("Current expression contains no variables."));
return false;
}
if (v == 0) {
if (!prompt_var(&v)) {
if (!prompt_var(mathomatic, &v)) {
return false;
}
}
if (!found_var(source, n, v)) {
error(_("Specified variable not found; the derivative would be zero."));
error(mathomatic, _("Specified variable not found; the derivative would be zero."));
return false;
}
blt(rhs[i], source, n * sizeof(token_type));
blt(mathomatic->rhs[i], source, n * sizeof(token_type));
/* 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."));
if (!differentiate(mathomatic, mathomatic->rhs[i], &n, v)) {
error(mathomatic, _("Differentiation failed."));
return false;
}
simpa_repeat_side(rhs[i], &n, true, false);
simpa_repeat_side(mathomatic, mathomatic->rhs[i], &n, true, false);
}
if (!found_var(rhs[i], n, v)) {
error(_("There are no solutions."));
if (!found_var(mathomatic->rhs[i], n, v)) {
error(mathomatic, _("There are no solutions."));
return false;
}
n_rhs[i] = n;
mathomatic->n_rhs[i] = n;
/* set equal to zero: */
n_lhs[i] = 1;
lhs[i][0] = zero_token;
cur_equation = i;
mathomatic->n_lhs[i] = 1;
mathomatic->lhs[i][0] = mathomatic->zero_token;
mathomatic->cur_equation = i;
/* lastly, solve for the specified variable and simplify: */
want.level = 1;
want.kind = VARIABLE;
want.token.variable = v;
if (solve_sub(&want, 1, lhs[i], &n_lhs[i], rhs[i], &n_rhs[i]) <= 0) {
error(_("Solve failed."));
if (solve_sub(mathomatic, &want, 1, mathomatic->lhs[i], &mathomatic->n_lhs[i], mathomatic->rhs[i], &mathomatic->n_rhs[i]) <= 0) {
error(mathomatic, _("Solve failed."));
return false;
}
simpa_repeat_side(rhs[i], &n_rhs[i], false, false);
return return_result(cur_equation);
simpa_repeat_side(mathomatic, mathomatic->rhs[i], &mathomatic->n_rhs[i], false, false);
return return_result(mathomatic, mathomatic->cur_equation);
}
/*
* The taylor command.
*/
int
taylor_cmd(cp)
char *cp;
taylor_cmd(MathoMatic* mathomatic, char *cp)
{
long v = 0; /* Mathomatic variable */
int i, j, k, i1;
@ -543,37 +537,37 @@ char *cp;
int simplify_flag = true;
cp_start = cp;
if (current_not_defined()) {
if (current_not_defined(mathomatic)) {
return false;
}
if (strcmp_tospace(cp, "nosimplify") == 0) {
simplify_flag = false;
cp = skip_param(cp);
}
i = next_espace();
blt(lhs[i], lhs[cur_equation], n_lhs[cur_equation] * sizeof(token_type));
n_lhs[i] = n_lhs[cur_equation];
n_rhs[i] = 0;
our = alloc_next_espace();
n_lhs[i] = 0;
i = next_espace(mathomatic);
blt(mathomatic->lhs[i], mathomatic->lhs[mathomatic->cur_equation], mathomatic->n_lhs[mathomatic->cur_equation] * sizeof(token_type));
mathomatic->n_lhs[i] = mathomatic->n_lhs[mathomatic->cur_equation];
mathomatic->n_rhs[i] = 0;
our = alloc_next_espace(mathomatic);
mathomatic->n_lhs[i] = 0;
if (our < 0) {
error(_("Out of free equation spaces."));
show_usage = false;
error(mathomatic, _("Out of free equation spaces."));
mathomatic->show_usage = false;
return false;
}
if (n_rhs[cur_equation]) {
source = rhs[cur_equation];
nps = &n_rhs[cur_equation];
dest = rhs[i];
np = &n_rhs[i];
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
source = mathomatic->rhs[mathomatic->cur_equation];
nps = &mathomatic->n_rhs[mathomatic->cur_equation];
dest = mathomatic->rhs[i];
np = &mathomatic->n_rhs[i];
} else {
source = lhs[cur_equation];
nps = &n_lhs[cur_equation];
dest = lhs[i];
np = &n_lhs[i];
source = mathomatic->lhs[mathomatic->cur_equation];
nps = &mathomatic->n_lhs[mathomatic->cur_equation];
dest = mathomatic->lhs[i];
np = &mathomatic->n_lhs[i];
}
if (*cp && isvarchar(*cp)) {
cp = parse_var2(&v, cp);
if (*cp && isvarchar(mathomatic, *cp)) {
cp = parse_var2(mathomatic, &v, cp);
if (cp == NULL) {
return false;
}
@ -581,55 +575,55 @@ char *cp;
if (*cp) {
order = decstrtol(cp, &cp1);
if (cp1 != skip_param(cp) || order < 0) {
error(_("Positive integer required for order."));
error(mathomatic, _("Positive integer required for order."));
return false;
}
cp = cp1;
}
show_usage = false;
mathomatic->show_usage = false;
no_vars(source, *nps, &v);
if (v == 0) {
if (!prompt_var(&v)) {
if (!prompt_var(mathomatic, &v)) {
return false;
}
}
if (!found_var(source, *nps, v)) {
warning(_("Specified differentiation variable not found; the derivative will be 0."));
warning(mathomatic, _("Specified differentiation variable not found; the derivative will be 0."));
}
blt(rhs[our], source, *nps * sizeof(token_type));
blt(mathomatic->rhs[our], source, *nps * sizeof(token_type));
our_nrhs = *nps;
/* Simplify and take the first derivative: */
uf_simp(rhs[our], &our_nrhs);
if (!differentiate(rhs[our], &our_nrhs, v)) {
error(_("Differentiation failed."));
uf_simp(mathomatic, mathomatic->rhs[our], &our_nrhs);
if (!differentiate(mathomatic, mathomatic->rhs[our], &our_nrhs, v)) {
error(mathomatic, _("Differentiation failed."));
return false;
}
if (*cp) {
input_column += (cp - cp_start);
cp = parse_expr(lhs[our], &our_nlhs, cp, true);
if (cp == NULL || extra_characters(cp) || our_nlhs <= 0) {
show_usage = true;
mathomatic->input_column += (cp - cp_start);
cp = parse_expr(mathomatic, mathomatic->lhs[our], &our_nlhs, cp, true);
if (cp == NULL || extra_characters(mathomatic, cp) || our_nlhs <= 0) {
mathomatic->show_usage = true;
return false;
}
} else {
#if !SILENT
list_var(v, 0);
printf(_("Taylor series expansion around %s = point.\n"), var_str);
list_var(mathomatic, v, 0);
printf(_("Taylor series expansion around %s = point.\n"), mathomatic->var_str);
#endif
my_strlcpy(prompt_str, _("Enter point (an expression; usually 0): "), sizeof(prompt_str));
if (!get_expr(lhs[our], &our_nlhs)) {
my_strlcpy(mathomatic->prompt_str, _("Enter point (an expression; usually 0): "), sizeof(mathomatic->prompt_str));
if (!get_expr(mathomatic, mathomatic->lhs[our], &our_nlhs)) {
return false;
}
}
if (order < 0) {
my_strlcpy(prompt_str, _("Enter order (number of derivatives to take): "), sizeof(prompt_str));
if ((cp1 = get_string(buf, sizeof(buf))) == NULL)
my_strlcpy(mathomatic->prompt_str, _("Enter order (number of derivatives to take): "), sizeof(mathomatic->prompt_str));
if ((cp1 = get_string(mathomatic, buf, sizeof(buf))) == NULL)
return false;
if (*cp1) {
cp = NULL;
order = decstrtol(cp1, &cp);
if (cp == NULL || *cp || order < 0) {
error(_("Positive integer required for order."));
error(mathomatic, _("Positive integer required for order."));
return false;
}
} else {
@ -640,18 +634,18 @@ char *cp;
}
}
#if !SILENT
fprintf(gfp, _("Taylor series"));
if (n_rhs[cur_equation]) {
fprintf(gfp, _(" of the RHS"));
fprintf(mathomatic->gfp, _("Taylor series"));
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
fprintf(mathomatic->gfp, _(" of the RHS"));
}
list_var(v, 0);
fprintf(gfp, _(" with respect to %s"), var_str);
list_var(mathomatic, v, 0);
fprintf(mathomatic->gfp, _(" with respect to %s"), mathomatic->var_str);
if (simplify_flag) {
fprintf(gfp, _(", simplified"));
fprintf(mathomatic->gfp, _(", simplified"));
} else {
fprintf(gfp, _(", not simplified"));
fprintf(mathomatic->gfp, _(", not simplified"));
}
fprintf(gfp, "...\n");
fprintf(mathomatic->gfp, "...\n");
#endif
n = 0;
i1 = 0;
@ -661,20 +655,20 @@ loop_again:
for (k = i1; k < n1; k += 2) {
if (dest[k].kind == VARIABLE && dest[k].token.variable == v) {
level = dest[k].level;
if ((n1 + our_nlhs - 1) > n_tokens)
error_huge();
if ((n1 + our_nlhs - 1) > mathomatic->n_tokens)
error_huge(mathomatic);
blt(&dest[k+our_nlhs], &dest[k+1], (n1 - (k + 1)) * sizeof(token_type));
n1 += our_nlhs - 1;
j = k;
blt(&dest[k], lhs[our], our_nlhs * sizeof(token_type));
blt(&dest[k], mathomatic->lhs[our], our_nlhs * sizeof(token_type));
k += our_nlhs;
for (; j < k; j++)
dest[j].level += level;
k--;
}
}
if ((n1 + our_nlhs + 7) > n_tokens)
error_huge();
if ((n1 + our_nlhs + 7) > mathomatic->n_tokens)
error_huge(mathomatic);
for (k = i1; k < n1; k++)
dest[k].level++;
ep = &dest[n1];
@ -691,7 +685,7 @@ loop_again:
ep->token.operatr = MINUS;
n1 += 3;
j = n1;
blt(&dest[n1], lhs[our], our_nlhs * sizeof(token_type));
blt(&dest[n1], mathomatic->lhs[our], our_nlhs * sizeof(token_type));
n1 += our_nlhs;
for (; j < n1; j++)
dest[j].level += 3;
@ -717,56 +711,55 @@ loop_again:
for (; i1 < n1; i1++)
dest[i1].level++;
if (simplify_flag) {
uf_simp(dest, &n1);
uf_simp(mathomatic, dest, &n1);
}
side_debug(1, dest, n1);
side_debug(mathomatic, 1, dest, n1);
if (exp_contains_infinity(dest, n1)) {
error(_("Result invalid because it contains infinity or NaN."));
error(mathomatic, _("Result invalid because it contains infinity or NaN."));
return false;
}
if (n < order) {
if (n > 0) {
if (!differentiate(rhs[our], &our_nrhs, v)) {
error(_("Differentiation failed."));
if (!differentiate(mathomatic, mathomatic->rhs[our], &our_nrhs, v)) {
error(mathomatic, _("Differentiation failed."));
return false;
}
}
/* symb_flag = symblify; */
simpa_repeat_side(rhs[our], &our_nrhs, true, false /* was true */);
simpa_repeat_side(mathomatic, mathomatic->rhs[our], &our_nrhs, true, false /* was true */);
/* symb_flag = false; */
if (our_nrhs != 1 || rhs[our][0].kind != CONSTANT || rhs[our][0].token.constant != 0.0) {
if (our_nrhs != 1 || mathomatic->rhs[our][0].kind != CONSTANT || mathomatic->rhs[our][0].token.constant != 0.0) {
i1 = n1;
if ((i1 + 1 + our_nrhs) > n_tokens)
error_huge();
if ((i1 + 1 + our_nrhs) > mathomatic->n_tokens)
error_huge(mathomatic);
for (j = 0; j < i1; j++)
dest[j].level++;
dest[i1].level = 1;
dest[i1].kind = OPERATOR;
dest[i1].token.operatr = PLUS;
i1++;
blt(&dest[i1], rhs[our], our_nrhs * sizeof(token_type));
blt(&dest[i1], mathomatic->rhs[our], our_nrhs * sizeof(token_type));
n1 = i1 + our_nrhs;
n++;
goto loop_again;
}
}
#if !SILENT
fprintf(gfp, _("%ld non-zero derivative%s applied.\n"), n, (n == 1) ? "" : "s");
fprintf(mathomatic->gfp, _("%ld non-zero derivative%s applied.\n"), n, (n == 1) ? "" : "s");
#endif
if (n_rhs[cur_equation]) {
n_lhs[i] = n_lhs[cur_equation];
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
mathomatic->n_lhs[i] = mathomatic->n_lhs[mathomatic->cur_equation];
}
*np = n1;
cur_equation = i;
return return_result(cur_equation);
mathomatic->cur_equation = i;
return return_result(mathomatic, mathomatic->cur_equation);
}
/*
* The limit command.
*/
int
limit_cmd(cp)
char *cp;
limit_cmd(MathoMatic* mathomatic, char *cp)
{
int i;
long v = 0; /* Mathomatic variable */
@ -774,120 +767,120 @@ char *cp;
char *cp_start;
cp_start = cp;
if (current_not_defined()) {
if (current_not_defined(mathomatic)) {
return false;
}
i = next_espace();
if (n_rhs[cur_equation] == 0) {
i = next_espace(mathomatic);
if (mathomatic->n_rhs[mathomatic->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;
parse_var(&lhs[cur_equation][0].token.variable, "limit");
blt(mathomatic->rhs[mathomatic->cur_equation], mathomatic->lhs[mathomatic->cur_equation], mathomatic->n_lhs[mathomatic->cur_equation] * sizeof(token_type));
mathomatic->n_rhs[mathomatic->cur_equation] = mathomatic->n_lhs[mathomatic->cur_equation];
mathomatic->n_lhs[mathomatic->cur_equation] = 1;
mathomatic->lhs[mathomatic->cur_equation][0].level = 1;
mathomatic->lhs[mathomatic->cur_equation][0].kind = VARIABLE;
parse_var(mathomatic, &mathomatic->lhs[mathomatic->cur_equation][0].token.variable, "limit");
}
if (!solved_equation(cur_equation)) {
error(_("The current equation is not solved for a variable."));
if (!solved_equation(mathomatic, mathomatic->cur_equation)) {
error(mathomatic, _("The current equation is not solved for a variable."));
return false;
}
solved_v = lhs[cur_equation][0];
solved_v = mathomatic->lhs[mathomatic->cur_equation][0];
/* parse the command line or prompt: */
if (*cp) {
cp = parse_var2(&v, cp);
cp = parse_var2(mathomatic, &v, cp);
if (cp == NULL) {
return false;
}
}
show_usage = false;
if (no_vars(rhs[cur_equation], n_rhs[cur_equation], &v)) {
warning(_("Current expression contains no variables; that is the answer."));
return return_result(cur_equation);
mathomatic->show_usage = false;
if (no_vars(mathomatic->rhs[mathomatic->cur_equation], mathomatic->n_rhs[mathomatic->cur_equation], &v)) {
warning(mathomatic, _("Current expression contains no variables; that is the answer."));
return return_result(mathomatic, mathomatic->cur_equation);
}
if (v == 0) {
if (!prompt_var(&v)) {
if (!prompt_var(mathomatic, &v)) {
return false;
}
}
if (!found_var(rhs[cur_equation], n_rhs[cur_equation], v)) {
warning(_("Limit variable not found; answer is original expression."));
return return_result(cur_equation);
if (!found_var(mathomatic->rhs[mathomatic->cur_equation], mathomatic->n_rhs[mathomatic->cur_equation], v)) {
warning(mathomatic, _("Limit variable not found; answer is original expression."));
return return_result(mathomatic, mathomatic->cur_equation);
}
if (*cp == '=') {
cp = skip_space(cp + 1);
}
if (*cp) {
input_column += (cp - cp_start);
cp = parse_expr(tes, &n_tes, cp, true);
if (cp == NULL || extra_characters(cp) || n_tes <= 0) {
show_usage = true;
mathomatic->input_column += (cp - cp_start);
cp = parse_expr(mathomatic, mathomatic->tes, &mathomatic->n_tes, cp, true);
if (cp == NULL || extra_characters(mathomatic, cp) || mathomatic->n_tes <= 0) {
mathomatic->show_usage = true;
return false;
}
} else {
list_var(v, 0);
snprintf(prompt_str, sizeof(prompt_str), _("as %s goes to: "), var_str);
if (!get_expr(tes, &n_tes)) {
list_var(mathomatic, v, 0);
snprintf(mathomatic->prompt_str, sizeof(mathomatic->prompt_str), _("as %s goes to: "), mathomatic->var_str);
if (!get_expr(mathomatic, mathomatic->tes, &mathomatic->n_tes)) {
return false;
}
}
simp_loop(tes, &n_tes);
simp_loop(mathomatic, mathomatic->tes, &mathomatic->n_tes);
#if !SILENT
list_var(v, 0);
fprintf(gfp, _("Taking the limit as %s goes to "), var_str);
list_proc(tes, n_tes, false);
fprintf(gfp, "\n");
list_var(mathomatic, v, 0);
fprintf(mathomatic->gfp, _("Taking the limit as %s goes to "), mathomatic->var_str);
list_proc(mathomatic, mathomatic->tes, mathomatic->n_tes, false);
fprintf(mathomatic->gfp, "\n");
#endif
/* copy the current equation to a new equation space, then simplify and work on the copy: */
copy_espace(cur_equation, i);
simpa_side(rhs[i], &n_rhs[i], false, false);
copy_espace(mathomatic, mathomatic->cur_equation, i);
simpa_side(mathomatic, mathomatic->rhs[i], &mathomatic->n_rhs[i], false, false);
/* see if the limit expression is positive infinity: */
if (n_tes == 1 && tes[0].kind == CONSTANT && tes[0].token.constant == INFINITY) {
if (mathomatic->n_tes == 1 && mathomatic->tes[0].kind == CONSTANT && mathomatic->tes[0].token.constant == INFINITY) {
/* 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;
tlhs[1].token.operatr = DIVIDE;
tlhs[2].level = 1;
tlhs[2].kind = VARIABLE;
tlhs[2].token.variable = v;
n_tlhs = 3;
subst_var_with_exp(rhs[i], &n_rhs[i], tlhs, n_tlhs, v);
mathomatic->n_tes = 1;
mathomatic->tes[0] = mathomatic->zero_token;
mathomatic->tlhs[0] = mathomatic->one_token;
mathomatic->tlhs[1].level = 1;
mathomatic->tlhs[1].kind = OPERATOR;
mathomatic->tlhs[1].token.operatr = DIVIDE;
mathomatic->tlhs[2].level = 1;
mathomatic->tlhs[2].kind = VARIABLE;
mathomatic->tlhs[2].token.variable = v;
mathomatic->n_tlhs = 3;
subst_var_with_exp(mathomatic, mathomatic->rhs[i], &mathomatic->n_rhs[i], mathomatic->tlhs, mathomatic->n_tlhs, v);
}
/* General limit taking, solve for the limit variable: */
debug_string(0, _("Solving..."));
debug_string(mathomatic, 0, _("Solving..."));
want.level = 1;
want.kind = VARIABLE;
want.token.variable = v;
if (solve_sub(&want, 1, lhs[i], &n_lhs[i], rhs[i], &n_rhs[i]) <= 0) {
error(_("Can't take the limit because solve failed."));
if (solve_sub(mathomatic, &want, 1, mathomatic->lhs[i], &mathomatic->n_lhs[i], mathomatic->rhs[i], &mathomatic->n_rhs[i]) <= 0) {
error(mathomatic, _("Can't take the limit because solve failed."));
return false;
}
/* replace the limit variable (LHS) with the limit expression: */
blt(lhs[i], tes, n_tes * sizeof(token_type));
n_lhs[i] = n_tes;
blt(mathomatic->lhs[i], mathomatic->tes, mathomatic->n_tes * sizeof(token_type));
mathomatic->n_lhs[i] = mathomatic->n_tes;
/* simplify the RHS: */
symb_flag = symblify;
simpa_side(rhs[i], &n_rhs[i], false, false);
symb_flag = false;
if (exp_contains_nan(rhs[i], n_rhs[i])) {
error(_("Unable to take limit; result contains NaN (Not a Number)."));
mathomatic->symb_flag = mathomatic->symblify;
simpa_side(mathomatic, mathomatic->rhs[i], &mathomatic->n_rhs[i], false, false);
mathomatic->symb_flag = false;
if (exp_contains_nan(mathomatic->rhs[i], mathomatic->n_rhs[i])) {
error(mathomatic, _("Unable to take limit; result contains NaN (Not a Number)."));
return false;
}
/* solve back for the original variable: */
if (solve_sub(&solved_v, 1, lhs[i], &n_lhs[i], rhs[i], &n_rhs[i]) <= 0) {
error(_("Can't take the limit because solve failed."));
if (solve_sub(mathomatic, &solved_v, 1, mathomatic->lhs[i], &mathomatic->n_lhs[i], mathomatic->rhs[i], &mathomatic->n_rhs[i]) <= 0) {
error(mathomatic, _("Can't take the limit because solve failed."));
return false;
}
/* simplify before returning the result: */
simpa_side(rhs[i], &n_rhs[i], false, false);
if (exp_contains_nan(rhs[i], n_rhs[i])) {
error(_("Unable to take limit; result contains NaN (Not a Number)."));
simpa_side(mathomatic, mathomatic->rhs[i], &mathomatic->n_rhs[i], false, false);
if (exp_contains_nan(mathomatic->rhs[i], mathomatic->n_rhs[i])) {
error(mathomatic, _("Unable to take limit; result contains NaN (Not a Number)."));
return false;
}
return return_result(i);
return return_result(mathomatic, i);
}

239
externs.h
View File

@ -22,115 +22,156 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
*/
extern int n_tokens;
extern int n_equations;
extern int cur_equation;
#ifndef MATHO_EXTERNS_H
#define MATHO_EXTERNS_H
extern token_type *lhs[N_EQUATIONS];
extern token_type *rhs[N_EQUATIONS];
typedef struct {
int n_tokens; /* maximum size of expressions, must only be set during startup */
int n_equations; /* number of equation spaces allocated */
int cur_equation; /* current equation space number (origin 0) */
extern int n_lhs[N_EQUATIONS];
extern int n_rhs[N_EQUATIONS];
/* expression storage pointers and current length variables (they go together) */
token_type *lhs[N_EQUATIONS]; /* The Left Hand Sides of equation spaces */
token_type *rhs[N_EQUATIONS]; /* The Right Hand Sides of equation spaces */
extern token_type *tlhs;
extern token_type *trhs;
extern token_type *tes;
int n_lhs[N_EQUATIONS]; /* number of tokens in each lhs[], 0 means equation space is empty */
int n_rhs[N_EQUATIONS]; /* number of tokens in each rhs[], 0 means not an equation */
extern int n_tlhs;
extern int n_trhs;
extern int n_tes;
token_type *tlhs; /* LHS during solve and temporary storage for expressions, quotient for poly_div() and smart_div(). */
token_type *trhs; /* RHS during solve and temporary storage for expressions, remainder for poly_div() and smart_div(). */
token_type *tes; /* Temporary Equation Side, used in commands, simpa_repeat_side(), simple_frac_repeat_side(), etc. */
token_type *scratch; /* Very temporary storage for expressions, used only in low level routines for expression manipulation. */
extern token_type *scratch;
int n_tlhs; /* number of tokens in tlhs */
int n_trhs; /* number of tokens in trhs */
int n_tes; /* number of tokens in tes */
extern token_type zero_token;
extern token_type one_token;
extern int precision;
extern int case_sensitive_flag;
extern int factor_int_flag;
extern int display2d;
extern int fractions_display;
extern int approximate_roots;
extern int preserve_surds;
extern int rationalize_denominators;
extern int modulus_mode;
extern volatile int screen_columns;
extern volatile int screen_rows;
extern int finance_option;
extern int autosolve;
extern int autocalc;
extern int autodelete;
extern int autoselect;
extern char special_variable_characters[256];
extern char plot_prefix[256];
extern int factor_out_all_numeric_gcds;
extern int right_associative_power;
extern int power_starstar;
#if !SILENT
extern int debug_level;
#endif
extern int domain_check;
extern int color_flag;
extern int bold_colors;
extern int text_color;
extern int cur_color;
extern int html_flag;
extern int readline_enabled;
extern int partial_flag;
extern int symb_flag;
extern int symblify;
extern int high_prec;
extern int input_column;
extern int sign_cmp_flag;
extern double small_epsilon;
extern double epsilon;
token_type zero_token; /* the universal constant 0.0 as an expression */
token_type one_token; /* the universal constant 1.0 as an expression */
extern char *prog_name;
extern char *var_names[MAX_VAR_NAMES];
extern char var_str[MAX_VAR_LEN+80];
extern char prompt_str[MAX_PROMPT_LEN];
#if !SECURE
extern char rc_file[MAX_CMD_LEN];
#endif
/* Set options with their initial values. */
int precision; /* the display precision for doubles (number of digits) */
int case_sensitive_flag; /* "set case_sensitive" flag */
int factor_int_flag; /* factor integers when displaying expressions */
int display2d; /* "set no display2d" to allow feeding the output to the input */
int fractions_display; /* "set fraction" mode */
int preserve_surds; /* set option to preserve roots like (2^.5) */
int rationalize_denominators; /* try to rationalize denominators if true */
int modulus_mode; /* true for mathematically correct modulus */
volatile int screen_columns; /* screen width of the terminal; 0 = infinite */
volatile int screen_rows; /* screen height of the terminal; 0 = infinite */
int finance_option; /* for displaying dollars and cents */
int autosolve; /* Allows solving by typing the variable name at the main prompt */
int autocalc; /* Allows automatically calculating a numerical expression */
int autodelete; /* Automatically deletes the previous calculated numerical expression when a new one is entered */
int autoselect; /* Allows selecting equation spaces by typing the number */
char special_variable_characters[256]; /* user defined characters for variable names, '\0' terminated */
/* allow backslash in variable names for Latex compatibility */
char plot_prefix[256]; /* prefix fed into gnuplot before the plot command */
int factor_out_all_numeric_gcds; /* if true, factor out the GCD of rational coefficients */
int right_associative_power; /* if true, evaluate power operators right to left */
int power_starstar; /* if true, display power operator as "**", otherwise "^" */
#if !SILENT
int debug_level; /* current debug level */
#endif
int domain_check;
int color_flag; /* "set color" flag; 0 for no color, 1 for color, 2 for alternative color output mode */
int bold_colors; /* bold_colors must be 0 or 1; 0 is dim */
int text_color; /* Current normal text color, -1 for no color */
int cur_color; /* memory of current color on the terminal */
int html_flag; /* 1 for HTML mode on all standard output; 2 for HTML mode on all output, even redirected output */
/* double precision floating point epsilon constants for number comparisons for equivalency */
double small_epsilon; /* for ignoring small, floating point round-off errors */
double epsilon; /* for ignoring larger, accumulated round-off errors */
#if CYGWIN || MINGW
extern char *dir_path;
#endif
#if READLINE || EDITLINE
extern char *last_history_string;
#endif
#if READLINE
extern char *history_filename;
extern char history_filename_storage[MAX_CMD_LEN];
#endif
/* string variables */
char *prog_name; /* name of this program */
char *var_names[MAX_VAR_NAMES]; /* index for storage of variable name strings */
char var_str[MAX_VAR_LEN+80]; /* temp storage for listing a variable name */
char prompt_str[MAX_PROMPT_LEN]; /* temp storage for the prompt string */
#if !SECURE
char rc_file[MAX_CMD_LEN]; /* pathname for the set options startup file */
#endif
extern double unique[];
extern int ucnt[];
extern int uno;
#if CYGWIN || MINGW
char *dir_path; /* directory path to the executable */
#endif
#if READLINE || EDITLINE
char *last_history_string; /* To prevent repeated, identical entries. Must not point to temporary string. */
#endif
#if READLINE
char *history_filename;
char history_filename_storage[MAX_CMD_LEN];
#endif
extern int previous_return_value;
extern sign_array_type sign_array;
extern FILE *default_out;
extern FILE *gfp;
extern char *gfp_filename;
extern int gfp_append_flag;
extern jmp_buf jmp_save;
extern int eoption;
extern int test_mode;
extern int demo_mode;
extern int quiet_mode;
extern int echo_input;
extern volatile int abort_flag;
extern int pull_number;
extern int security_level;
extern int repeat_flag;
extern int show_usage;
extern int point_flag;
/* The following are for integer factoring (filled by factor_one()): */
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[] */
extern char *result_str;
extern int result_en;
extern const char *error_str;
extern const char *warning_str;
/* misc. variables */
int previous_return_value; /* Return value of last command entered. */
sign_array_type sign_array; /* for keeping track of unique "sign" variables */
FILE *default_out; /* file pointer where all gfp output goes by default */
FILE *gfp; /* global output file pointer, for dynamically redirecting Mathomatic output */
char *gfp_filename; /* filename associated with gfp if redirection is happening */
int gfp_append_flag; /* true if appending to gfp, false if overwriting */
jmp_buf jmp_save; /* for setjmp(3) to longjmp(3) to when an error happens deep within this code */
int eoption; /* -e option flag */
int test_mode; /* test mode flag (-t) */
int demo_mode; /* demo mode flag (-d), don't load rc file or pause commands when true */
int quiet_mode; /* quiet mode (-q, don't display prompts) */
int echo_input; /* if true, echo input */
int readline_enabled; /* set to false (-r) to disable readline */
int partial_flag; /* normally true for partial unfactoring, false for "unfactor fraction" */
int symb_flag; /* true during "simplify symbolic", which is not 100% mathematically correct */
int symblify; /* if true, set symb_flag when helpful during solving, etc. */
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_cmp_flag; /* true when all "sign" variables are to compare equal */
int approximate_roots; /* true if in calculate command (force approximation of roots like (2^.5)) */
volatile int abort_flag; /* if true, abort current operation; set by control-C interrupt */
int pull_number; /* equation space number to pull when using the library */
int security_level; /* current enforced security level for session, -1 for m4 Mathomatic */
int repeat_flag; /* true if the command is to repeat its function or simplification, set by repeat command */
int show_usage; /* show command usage info if a command fails and this flag is true */
int point_flag; /* point to location of parse error if true */
extern char *vscreen[TEXT_ROWS];
extern int current_columns;
/* library variables go here */
char *result_str; /* returned result text string when using as library */
int result_en; /* equation number of the returned result, if stored in an equation space */
const char *error_str; /* last error string */
const char *warning_str; /* last warning string */
/* Screen character array, for buffering page-at-a-time 2D string output: */
char *vscreen[TEXT_ROWS];
int current_columns;
/* Global variables for the optimize command. */
int opt_en[N_EQUATIONS+1];
int last_temp_var;
/* The following data is used to factor integers: */
double nn, sqrt_value;
/* from solve.c */
int repeat_count;
int prev_n1, prev_n2;
int last_int_var;
/* from help.c */
int last_autocalc_en;
/* from integrate.c */
int constant_var_number; /* makes unique numbers for the constant of integration */
/* from list.c */
int cur_line; /* current line */
int cur_pos; /* current position in the current line on the screen */
} MathoMatic;
//extern MathoMatic *mathomatic;
#endif /*MATHO_EXTERNS_H*/

424
factor.c
View File

@ -26,13 +26,13 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#define ALWAYS_FACTOR_POWER 1
static int fplus_recurse(token_type *equation, int *np, int loc, int level, long v, double d, int whole_flag, int div_only);
static int fplus_sub(token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level, long v, double d, int whole_flag, int div_only);
static int big_fplus(token_type *equation, int level, int diff_sign, int sop1, int op1, int op2, int i1, int i2, int b1, int b2, int ai, int aj, int i, int j, int e1, int e2);
static int ftimes_recurse(token_type *equation, int *np, int loc, int level);
static int ftimes_sub(token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level);
static int fpower_recurse(token_type *equation, int *np, int loc, int level);
static int fpower_sub(token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level);
static int fplus_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, long v, double d, int whole_flag, int div_only);
static int fplus_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level, long v, double d, int whole_flag, int div_only);
static int big_fplus(MathoMatic* mathomatic, token_type *equation, int level, int diff_sign, int sop1, int op1, int op2, int i1, int i2, int b1, int b2, int ai, int aj, int i, int j, int e1, int e2);
static int ftimes_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level);
static int ftimes_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level);
static int fpower_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level);
static int fpower_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level);
/*
* Factor divides only: (a/c + b/c) -> ((a+b)/c).
@ -40,13 +40,9 @@ static int fpower_sub(token_type *equation, int *np, int loc, int i1, int n1, in
* Return true if equation side was modified.
*/
int
factor_divide(equation, np, v, d)
token_type *equation;
int *np;
long v;
double d;
factor_divide(MathoMatic* mathomatic, token_type *equation, int *np, long v, double d)
{
return fplus_recurse(equation, np, 0, 1, v, d, false, true);
return fplus_recurse(mathomatic, equation, np, 0, 1, v, d, false, true);
}
/*
@ -56,11 +52,9 @@ double d;
* Return true if equation side was modified.
*/
int
subtract_itself(equation, np)
token_type *equation;
int *np;
subtract_itself(MathoMatic* mathomatic, token_type *equation, int *np)
{
return fplus_recurse(equation, np, 0, 1, 0L, 0.0, true, false);
return fplus_recurse(mathomatic, equation, np, 0, 1, 0L, 0.0, true, false);
}
/*
@ -84,13 +78,13 @@ int *np;
* Return true if equation side was modified.
*/
int
factor_plus(equation, np, v, d)
token_type *equation; /* pointer to beginning of equation side */
int *np; /* pointer to length of equation side */
long v; /* Mathomatic variable */
double d; /* control exponent */
factor_plus(MathoMatic* mathomatic, 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; /* Mathomatic variable */
//double d; /* control exponent */
{
return fplus_recurse(equation, np, 0, 1, v, d, false, false);
return fplus_recurse(mathomatic, equation, np, 0, 1, v, d, false, false);
}
/*
@ -100,13 +94,9 @@ double d; /* control exponent */
* Return true if equation side was modified.
*/
static int
fplus_recurse(equation, np, loc, level, v, d, whole_flag, div_only)
token_type *equation;
int *np, loc, level;
long v;
double d;
int whole_flag; /* factor only whole expressions multiplied by a constant */
int div_only; /* factor only divides */
fplus_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, long v, double d, int whole_flag, int div_only)
//int whole_flag; /* factor only whole expressions multiplied by a constant */
//int div_only; /* factor only divides */
{
int modified = false;
int i, j, k;
@ -137,7 +127,7 @@ f_again:
break;
}
len2 = k - j;
if (fplus_sub(equation, np, loc, i, len1, j, len2, level + 1, v, d, whole_flag, div_only)) {
if (fplus_sub(mathomatic, equation, np, loc, i, len1, j, len2, level + 1, v, d, whole_flag, div_only)) {
modified = true;
goto f_again;
}
@ -151,7 +141,7 @@ f_again:
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, whole_flag, div_only);
modified |= fplus_recurse(mathomatic, equation, np, i, level + 1, v, d, whole_flag, div_only);
i++;
for (; i < *np && equation[i].level > level; i += 2)
;
@ -168,16 +158,12 @@ f_again:
* Return true if a transformation was made.
*/
static int
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 sub-expression */
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 */
fplus_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level, long v, double d, int whole_flag, int 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 sub-expression */
//int whole_flag; /* factor only whole expressions multiplied by a constant */
//int div_only; /* factor only divides */
{
int e1, e2;
int op1, op2;
@ -315,7 +301,7 @@ f_inner:
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);
same_flag = se_compare(mathomatic, &equation[b1], i - b1, &equation[b2], j - b2, &diff_sign);
if (flag1) {
equation[i1].token.constant = save_k1;
b1 += 2;
@ -329,131 +315,131 @@ f_inner:
power = 1.0; /* not doing Horner factoring */
horner_factor:
if (sop1 == DIVIDE) {
scratch[0].level = level;
scratch[0].kind = CONSTANT;
scratch[0].token.constant = 1.0;
scratch[1].level = level;
scratch[1].kind = OPERATOR;
scratch[1].token.operatr = DIVIDE;
mathomatic->scratch[0].level = level;
mathomatic->scratch[0].kind = CONSTANT;
mathomatic->scratch[0].token.constant = 1.0;
mathomatic->scratch[1].level = level;
mathomatic->scratch[1].kind = OPERATOR;
mathomatic->scratch[1].token.operatr = DIVIDE;
len = 2;
} else {
len = 0;
}
k = len;
blt(&scratch[len], &equation[b1], (ai - b1) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b1], (ai - b1) * sizeof(token_type));
len += ai - b1;
if (power != 1.0) {
for (; k < len; k++)
scratch[k].level += 2;
scratch[len].level = level + 1;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = POWER;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = POWER;
len++;
scratch[len].level = level + 1;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = power;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = power;
len++;
if (always_positive(power))
diff_sign = false;
} else if (b1 == i1 && ai == e1) {
for (; k < len; k++)
scratch[k].level++;
mathomatic->scratch[k].level++;
}
scratch[len].level = level;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = TIMES;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
k = len;
blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
blt(&mathomatic->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(token_type));
blt(&mathomatic->scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
len += i - b1;
if (b1 == i1 && i == e1) {
for (; l < len; l++)
scratch[l].level++;
mathomatic->scratch[l].level++;
}
l = m;
m++;
for (; m < len; m++)
scratch[m].level++;
scratch[len].level = scratch[l].level + 1;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = MINUS;
mathomatic->scratch[m].level++;
mathomatic->scratch[len].level = mathomatic->scratch[l].level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = MINUS;
len++;
scratch[len].level = scratch[l].level + 1;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = power;
mathomatic->scratch[len].level = mathomatic->scratch[l].level + 1;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = power;
len++;
scratch[len].level = level;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = TIMES;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
}
scratch[len].level = level;
scratch[len].kind = CONSTANT;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = CONSTANT;
if (op1 == MINUS) {
scratch[len].token.constant = -1.0;
mathomatic->scratch[len].token.constant = -1.0;
} else {
scratch[len].token.constant = 1.0;
mathomatic->scratch[len].token.constant = 1.0;
}
len++;
blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
blt(&mathomatic->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;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = OPERATOR;
diff_sign ^= (op2 == MINUS);
if (diff_sign) {
scratch[len].token.operatr = MINUS;
mathomatic->scratch[len].token.operatr = MINUS;
} else {
scratch[len].token.operatr = PLUS;
mathomatic->scratch[len].token.operatr = PLUS;
}
len++;
k = len;
if (aj != j) {
if (len + n2 + 2 > n_tokens) {
error_huge();
if (len + n2 + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
} else {
if (len + (b2 - i2) + (e2 - j) + 1 > n_tokens) {
error_huge();
if (len + (b2 - i2) + (e2 - j) + 1 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
}
blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
blt(&mathomatic->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(token_type));
blt(&mathomatic->scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
len += j - b2;
l = m;
m++;
for (; m < len; m++)
scratch[m].level++;
scratch[len].level = scratch[l].level + 1;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = MINUS;
mathomatic->scratch[m].level++;
mathomatic->scratch[len].level = mathomatic->scratch[l].level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = MINUS;
len++;
scratch[len].level = scratch[l].level + 1;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = power;
mathomatic->scratch[len].level = mathomatic->scratch[l].level + 1;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = power;
len++;
} else {
scratch[len].level = level;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = 1.0;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = 1.0;
len++;
}
blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
len += e2 - j;
for (; k < len; k++)
scratch[k].level += 2;
mathomatic->scratch[k].level += 2;
end_mess:
if (*np + len - n1 - (n2 + 1) > n_tokens) {
error_huge();
if (*np + len - n1 - (n2 + 1) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
if (op1 == MINUS) {
equation[i1-1].token.operatr = PLUS;
@ -462,7 +448,7 @@ end_mess:
*np -= n2 + 1;
blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(token_type));
*np += len - n1;
blt(&equation[i1], scratch, len * sizeof(token_type));
blt(&equation[i1], mathomatic->scratch, len * sizeof(token_type));
return true;
}
if (whole_flag)
@ -517,7 +503,7 @@ end_mess:
goto f_inner;
if (d == 1.0 && (save_d1 < 0.0 || save_d2 < 0.0))
goto f_inner;
if (se_compare(&equation[b1], ai - b1, &equation[b2], aj - b2, &diff_sign)) {
if (se_compare(mathomatic, &equation[b1], ai - b1, &equation[b2], aj - b2, &diff_sign)) {
if (save_d1 > 0.0 || save_d2 > 0.0) {
if (save_d1 < 0.0) {
power = save_d2;
@ -563,10 +549,10 @@ end_mess:
}
}
if (d1 <= d2) {
len = big_fplus(equation, level, diff_sign, sop1,
len = big_fplus(mathomatic, equation, level, diff_sign, sop1,
op1, op2, i1, i2, b1, b2, ai, aj, i, j, e1, e2);
} else {
len = big_fplus(equation, level, diff_sign, sop1,
len = big_fplus(mathomatic, equation, level, diff_sign, sop1,
op2, op1, i2, i1, b2, b1, aj, ai, j, i, e2, e1);
}
goto end_mess;
@ -579,111 +565,101 @@ end_mess:
* 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)
token_type *equation;
int level;
int diff_sign;
int sop1;
int op1, op2;
int i1, i2;
int b1, b2;
int ai, aj;
int i, j;
int e1, e2;
big_fplus(MathoMatic* mathomatic, token_type *equation, int level, int diff_sign, int sop1, int op1, int op2, int i1, int i2, int b1, int b2, int ai, int aj, int i, int j, int e1, int e2)
{
int k, l, m, n, o;
int len;
if (sop1 == DIVIDE) {
scratch[0].level = level;
scratch[0].kind = CONSTANT;
scratch[0].token.constant = 1.0;
scratch[1].level = level;
scratch[1].kind = OPERATOR;
scratch[1].token.operatr = DIVIDE;
mathomatic->scratch[0].level = level;
mathomatic->scratch[0].kind = CONSTANT;
mathomatic->scratch[0].token.constant = 1.0;
mathomatic->scratch[1].level = level;
mathomatic->scratch[1].kind = OPERATOR;
mathomatic->scratch[1].token.operatr = DIVIDE;
len = 2;
} else {
len = 0;
}
k = len;
o = len + ai - b1;
blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
len += i - b1;
if (b1 == i1 && i == e1) {
for (; k < len; k++)
scratch[k].level++;
mathomatic->scratch[k].level++;
}
scratch[len].level = level;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = TIMES;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
k = len;
blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
len += b1 - i1;
scratch[len].level = level;
scratch[len].kind = CONSTANT;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = CONSTANT;
if (op1 == MINUS) {
scratch[len].token.constant = -1.0;
mathomatic->scratch[len].token.constant = -1.0;
} else {
scratch[len].token.constant = 1.0;
mathomatic->scratch[len].token.constant = 1.0;
}
len++;
blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
blt(&mathomatic->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;
scratch[len].token.operatr = op2;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = op2;
len++;
k = len;
blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
len += b2 - i2;
if (len + (e2 - b2) + 2 * (i - ai) + 2 > n_tokens) {
error_huge();
if (len + (e2 - b2) + 2 * (i - ai) + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
n = len;
m = len + aj - b2;
blt(&scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
len += j - b2;
l = m;
m++;
for (; m < len; m++)
scratch[m].level++;
mathomatic->scratch[m].level++;
if (diff_sign && b2 == i2 && j == e2) {
for (; n < len; n++)
scratch[n].level++;
mathomatic->scratch[n].level++;
}
scratch[len].level = scratch[l].level + 1;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = MINUS;
mathomatic->scratch[len].level = mathomatic->scratch[l].level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = MINUS;
len++;
m = len;
blt(&scratch[len], &equation[ai+1], (i - (ai + 1)) * sizeof(token_type));
blt(&mathomatic->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;
n = min_level(mathomatic, &equation[ai+1], i - (ai + 1));
n = mathomatic->scratch[l].level + 2 - n;
for (; m < len; m++)
scratch[m].level += n;
mathomatic->scratch[m].level += n;
if (diff_sign) {
scratch[len].level = level;
scratch[len].kind = OPERATOR;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
if (sop1 == DIVIDE)
scratch[len].token.operatr = TIMES;
mathomatic->scratch[len].token.operatr = TIMES;
else
scratch[len].token.operatr = DIVIDE;
mathomatic->scratch[len].token.operatr = DIVIDE;
len++;
scratch[len].level = level + 1;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = -1.0;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = -1.0;
len++;
blt(&scratch[len], &scratch[o], (i - ai) * sizeof(token_type));
blt(&mathomatic->scratch[len], &mathomatic->scratch[o], (i - ai) * sizeof(token_type));
len += i - ai;
}
blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
len += e2 - j;
for (; k < len; k++)
scratch[k].level += 2;
mathomatic->scratch[k].level += 2;
return len;
}
@ -693,17 +669,13 @@ int e1, e2;
* Return true if equation side was modified.
*/
int
factor_times(equation, np)
token_type *equation;
int *np;
factor_times(MathoMatic* mathomatic, token_type *equation, int *np)
{
return ftimes_recurse(equation, np, 0, 1);
return ftimes_recurse(mathomatic, equation, np, 0, 1);
}
static int
ftimes_recurse(equation, np, loc, level)
token_type *equation;
int *np, loc, level;
ftimes_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level)
{
int modified = false;
int i, j, k;
@ -734,7 +706,7 @@ f_again:
break;
}
len2 = k - j;
if (ftimes_sub(equation, np, loc, i, len1, j, len2, level + 1)) {
if (ftimes_sub(mathomatic, equation, np, loc, i, len1, j, len2, level + 1)) {
modified = true;
goto f_again;
}
@ -748,7 +720,7 @@ f_again:
return true;
for (i = loc; i < *np && equation[i].level >= level;) {
if (equation[i].level > level) {
modified |= ftimes_recurse(equation, np, i, level + 1);
modified |= ftimes_recurse(mathomatic, equation, np, i, level + 1);
i++;
for (; i < *np && equation[i].level > level; i += 2)
;
@ -760,9 +732,7 @@ f_again:
}
static int
ftimes_sub(equation, np, loc, i1, n1, i2, n2, level)
token_type *equation;
int *np, loc, i1, n1, i2, n2, level;
ftimes_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level)
{
int e1, e2;
int op1, op2;
@ -789,7 +759,7 @@ int *np, loc, i1, n1, i2, n2, level;
}
#endif
both_divide = (op1 == DIVIDE && op2 == DIVIDE);
if (se_compare(&equation[i1], n1, &equation[i2], n2, &diff_sign)) {
if (se_compare(mathomatic, &equation[i1], n1, &equation[i2], n2, &diff_sign)) {
i = e1;
j = e2;
goto common_base;
@ -807,15 +777,15 @@ int *np, loc, i1, n1, i2, n2, level;
if (i >= e1 && j >= e2) {
return false;
}
if (se_compare(&equation[i1], i - i1, &equation[i2], j - i2, &diff_sign)) {
if (se_compare(mathomatic, &equation[i1], i - i1, &equation[i2], j - i2, &diff_sign)) {
goto common_base;
}
if (i < e1 && j < e2) {
if (se_compare(&equation[i1], n1, &equation[i2], j - i2, &diff_sign)) {
if (se_compare(mathomatic, &equation[i1], n1, &equation[i2], j - i2, &diff_sign)) {
i = e1;
goto common_base;
}
if (se_compare(&equation[i1], i - i1, &equation[i2], n2, &diff_sign)) {
if (se_compare(mathomatic, &equation[i1], i - i1, &equation[i2], n2, &diff_sign)) {
j = e2;
goto common_base;
}
@ -833,8 +803,8 @@ common_base:
if (j - i2 == 1 && equation[i2].kind == CONSTANT)
return false;
len2 = 2 + e2 - j;
if (*np + len2 + len > n_tokens) {
error_huge();
if (*np + len2 + len > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[e2+len2], &equation[e2], (*np - e2) * sizeof(token_type));
*np += len2;
@ -846,8 +816,8 @@ common_base:
equation[e2+1].token.constant = -1.0;
blt(&equation[e2+2], &equation[j], (e2 - j) * sizeof(token_type));
}
if (*np + len > n_tokens) {
error_huge();
if (*np + len > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[e1+len], &equation[e1], (*np - e1) * sizeof(token_type));
*np += len;
@ -901,17 +871,13 @@ common_base:
* Return true if equation side was modified.
*/
int
factor_power(equation, np)
token_type *equation;
int *np;
factor_power(MathoMatic* mathomatic, token_type *equation, int *np)
{
return fpower_recurse(equation, np, 0, 1);
return fpower_recurse(mathomatic, equation, np, 0, 1);
}
static int
fpower_recurse(equation, np, loc, level)
token_type *equation;
int *np, loc, level;
fpower_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level)
{
int modified = false;
int i, j, k;
@ -942,7 +908,7 @@ f_again:
break;
}
len2 = k - j;
if (fpower_sub(equation, np, loc, i, len1, j, len2, level + 1)) {
if (fpower_sub(mathomatic, equation, np, loc, i, len1, j, len2, level + 1)) {
modified = true;
goto f_again;
}
@ -955,7 +921,7 @@ f_again:
for (i = loc; i < *np && equation[i].level >= level;) {
if (equation[i].level > level) {
modified |= fpower_recurse(equation, np, i, level + 1);
modified |= fpower_recurse(mathomatic, equation, np, i, level + 1);
i++;
for (; i < *np && equation[i].level > level; i += 2)
;
@ -967,9 +933,7 @@ f_again:
}
static int
fpower_sub(equation, np, loc, i1, n1, i2, n2, level)
token_type *equation;
int *np, loc, i1, n1, i2, n2, level;
fpower_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level)
{
int e1, e2;
int op1, op2;
@ -1048,10 +1012,10 @@ int *np, loc, i1, n1, i2, n2, level;
#endif
start2 = j;
#if 1
if (se_compare(&equation[i+1], e1 - (i + 1), &one_token, 1, &diff_sign)) {
if (se_compare(mathomatic, &equation[i+1], e1 - (i + 1), &mathomatic->one_token, 1, &diff_sign)) {
return false;
}
if (se_compare(&equation[i+1], e1 - (i + 1), &equation[j+1], e2 - (j + 1), &diff_sign)) {
if (se_compare(mathomatic, &equation[i+1], e1 - (i + 1), &equation[j+1], e2 - (j + 1), &diff_sign)) {
b1 = i + 1;
b2 = j + 1;
i = e1;
@ -1075,7 +1039,7 @@ fp_outer:
break;
}
}
if (se_compare(&equation[b1], i - b1, &one_token, 1, &diff_sign)) {
if (se_compare(mathomatic, &equation[b1], i - b1, &mathomatic->one_token, 1, &diff_sign)) {
goto fp_outer;
}
j = start2;
@ -1097,66 +1061,66 @@ fp_inner:
} else if (equation[b2-1].token.operatr != pop1) {
goto fp_inner;
}
if (se_compare(&equation[b1], i - b1, &equation[b2], j - b2, &diff_sign)) {
if (se_compare(mathomatic, &equation[b1], i - b1, &equation[b2], j - b2, &diff_sign)) {
common_exponent:
if (op2 == DIVIDE)
diff_sign = !diff_sign;
all_divide = (op1 == DIVIDE && diff_sign);
len = 0;
blt(&scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[i1], (b1 - i1) * sizeof(token_type));
len += b1 - i1;
scratch[len].level = level + 1;
scratch[len].kind = CONSTANT;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = CONSTANT;
if (!all_divide && op1 == DIVIDE) {
scratch[len].token.constant = -1.0;
mathomatic->scratch[len].token.constant = -1.0;
} else {
scratch[len].token.constant = 1.0;
mathomatic->scratch[len].token.constant = 1.0;
}
len++;
blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
len += e1 - i;
for (k = 0; k < len; k++)
scratch[k].level += 2;
scratch[len].level = level + 1;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = TIMES;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
k = len;
blt(&scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[i2], (b2 - i2) * sizeof(token_type));
len += b2 - i2;
scratch[len].level = level + 1;
scratch[len].kind = CONSTANT;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = CONSTANT;
if (!all_divide && diff_sign) {
scratch[len].token.constant = -1.0;
mathomatic->scratch[len].token.constant = -1.0;
} else {
scratch[len].token.constant = 1.0;
mathomatic->scratch[len].token.constant = 1.0;
}
len++;
blt(&scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[j], (e2 - j) * sizeof(token_type));
len += e2 - j;
for (; k < len; k++)
scratch[k].level += 2;
scratch[len].level = level;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = POWER;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = POWER;
len++;
if (pop1 == DIVIDE) {
scratch[len].level = level + 1;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = 1.0;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = 1.0;
len++;
scratch[len].level = level + 1;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = DIVIDE;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = DIVIDE;
len++;
}
k = len;
blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
len += i - b1;
for (; k < len; k++)
scratch[k].level++;
if (*np + len - n1 - (n2 + 1) > n_tokens) {
error_huge();
mathomatic->scratch[k].level++;
if (*np + len - n1 - (n2 + 1) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
if (!all_divide && op1 == DIVIDE) {
equation[i1-1].token.operatr = TIMES;
@ -1165,7 +1129,7 @@ common_exponent:
*np -= n2 + 1;
blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(token_type));
*np += len - n1;
blt(&equation[i1], scratch, len * sizeof(token_type));
blt(&equation[i1], mathomatic->scratch, len * sizeof(token_type));
return true;
}
goto fp_inner;

View File

@ -24,12 +24,11 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#include "includes.h"
static void try_factor(double arg);
static int fc_recurse(token_type *equation, int *np, int loc, int level, int level_code);
static void try_factor(MathoMatic* mathomatic, double arg);
static int fc_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, int level_code);
/* The following data is used to factor integers: */
static double nn, sqrt_value;
static double skip_multiples[] = { /* Additive array that skips over multiples of 2, 3, 5, and 7. */
static const 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,
@ -45,53 +44,52 @@ static double skip_multiples[] = { /* Additive array that skips over multiples o
* Return true if successful.
*/
int
factor_one(value)
double value;
factor_one(MathoMatic* mathomatic, double value)
{
int i;
double d;
uno = 0;
nn = value;
if (nn == 0.0 || !isfinite(nn)) {
mathomatic->uno = 0;
mathomatic->nn = value;
if (mathomatic->nn == 0.0 || !isfinite(mathomatic->nn)) {
/* zero or not finite */
return false;
}
if (fabs(nn) >= MAX_K_INTEGER) {
if (fabs(mathomatic->nn) >= MAX_K_INTEGER) {
/* too large to factor */
return false;
}
if (fmod(nn, 1.0) != 0.0) {
if (fmod(mathomatic->nn, 1.0) != 0.0) {
/* not an integer */
return false;
}
sqrt_value = 1.0 + sqrt(fabs(nn));
try_factor(2.0);
try_factor(3.0);
try_factor(5.0);
try_factor(7.0);
mathomatic->sqrt_value = 1.0 + sqrt(fabs(mathomatic->nn));
try_factor(mathomatic, 2.0);
try_factor(mathomatic, 3.0);
try_factor(mathomatic, 5.0);
try_factor(mathomatic, 7.0);
d = 1.0;
while (d <= sqrt_value) {
while (d <= mathomatic->sqrt_value) {
for (i = 0; i < ARR_CNT(skip_multiples); i++) {
d += skip_multiples[i];
try_factor(d);
try_factor(mathomatic, d);
}
}
if (nn != 1.0) {
if (nn < 0 && nn != -1.0) {
try_factor(fabs(nn));
if (mathomatic->nn != 1.0) {
if (mathomatic->nn < 0 && mathomatic->nn != -1.0) {
try_factor(mathomatic, fabs(mathomatic->nn));
}
try_factor(nn);
try_factor(mathomatic, mathomatic->nn);
}
if (uno == 0) {
try_factor(1.0);
if (mathomatic->uno == 0) {
try_factor(mathomatic, 1.0);
}
/* Do some floating point arithmetic self-checking. If the following fails, it is due to a floating point bug. */
if (nn != 1.0) {
error_bug("Internal error factoring integers (final nn != 1.0).");
if (mathomatic->nn != 1.0) {
error_bug(mathomatic, "Internal error factoring integers (final nn != 1.0).");
}
if (value != multiply_out_unique()) {
error_bug("Internal error factoring integers (result array value is incorrect).");
if (value != multiply_out_unique(mathomatic)) {
error_bug(mathomatic, "Internal error factoring integers (result array value is incorrect).");
}
return true;
}
@ -101,31 +99,30 @@ double value;
* If so, save it and remove it from "nn".
*/
static void
try_factor(arg)
double arg;
try_factor(MathoMatic* mathomatic, double arg)
{
#if DEBUG
if (fmod(arg, 1.0) != 0.0) {
error_bug("Trying factor that is not an integer!");
error_bug(mathomatic, "Trying factor that is not an integer!");
}
#endif
while (fmod(nn, arg) == 0.0) {
if (uno > 0 && ucnt[uno-1] > 0 && unique[uno-1] == arg) {
ucnt[uno-1]++;
while (fmod(mathomatic->nn, arg) == 0.0) {
if (mathomatic->uno > 0 && mathomatic->ucnt[mathomatic->uno-1] > 0 && mathomatic->unique[mathomatic->uno-1] == arg) {
mathomatic->ucnt[mathomatic->uno-1]++;
} else {
while (uno > 0 && ucnt[uno-1] <= 0)
uno--;
unique[uno] = arg;
ucnt[uno++] = 1;
while (mathomatic->uno > 0 && mathomatic->ucnt[mathomatic->uno-1] <= 0)
mathomatic->uno--;
mathomatic->unique[mathomatic->uno] = arg;
mathomatic->ucnt[mathomatic->uno++] = 1;
}
nn /= arg;
mathomatic->nn /= arg;
#if DEBUG
if (fmod(nn, 1.0) != 0.0) {
error_bug("nn turned non-integer in try_factor().");
if (fmod(mathomatic->nn, 1.0) != 0.0) {
error_bug(mathomatic, "nn turned non-integer in try_factor().");
}
#endif
sqrt_value = 1.0 + sqrt(fabs(nn));
if (fabs(nn) <= 1.5 || fabs(arg) <= 1.5)
mathomatic->sqrt_value = 1.0 + sqrt(fabs(mathomatic->nn));
if (fabs(mathomatic->nn) <= 1.5 || fabs(arg) <= 1.5)
break;
}
}
@ -136,20 +133,20 @@ double arg;
* Nothing is changed and the value is returned.
*/
double
multiply_out_unique(void)
multiply_out_unique(MathoMatic* mathomatic)
{
int i, j;
double d;
d = 1.0;
for (i = 0; i < uno; i++) {
for (i = 0; i < mathomatic->uno; i++) {
#if DEBUG
if (ucnt[i] < 0) {
error_bug("Error in ucnt[] being negative.");
if (mathomatic->ucnt[i] < 0) {
error_bug(mathomatic, "Error in ucnt[] being negative.");
}
#endif
for (j = 0; j < ucnt[i]; j++) {
d *= unique[i];
for (j = 0; j < mathomatic->ucnt[i]; j++) {
d *= mathomatic->unique[i];
}
}
return d;
@ -163,33 +160,33 @@ multiply_out_unique(void)
* Return true if successful.
*/
int
display_unique(void)
display_unique(MathoMatic* mathomatic)
{
int i;
double value;
if (uno <= 0)
if (mathomatic->uno <= 0)
return false;
value = multiply_out_unique();
fprintf(gfp, "%.0f = ", value);
for (i = 0; i < uno;) {
if (ucnt[i] > 0) {
fprintf(gfp, "%.0f", unique[i]);
value = multiply_out_unique(mathomatic);
fprintf(mathomatic->gfp, "%.0f = ", value);
for (i = 0; i < mathomatic->uno;) {
if (mathomatic->ucnt[i] > 0) {
fprintf(mathomatic->gfp, "%.0f", mathomatic->unique[i]);
} else {
i++;
continue;
}
if (ucnt[i] > 1) {
fprintf(gfp, "^%d", ucnt[i]);
if (mathomatic->ucnt[i] > 1) {
fprintf(mathomatic->gfp, "^%d", mathomatic->ucnt[i]);
}
do {
i++;
} while (i < uno && ucnt[i] <= 0);
if (i < uno) {
fprintf(gfp, " * ");
} while (i < mathomatic->uno && mathomatic->ucnt[i] <= 0);
if (i < mathomatic->uno) {
fprintf(mathomatic->gfp, " * ");
}
}
fprintf(gfp, "\n");
fprintf(mathomatic->gfp, "\n");
return true;
}
@ -199,20 +196,20 @@ display_unique(void)
* Return true if x is a prime number.
*/
int
is_prime(void)
is_prime(MathoMatic* mathomatic)
{
double value;
if (uno <= 0) {
if (mathomatic->uno <= 0) {
#if DEBUG
error_bug("uno == 0 in is_prime().");
error_bug(mathomatic, "uno == 0 in is_prime().");
#endif
return false;
}
value = multiply_out_unique();
value = multiply_out_unique(mathomatic);
if (value < 2.0)
return false;
if (uno == 1 && ucnt[0] == 1)
if (mathomatic->uno == 1 && mathomatic->ucnt[0] == 1)
return true;
return false;
}
@ -223,9 +220,7 @@ is_prime(void)
* Return true if the equation side was modified.
*/
int
factor_int(equation, np)
token_type *equation;
int *np;
factor_int(MathoMatic* mathomatic, token_type *equation, int *np)
{
int i, j;
int xsize;
@ -233,24 +228,24 @@ int *np;
int modified = false;
for (i = 0; i < *np; i += 2) {
if (equation[i].kind == CONSTANT && factor_one(equation[i].token.constant) && uno > 0) {
if (uno == 1 && ucnt[0] <= 1)
if (equation[i].kind == CONSTANT && factor_one(mathomatic, equation[i].token.constant) && mathomatic->uno > 0) {
if (mathomatic->uno == 1 && mathomatic->ucnt[0] <= 1)
continue; /* prime number */
level = equation[i].level;
if (uno > 1 && *np > 1)
if (mathomatic->uno > 1 && *np > 1)
level++;
xsize = -2;
for (j = 0; j < uno; j++) {
if (ucnt[j] > 1)
for (j = 0; j < mathomatic->uno; j++) {
if (mathomatic->ucnt[j] > 1)
xsize += 4;
else
xsize += 2;
}
if (*np + xsize > n_tokens) {
error_huge();
if (*np + xsize > mathomatic->n_tokens) {
error_huge(mathomatic);
}
for (j = 0; j < uno; j++) {
if (ucnt[j] > 1)
for (j = 0; j < mathomatic->uno; j++) {
if (mathomatic->ucnt[j] > 1)
xsize = 4;
else
xsize = 2;
@ -269,8 +264,8 @@ int *np;
}
equation[i].kind = CONSTANT;
equation[i].level = level;
equation[i].token.constant = unique[j];
if (ucnt[j] > 1) {
equation[i].token.constant = mathomatic->unique[j];
if (mathomatic->ucnt[j] > 1) {
equation[i].level = level + 1;
i++;
equation[i].kind = OPERATOR;
@ -279,7 +274,7 @@ int *np;
i++;
equation[i].level = level + 1;
equation[i].kind = CONSTANT;
equation[i].token.constant = ucnt[j];
equation[i].token.constant = mathomatic->ucnt[j];
}
}
modified = true;
@ -294,16 +289,16 @@ int *np;
* Return true if something was factored.
*/
int
factor_int_equation(n)
int n; /* equation space number */
factor_int_equation(MathoMatic* mathomatic, int n)
//int n; /* equation space number */
{
int rv = false;
if (empty_equation_space(n))
if (empty_equation_space(mathomatic, n))
return rv;
if (factor_int(lhs[n], &n_lhs[n]))
if (factor_int(mathomatic, mathomatic->lhs[n], &mathomatic->n_lhs[n]))
rv = true;
if (factor_int(rhs[n], &n_rhs[n]))
if (factor_int(mathomatic, mathomatic->rhs[n], &mathomatic->n_rhs[n]))
rv = true;
return rv;
}
@ -312,15 +307,12 @@ int n; /* equation space number */
* List an equation side with optional integer factoring.
*/
int
list_factor(equation, np, factor_flag)
token_type *equation;
int *np;
int factor_flag;
list_factor(MathoMatic* mathomatic, token_type *equation, int *np, int factor_flag)
{
if (factor_flag || factor_int_flag) {
factor_int(equation, np);
if (factor_flag || mathomatic->factor_int_flag) {
factor_int(mathomatic, equation, np);
}
return list_proc(equation, *np, false);
return list_proc(mathomatic, equation, *np, false);
}
/*
@ -352,21 +344,18 @@ int factor_flag;
* Return true if equation side was modified.
*/
int
factor_constants(equation, np, 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 */
factor_constants(MathoMatic* mathomatic, 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 == 3)
return false;
return fc_recurse(equation, np, 0, 1, level_code);
return fc_recurse(mathomatic, equation, np, 0, 1, level_code);
}
static int
fc_recurse(equation, np, loc, level, level_code)
token_type *equation;
int *np, loc, level;
int level_code;
fc_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, int level_code)
{
int i, j, k, eloc;
int op;
@ -376,7 +365,7 @@ int level_code;
for (i = loc; i < *np && equation[i].level >= level;) {
if (equation[i].level > level) {
modified |= fc_recurse(equation, np, i, level + 1, level_code);
modified |= fc_recurse(mathomatic, equation, np, i, level + 1, level_code);
i++;
for (; i < *np && equation[i].level > level; i += 2)
;
@ -387,7 +376,7 @@ int level_code;
if (modified)
return true;
improve_readability = ((level_code & 3) > 1 || ((level_code & 3) && (level == 1)));
gcd_flag = ((improve_readability && factor_out_all_numeric_gcds) || (level_code & 4));
gcd_flag = ((improve_readability && mathomatic->factor_out_all_numeric_gcds) || (level_code & 4));
for (i = loc; i < *np && equation[i].level >= level;) {
if (equation[i].level == level) {
switch (equation[i].kind) {
@ -422,14 +411,14 @@ int level_code;
if (minimum > d)
minimum = d;
if (gcd_flag && cogcd != 0.0)
cogcd = gcd_verified(d, cogcd);
cogcd = gcd_verified(mathomatic, d, cogcd);
}
} else {
op = 0;
for (j = i + 1; j < *np && equation[j].level > level; j += 2) {
#if DEBUG
if (equation[j].kind != OPERATOR) {
error_bug("Bug in factor_constants().");
error_bug(mathomatic, "Bug in factor_constants().");
}
#endif
if (equation[j].level == level + 1) {
@ -455,7 +444,7 @@ int level_code;
if (minimum > d)
minimum = d;
if (gcd_flag && cogcd != 0.0)
cogcd = gcd_verified(d, cogcd);
cogcd = gcd_verified(mathomatic, d, cogcd);
}
i = j;
}
@ -473,7 +462,7 @@ int level_code;
if (minimum > 1.0)
minimum = 1.0;
if (gcd_flag && cogcd != 0.0)
cogcd = gcd_verified(1.0, cogcd);
cogcd = gcd_verified(mathomatic, 1.0, cogcd);
}
i = j;
continue;
@ -529,8 +518,8 @@ int level_code;
minimum = -minimum;
if (minimum == 1.0)
return modified;
if (*np + ((op_count + 2) * 2) > n_tokens) {
error_huge();
if (*np + ((op_count + 2) * 2) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
for (i = loc; i < *np && equation[i].level >= level; i++) {
if (equation[i].kind != OPERATOR) {

76
gcd.c
View File

@ -42,8 +42,7 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
* Returns 0 on failure, otherwise returns the positive GCD.
*/
double
gcd(d1, d2)
double d1, d2;
gcd(MathoMatic* mathomatic, double d1, double d2)
{
int count;
double larger, divisor, remainder1, lower_limit;
@ -66,7 +65,7 @@ double d1, d2;
larger = d2;
divisor = d1;
}
lower_limit = larger * epsilon;
lower_limit = larger * mathomatic->epsilon;
if (divisor <= lower_limit || larger >= MAX_K_INTEGER) {
return 0.0; /* out of range, result would be too inaccurate */
}
@ -92,18 +91,17 @@ double d1, d2;
* Result is not necessarily integer unless both d1 and d2 are integer.
*/
double
gcd_verified(d1, d2)
double d1, d2;
gcd_verified(MathoMatic* mathomatic, double d1, double d2)
{
double divisor, d3, d4;
divisor = gcd(d1, d2);
divisor = gcd(mathomatic, d1, d2);
if (divisor != 0.0) {
d3 = d1 / divisor;
d4 = d2 / divisor;
if (fmod(d3, 1.0) != 0.0 || fmod(d4, 1.0) != 0.0)
return 0.0;
if (gcd(d3, d4) != 1.0)
if (gcd(mathomatic, d3, d4) != 1.0)
return 0.0;
}
return divisor;
@ -141,10 +139,10 @@ double d1; /* value to round */
* True return indicates d is rational and finite, otherwise d is probably irrational.
*/
int
f_to_fraction(d, numeratorp, denominatorp)
double d; /* floating point number to convert */
double *numeratorp; /* returned numerator */
double *denominatorp; /* returned denominator */
f_to_fraction(MathoMatic* mathomatic, double d, double *numeratorp, double *denominatorp)
//double d; /* floating point number to convert */
//double *numeratorp; /* returned numerator */
//double *denominatorp; /* returned denominator */
{
double divisor;
double numerator, denominator;
@ -163,7 +161,7 @@ double *denominatorp; /* returned denominator */
/* more than 15 digits in number means we do nothing (for better accuracy) */
if (fabs(d) >= MAX_K_INTEGER)
return false;
k3 = fabs(d) * small_epsilon;
k3 = fabs(d) * mathomatic->small_epsilon;
if (k3 >= .5)
return false; /* fixes "factor number 17!" to give error instead of wrong answer */
k4 = my_round(d);
@ -173,7 +171,7 @@ double *denominatorp; /* returned denominator */
return true;
}
/* try to convert non-integer floating point value in "d" to a fraction: */
if ((divisor = gcd(1.0, d)) > epsilon) {
if ((divisor = gcd(mathomatic, 1.0, d)) > mathomatic->epsilon) {
numerator = my_round(d / divisor);
denominator = my_round(1.0 / divisor);
/* don't allow more than 11 digits in the numerator or denominator: */
@ -182,19 +180,19 @@ double *denominatorp; /* returned denominator */
if (denominator >= 1.0e12 || denominator < 2.0)
return false;
/* make sure the result is a fully reduced fraction: */
divisor = gcd(numerator, denominator);
divisor = gcd(mathomatic, numerator, denominator);
if (divisor > 1.0) { /* just in case result isn't already fully reduced */
numerator /= divisor;
denominator /= divisor;
}
k3 = (numerator / denominator);
if (fabs(k3 - d) > (small_epsilon * fabs(k3))) {
if (fabs(k3 - d) > (mathomatic->small_epsilon * fabs(k3))) {
return false; /* result is too inaccurate */
}
if (fmod(numerator, 1.0) != 0.0 || fmod(denominator, 1.0) != 0.0) {
/* Shouldn't happen if everything works. */
#if DEBUG
error_bug("Fraction should have been fully reduced by gcd(), but was not.");
error_bug(mathomatic, "Fraction should have been fully reduced by gcd(), but was not.");
#endif
return false;
}
@ -213,16 +211,16 @@ double *denominatorp; /* returned denominator */
* Returns true if any fractions were created.
*/
int
make_fractions(equation, np)
token_type *equation; /* equation side pointer */
int *np; /* pointer to length of equation side */
make_fractions(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* equation side pointer */
//int *np; /* pointer to length of equation side */
{
switch (fractions_display) {
switch (mathomatic->fractions_display) {
case 2:
return make_mixed_fractions(equation, np);
return make_mixed_fractions(mathomatic, equation, np);
break;
default:
return make_simple_fractions(equation, np);
return make_simple_fractions(mathomatic, equation, np);
break;
}
}
@ -236,9 +234,9 @@ int *np; /* pointer to length of equation side */
* Returns true if any fractions were created.
*/
int
make_simple_fractions(equation, np)
token_type *equation; /* equation side pointer */
int *np; /* pointer to length of equation side */
make_simple_fractions(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* equation side pointer */
//int *np; /* pointer to length of equation side */
{
int i, j, k;
int level;
@ -250,14 +248,14 @@ int *np; /* pointer to length of equation side */
level = equation[i].level;
if (i > 0 && equation[i-1].level == level && (equation[i-1].token.operatr == DIVIDE /* || equation[i-1].token.operatr == POWER */))
continue;
if (!f_to_fraction(equation[i].token.constant, &numerator, &denominator))
if (!f_to_fraction(mathomatic, equation[i].token.constant, &numerator, &denominator))
continue;
if (denominator == 1.0) {
equation[i].token.constant = numerator;
continue;
}
if ((*np + 2) > n_tokens) {
error_huge();
if ((*np + 2) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
modified = true;
inc_level = (*np > 1);
@ -324,9 +322,9 @@ int *np; /* pointer to length of equation side */
* Returns true if any fractions were created.
*/
int
make_mixed_fractions(equation, np)
token_type *equation; /* equation side pointer */
int *np; /* pointer to length of equation side */
make_mixed_fractions(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* equation side pointer */
//int *np; /* pointer to length of equation side */
{
int i, j, k;
int level;
@ -338,7 +336,7 @@ int *np; /* pointer to length of equation side */
level = equation[i].level;
if (i > 0 && equation[i-1].level == level && (equation[i-1].token.operatr == DIVIDE /* || equation[i-1].token.operatr == POWER */))
continue;
if (!f_to_fraction(equation[i].token.constant, &numerator, &denominator))
if (!f_to_fraction(mathomatic, equation[i].token.constant, &numerator, &denominator))
continue;
if (denominator == 1.0) {
equation[i].token.constant = numerator;
@ -349,8 +347,8 @@ int *np; /* pointer to length of equation side */
remainder1 = modf(fabs(numerator) / denominator, &quotient1);
remainder1 = my_round(remainder1 * denominator);
if (numerator < 0.0) {
if ((*np + 6) > n_tokens) {
error_huge();
if ((*np + 6) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[i+7], &equation[i+1], (*np - (i + 1)) * sizeof(token_type));
*np += 6;
@ -381,8 +379,8 @@ int *np; /* pointer to length of equation side */
equation[i].kind = CONSTANT;
equation[i].token.constant = denominator;
} else {
if ((*np + 4) > n_tokens) {
error_huge();
if ((*np + 4) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[i+5], &equation[i+1], (*np - (i + 1)) * sizeof(token_type));
*np += 4;
@ -406,8 +404,8 @@ int *np; /* pointer to length of equation side */
equation[i].token.constant = denominator;
}
} else {
if ((*np + 2) > n_tokens) {
error_huge();
if ((*np + 2) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
inc_level = (*np > 1);
if ((i + 1) < *np && equation[i+1].level == level) {
@ -462,7 +460,7 @@ int *np; /* pointer to length of equation side */
}
}
if (modified) {
organize(equation, np);
organize(mathomatic, equation, np);
}
return modified;
}

219
globals.c
View File

@ -28,147 +28,108 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#include "includes.h"
int n_tokens = DEFAULT_N_TOKENS; /* maximum size of expressions, must only be set during startup */
//MathoMatic *mathomatic;
int n_equations, /* number of equation spaces allocated */
cur_equation; /* current equation space number (origin 0) */
MathoMatic *newtMathoMatic(void) {
MathoMatic *mathomatic = malloc(sizeof(MathoMatic));
if(!mathomatic) return NULL;
memset(mathomatic, 0, sizeof(MathoMatic));
/* expression storage pointers and current length variables (they go together) */
token_type *lhs[N_EQUATIONS], /* The Left Hand Sides of equation spaces */
*rhs[N_EQUATIONS]; /* The Right Hand Sides of equation spaces */
mathomatic->n_tokens = DEFAULT_N_TOKENS; /* maximum size of expressions, must only be set during startup */
/* Set options with their initial values. */
mathomatic->precision = 14; /* the display precision for doubles (number of digits) */
mathomatic->case_sensitive_flag = true; /* "set case_sensitive" flag */
#if LIBRARY && !ROBOT_COMMAND
mathomatic->display2d = false; /* "set no display2d" to allow feeding the output to the input */
#else
mathomatic->display2d = true; /* "set display2d" flag for 2D display */
#endif
mathomatic->fractions_display = 1; /* "set fraction" mode */
mathomatic->preserve_surds = true; /* set option to preserve roots like (2^.5) */
mathomatic->rationalize_denominators = true; /* try to rationalize denominators if true */
mathomatic->modulus_mode = 2; /* true for mathematically correct modulus */
mathomatic->screen_columns = STANDARD_SCREEN_COLUMNS; /* screen width of the terminal; 0 = infinite */
mathomatic->screen_rows = STANDARD_SCREEN_ROWS; /* screen height of the terminal; 0 = infinite */
mathomatic->finance_option = -1; /* for displaying dollars and cents */
mathomatic->autosolve = true; /* Allows solving by typing the variable name at the main prompt */
mathomatic->autocalc = true; /* Allows automatically calculating a numerical expression */
mathomatic->autodelete = false; /* Automatically deletes the previous calculated numerical expression when a new one is entered */
mathomatic->autoselect = true; /* Allows selecting equation spaces by typing the number */
#if LIBRARY
strcpy(mathomatic->special_variable_characters, "\\[]"); /* allow backslash in variable names for Latex compatibility */
#else
strcpy(mathomatic->special_variable_characters, "'\\[]"); /* user defined characters for variable names, '\0' terminated */
#endif
#if MINGW
strcpy(mathomatic->plot_prefix, "set grid; set xlabel 'X'; set ylabel 'Y';"); /* prefix fed into gnuplot before the plot command */
#else
strcpy(mathomatic->plot_prefix, "set grid; set xlabel \"X\"; set ylabel \"Y\";"); /* prefix fed into gnuplot before the plot command */
#endif
mathomatic->factor_out_all_numeric_gcds = false; /* if true, factor out the GCD of rational coefficients */
int n_lhs[N_EQUATIONS], /* number of tokens in each lhs[], 0 means equation space is empty */
n_rhs[N_EQUATIONS]; /* number of tokens in each rhs[], 0 means not an equation */
/* variables having to do with color output mode */
#if LIBRARY || NO_COLOR
mathomatic->color_flag = 0; /* library shouldn't default to color mode */
#else
mathomatic->color_flag = 1; /* "set color" flag; 0 for no color, 1 for color, 2 for alternative color output mode */
#endif
#if BOLD_COLOR
mathomatic->bold_colors = 1; /* "set bold color" flag for brighter colors */
#else
mathomatic->bold_colors = 0; /* bold_colors must be 0 or 1; 0 is dim */
#endif
mathomatic->text_color = -1; /* Current normal text color, -1 for no color */
mathomatic->cur_color = -1; /* memory of current color on the terminal */
token_type *tlhs, /* LHS during solve and temporary storage for expressions, quotient for poly_div() and smart_div(). */
*trhs, /* RHS during solve and temporary storage for expressions, remainder for poly_div() and smart_div(). */
*tes, /* Temporary Equation Side, used in commands, simpa_repeat_side(), simple_frac_repeat_side(), etc. */
*scratch; /* Very temporary storage for expressions, used only in low level routines for expression manipulation. */
/* Do not run any functions on scratch[], except for blt() (which is memmove(3)). */
/* double precision floating point epsilon constants for number comparisons for equivalency */
mathomatic->small_epsilon = 0.000000000000005; /* for ignoring small, floating point round-off errors */
mathomatic->epsilon = 0.00000000000005; /* for ignoring larger, accumulated round-off errors */
int n_tlhs, /* number of tokens in tlhs */
n_trhs, /* number of tokens in trhs */
n_tes; /* number of tokens in tes */
/* string variables */
mathomatic->prog_name = "mathomatic"; /* name of this program */
token_type zero_token, /* the universal constant 0.0 as an expression */
one_token; /* the universal constant 1.0 as an expression */
/* misc. variables */
mathomatic->previous_return_value = 1; /* Return value of last command entered. */
mathomatic->readline_enabled = true; /* set to false (-r) to disable readline */
mathomatic->symblify = true; /* if true, set symb_flag when helpful during solving, etc. */
/* Set options with their initial values. */
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 */
#if LIBRARY && !ROBOT_COMMAND
int display2d = false; /* "set no display2d" to allow feeding the output to the input */
#else
int display2d = true; /* "set display2d" flag for 2D display */
#endif
int fractions_display = 1; /* "set fraction" mode */
int preserve_surds = true; /* set option to preserve roots like (2^.5) */
int rationalize_denominators = true; /* try to rationalize denominators if true */
int modulus_mode = 2; /* true for mathematically correct modulus */
volatile int screen_columns = STANDARD_SCREEN_COLUMNS; /* screen width of the terminal; 0 = infinite */
volatile int screen_rows = STANDARD_SCREEN_ROWS; /* screen height of the terminal; 0 = infinite */
int finance_option = -1; /* for displaying dollars and cents */
int autosolve = true; /* Allows solving by typing the variable name at the main prompt */
int autocalc = true; /* Allows automatically calculating a numerical expression */
int autodelete = false; /* Automatically deletes the previous calculated numerical expression when a new one is entered */
int autoselect = true; /* Allows selecting equation spaces by typing the number */
#if LIBRARY
char special_variable_characters[256] = "\\[]"; /* allow backslash in variable names for Latex compatibility */
#else
char special_variable_characters[256] = "'\\[]"; /* user defined characters for variable names, '\0' terminated */
#endif
#if MINGW
char plot_prefix[256] = "set grid; set xlabel 'X'; set ylabel 'Y';"; /* prefix fed into gnuplot before the plot command */
#else
char plot_prefix[256] = "set grid; set xlabel \"X\"; set ylabel \"Y\";"; /* prefix fed into gnuplot before the plot command */
#endif
int factor_out_all_numeric_gcds = false; /* if true, factor out the GCD of rational coefficients */
int right_associative_power; /* if true, evaluate power operators right to left */
int power_starstar; /* if true, display power operator as "**", otherwise "^" */
#if !SILENT
int debug_level; /* current debug level */
#endif
/* library variables go here */
mathomatic->result_en = -1; /* equation number of the returned result, if stored in an equation space */
mathomatic->last_autocalc_en = -1;
mathomatic->constant_var_number = 1; /* makes unique numbers for the constant of integration */
/* variables having to do with color output mode */
#if LIBRARY || NO_COLOR
int color_flag = 0; /* library shouldn't default to color mode */
#else
int color_flag = 1; /* "set color" flag; 0 for no color, 1 for color, 2 for alternative color output mode */
#endif
#if BOLD_COLOR
int bold_colors = 1; /* "set bold color" flag for brighter colors */
#else
int bold_colors = 0; /* bold_colors must be 0 or 1; 0 is dim */
#endif
int text_color = -1; /* Current normal text color, -1 for no color */
int cur_color = -1; /* memory of current color on the terminal */
int html_flag; /* 1 for HTML mode on all standard output; 2 for HTML mode on all output, even redirected output */
return mathomatic;
}
/* double precision floating point epsilon constants for number comparisons for equivalency */
double small_epsilon = 0.000000000000005; /* for ignoring small, floating point round-off errors */
double epsilon = 0.00000000000005; /* for ignoring larger, accumulated round-off errors */
void closetMathoMatic(MathoMatic *mathomatic) {
free(mathomatic);
}
/* string variables */
char *prog_name = "mathomatic"; /* name of this program */
char *var_names[MAX_VAR_NAMES]; /* index for storage of variable name strings */
char var_str[MAX_VAR_LEN+80]; /* temp storage for listing a variable name */
char prompt_str[MAX_PROMPT_LEN]; /* temp storage for the prompt string */
#if !SECURE
char rc_file[MAX_CMD_LEN]; /* pathname for the set options startup file */
#endif
int matho_cur_equation(MathoMatic * mathomatic) {
return mathomatic->cur_equation;
}
#if CYGWIN || MINGW
char *dir_path; /* directory path to the executable */
#endif
#if READLINE || EDITLINE
char *last_history_string; /* To prevent repeated, identical entries. Must not point to temporary string. */
#endif
#if READLINE
char *history_filename;
char history_filename_storage[MAX_CMD_LEN];
#endif
int matho_result_en(MathoMatic * mathomatic) {
return mathomatic->result_en;
}
/* The following are for integer factoring (filled by factor_one()): */
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[] */
const char *matho_get_warning_str(MathoMatic * mathomatic) {
return mathomatic->warning_str;
}
/* misc. variables */
int previous_return_value = 1; /* Return value of last command entered. */
sign_array_type sign_array; /* for keeping track of unique "sign" variables */
FILE *default_out; /* file pointer where all gfp output goes by default */
FILE *gfp; /* global output file pointer, for dynamically redirecting Mathomatic output */
char *gfp_filename; /* filename associated with gfp if redirection is happening */
int gfp_append_flag; /* true if appending to gfp, false if overwriting */
jmp_buf jmp_save; /* for setjmp(3) to longjmp(3) to when an error happens deep within this code */
int eoption; /* -e option flag */
int test_mode; /* test mode flag (-t) */
int demo_mode; /* demo mode flag (-d), don't load rc file or pause commands when true */
int quiet_mode; /* quiet mode (-q, don't display prompts) */
int echo_input; /* if true, echo input */
int readline_enabled = true; /* set to false (-r) to disable readline */
int partial_flag; /* normally true for partial unfactoring, false for "unfactor fraction" */
int symb_flag; /* true during "simplify symbolic", which is not 100% mathematically correct */
int symblify = true; /* if true, set symb_flag when helpful during solving, etc. */
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_cmp_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 approximation of roots like (2^.5)) */
volatile int abort_flag; /* if true, abort current operation; set by control-C interrupt */
int pull_number; /* equation space number to pull when using the library */
int security_level; /* current enforced security level for session, -1 for m4 Mathomatic */
int repeat_flag; /* true if the command is to repeat its function or simplification, set by repeat command */
int show_usage; /* show command usage info if a command fails and this flag is true */
int point_flag; /* point to location of parse error if true */
void matho_set_warning_str(MathoMatic * mathomatic, const char *ws) {
mathomatic->warning_str = ws;
}
/* library variables go here */
char *result_str; /* returned result text string when using as library */
int result_en = -1; /* equation number of the returned result, if stored in an equation space */
const char *error_str; /* last error string */
const char *warning_str; /* last warning string */
void matho_set_error_str(MathoMatic * mathomatic, const char *ws) {
mathomatic->error_str = ws;
}
/* Screen character array, for buffering page-at-a-time 2D string output: */
char *vscreen[TEXT_ROWS];
int current_columns;
int matho_get_abort_flag(MathoMatic* mathomatic) {
return mathomatic->abort_flag;
}
void matho_inc_abort_flag(MathoMatic* mathomatic) {
++mathomatic->abort_flag;
}

861
help.c

File diff suppressed because it is too large Load Diff

View File

@ -113,7 +113,7 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#include "standard.h" /* a standard include file for any math program written in C */
#include "am.h" /* the main include file for Mathomatic, contains tunable parameters */
#include "complex.h" /* floating point complex number arithmetic function prototypes */
#include "externs.h" /* global variable extern definitions */
#include "proto.h" /* global function prototypes, made with cproto utility */
#include "altproto.h" /* backup global function prototypes, in case of no proto.h */
#include "externs.h" /* global variable extern definitions */
#include "blt.h" /* blt() function definition */

View File

@ -24,21 +24,21 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#include "includes.h"
static int integrate_sub(token_type *equation, int *np, int loc, int eloc, long v);
static int laplace_sub(token_type *equation, int *np, int loc, int eloc, long v);
static int inv_laplace_sub(token_type *equation, int *np, int loc, int eloc, long v);
static int integrate_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v);
static int laplace_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v);
static int inv_laplace_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v);
static int constant_var_number = 1; /* makes unique numbers for the constant of integration */
//static int constant_var_number = 1; /* makes unique numbers for the constant of integration */
/*
* Make variable "v" always raised to a power,
* unless it is on the right side of a power operator.
*/
void
make_powers(equation, np, v)
token_type *equation; /* pointer to beginning of equation side */
int *np; /* pointer to length of equation side */
long v; /* Mathomatic variable */
make_powers(MathoMatic* mathomatic, token_type *equation, int *np, long v)
//token_type *equation; /* pointer to beginning of equation side */
//int *np; /* pointer to length of equation side */
//long v; /* Mathomatic variable */
{
int i;
int level;
@ -52,8 +52,8 @@ long v; /* Mathomatic variable */
}
if (equation[i].kind == VARIABLE && equation[i].token.variable == v) {
if ((i + 1) >= *np || equation[i+1].token.operatr != POWER) {
if (*np + 2 > n_tokens) {
error_huge();
if (*np + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
level++;
equation[i].level = level;
@ -81,22 +81,22 @@ long v; /* Mathomatic variable */
* Return true if successful.
*/
int
int_dispatch(equation, np, v, func)
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)(token_type *equation, int *np, int loc, int eloc, long v); /* integration function to call for each term */
int_dispatch(MathoMatic* mathomatic, token_type *equation, int *np, long v, int (*func)(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v))
//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)(token_type *equation, int *np, int loc, int eloc, long v); /* integration function to call for each term */
{
int i, j;
make_powers(equation, np, v);
make_powers(mathomatic, equation, np, v);
for (j = 0, i = 1;; i += 2) {
if (i >= *np) {
return((*func)(equation, np, j, i, v));
return((*func)(mathomatic, equation, np, j, i, v));
}
if (equation[i].level == 1
&& (equation[i].token.operatr == PLUS || equation[i].token.operatr == MINUS)) {
if (!(*func)(equation, np, j, i, v)) {
if (!(*func)(mathomatic, equation, np, j, i, v)) {
return false;
}
for (i = j + 1;; i += 2) {
@ -119,12 +119,12 @@ int (*func)(token_type *equation, int *np, int loc, int eloc, long v); /* integ
* Return true if successful.
*/
static int
integrate_sub(equation, np, loc, eloc, v)
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 of integration */
integrate_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v)
//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 of integration */
{
int i, j, k;
int len;
@ -132,7 +132,7 @@ long v; /* variable of integration */
int count;
int div_flag;
level = min_level(&equation[loc], eloc - loc);
level = min_level(mathomatic, &equation[loc], eloc - loc);
/* determine if the term is a polynomial term in "v" */
for (i = loc, count = 0; i < eloc; i += 2) {
if (equation[i].kind == VARIABLE && equation[i].token.variable == v) {
@ -183,8 +183,8 @@ long v; /* variable of integration */
&& equation[i].kind == CONSTANT
&& equation[i].token.constant == 1.0)
return false;
if (*np + 2 > n_tokens)
error_huge();
if (*np + 2 > mathomatic->n_tokens)
error_huge(mathomatic);
for (j = i; j < eloc && equation[j].level >= level; j++)
equation[j].level++;
equation[i-3].token.operatr = TIMES;
@ -201,8 +201,8 @@ long v; /* variable of integration */
for (j = i; j < eloc && equation[j].level >= level; j++)
equation[j].level++;
len = j - i;
if (*np + len + 5 > n_tokens)
error_huge();
if (*np + len + 5 > mathomatic->n_tokens)
error_huge(mathomatic);
blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type));
*np += 2;
eloc += 2;
@ -224,8 +224,8 @@ long v; /* variable of integration */
return true;
}
}
if (*np + 2 > n_tokens) {
error_huge();
if (*np + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[eloc+2], &equation[eloc], (*np - eloc) * sizeof(token_type));
*np += 2;
@ -243,8 +243,7 @@ long v; /* variable of integration */
* The integrate command.
*/
int
integrate_cmd(cp)
char *cp;
integrate_cmd(MathoMatic* mathomatic, char *cp)
{
int i, j;
int len;
@ -257,13 +256,13 @@ char *cp;
long l1;
cp_start = cp;
if (current_not_defined()) {
if (current_not_defined(mathomatic)) {
return false;
}
n_tlhs = 0;
n_trhs = 0;
solved = solved_equation(cur_equation);
i = next_espace();
mathomatic->n_tlhs = 0;
mathomatic->n_trhs = 0;
solved = solved_equation(mathomatic, mathomatic->cur_equation);
i = next_espace(mathomatic);
for (;; cp = skip_param(cp)) {
if (strcmp_tospace(cp, "definite") == 0) {
definite_flag = true;
@ -276,27 +275,27 @@ char *cp;
break;
}
if (constant_flag && definite_flag) {
error(_("Conflicting options given."));
error(mathomatic, _("Conflicting options given."));
return false;
}
if (n_rhs[cur_equation]) {
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
if (!solved) {
warning(_("Not a solved equation."));
warning(mathomatic, _("Not a solved equation."));
}
debug_string(0, _("Only the RHS will be transformed."));
source = rhs[cur_equation];
nps = &n_rhs[cur_equation];
dest = rhs[i];
np = &n_rhs[i];
debug_string(mathomatic, 0, _("Only the RHS will be transformed."));
source = mathomatic->rhs[mathomatic->cur_equation];
nps = &mathomatic->n_rhs[mathomatic->cur_equation];
dest = mathomatic->rhs[i];
np = &mathomatic->n_rhs[i];
} else {
source = lhs[cur_equation];
nps = &n_lhs[cur_equation];
dest = lhs[i];
np = &n_lhs[i];
source = mathomatic->lhs[mathomatic->cur_equation];
nps = &mathomatic->n_lhs[mathomatic->cur_equation];
dest = mathomatic->lhs[i];
np = &mathomatic->n_lhs[i];
}
if (*cp) {
if (isvarchar(*cp)) {
cp = parse_var2(&v, cp);
if (isvarchar(mathomatic, *cp)) {
cp = parse_var2(mathomatic, &v, cp);
if (cp == NULL) {
return false;
}
@ -305,60 +304,60 @@ char *cp;
integrate_order = strtod(cp, &cp);
}
if (!isfinite(integrate_order) || integrate_order <= 0 || fmod(integrate_order, 1.0) != 0.0) {
error(_("The order must be a positive integer."));
error(mathomatic, _("The order must be a positive integer."));
return false;
}
}
if (*cp) {
cp = skip_comma_space(cp);
input_column += (cp - cp_start);
cp = parse_expr(tlhs, &n_tlhs, cp, false);
if (cp == NULL || n_tlhs <= 0) {
mathomatic->input_column += (cp - cp_start);
cp = parse_expr(mathomatic, mathomatic->tlhs, &mathomatic->n_tlhs, cp, false);
if (cp == NULL || mathomatic->n_tlhs <= 0) {
return false;
}
}
if (*cp) {
cp_start = cp;
cp = skip_comma_space(cp);
input_column += (cp - cp_start);
cp = parse_expr(trhs, &n_trhs, cp, false);
if (cp == NULL || extra_characters(cp) || n_trhs <= 0) {
mathomatic->input_column += (cp - cp_start);
cp = parse_expr(mathomatic, mathomatic->trhs, &mathomatic->n_trhs, cp, false);
if (cp == NULL || extra_characters(mathomatic, cp) || mathomatic->n_trhs <= 0) {
return false;
}
}
show_usage = false;
mathomatic->show_usage = false;
if (v == 0) {
if (!prompt_var(&v)) {
if (!prompt_var(mathomatic, &v)) {
return false;
}
}
#if !SILENT
list_var(v, 0);
if (n_rhs[cur_equation]) {
fprintf(gfp, _("Integrating the RHS with respect to %s"), var_str);
list_var(mathomatic, v, 0);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
fprintf(mathomatic->gfp, _("Integrating the RHS with respect to %s"), mathomatic->var_str);
} else {
fprintf(gfp, _("Integrating with respect to %s"), var_str);
fprintf(mathomatic->gfp, _("Integrating with respect to %s"), mathomatic->var_str);
}
if (integrate_order != 1.0) {
fprintf(gfp, _(" %.*g times"), precision, integrate_order);
fprintf(mathomatic->gfp, _(" %.*g times"), mathomatic->precision, integrate_order);
}
fprintf(gfp, _(" and simplifying...\n"));
fprintf(mathomatic->gfp, _(" and simplifying...\n"));
#endif
partial_flag = false;
uf_simp(source, nps);
partial_flag = true;
factorv(source, nps, v);
mathomatic->partial_flag = false;
uf_simp(mathomatic, source, nps);
mathomatic->partial_flag = true;
factorv(mathomatic, source, nps, v);
blt(dest, source, *nps * sizeof(token_type));
n1 = *nps;
for (l1 = 0; l1 < integrate_order; l1++) {
if (!int_dispatch(dest, &n1, v, integrate_sub)) {
error(_("Integration failed, not a polynomial."));
if (!int_dispatch(mathomatic, dest, &n1, v, integrate_sub)) {
error(mathomatic, _("Integration failed, not a polynomial."));
return false;
}
if (constant_flag) {
if (n1 + 2 > n_tokens) {
error_huge();
if (n1 + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
for (j = 0; j < n1; j++) {
dest[j].level++;
@ -369,66 +368,66 @@ char *cp;
n1++;
dest[n1].kind = VARIABLE;
dest[n1].level = 1;
snprintf(var_name_buf, sizeof(var_name_buf), "C_%d", constant_var_number);
if (parse_var(&dest[n1].token.variable, var_name_buf) == NULL) {
snprintf(var_name_buf, sizeof(var_name_buf), "C_%d", mathomatic->constant_var_number);
if (parse_var(mathomatic, &dest[n1].token.variable, var_name_buf) == NULL) {
return false;
}
n1++;
constant_var_number++;
if (constant_var_number < 0) {
constant_var_number = 1;
mathomatic->constant_var_number++;
if (mathomatic->constant_var_number < 0) {
mathomatic->constant_var_number = 1;
}
}
simp_loop(dest, &n1);
simp_loop(mathomatic, dest, &n1);
}
if (definite_flag) {
if (n_tlhs == 0) {
my_strlcpy(prompt_str, _("Enter lower bound: "), sizeof(prompt_str));
if (!get_expr(tlhs, &n_tlhs)) {
if (mathomatic->n_tlhs == 0) {
my_strlcpy(mathomatic->prompt_str, _("Enter lower bound: "), sizeof(mathomatic->prompt_str));
if (!get_expr(mathomatic, mathomatic->tlhs, &mathomatic->n_tlhs)) {
return false;
}
}
if (n_trhs == 0) {
my_strlcpy(prompt_str, _("Enter upper bound: "), sizeof(prompt_str));
if (!get_expr(trhs, &n_trhs)) {
if (mathomatic->n_trhs == 0) {
my_strlcpy(mathomatic->prompt_str, _("Enter upper bound: "), sizeof(mathomatic->prompt_str));
if (!get_expr(mathomatic, mathomatic->trhs, &mathomatic->n_trhs)) {
return false;
}
}
blt(scratch, dest, n1 * sizeof(token_type));
blt(mathomatic->scratch, dest, n1 * sizeof(token_type));
n2 = n1;
subst_var_with_exp(scratch, &n2, tlhs, n_tlhs, v);
subst_var_with_exp(dest, &n1, trhs, n_trhs, v);
if (n1 + 1 + n2 > n_tokens) {
error_huge();
subst_var_with_exp(mathomatic, mathomatic->scratch, &n2, mathomatic->tlhs, mathomatic->n_tlhs, v);
subst_var_with_exp(mathomatic, dest, &n1, mathomatic->trhs, mathomatic->n_trhs, v);
if (n1 + 1 + n2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
for (j = 0; j < n1; j++) {
dest[j].level++;
}
for (j = 0; j < n2; j++) {
scratch[j].level++;
mathomatic->scratch[j].level++;
}
dest[n1].kind = OPERATOR;
dest[n1].level = 1;
dest[n1].token.operatr = MINUS;
n1++;
blt(&dest[n1], scratch, n2 * sizeof(token_type));
blt(&dest[n1], mathomatic->scratch, n2 * sizeof(token_type));
n1 += n2;
}
simpa_side(dest, &n1, false, false);
simpa_side(mathomatic, dest, &n1, false, false);
*np = n1;
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];
if (solved && isvarchar('\'')) {
len = list_var(lhs[i][0].token.variable, 0);
for (l1 = 0; l1 < integrate_order && len > 0 && var_str[len-1] == '\''; l1++) {
var_str[--len] = '\0';
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
blt(mathomatic->lhs[i], mathomatic->lhs[mathomatic->cur_equation], mathomatic->n_lhs[mathomatic->cur_equation] * sizeof(token_type));
mathomatic->n_lhs[i] = mathomatic->n_lhs[mathomatic->cur_equation];
if (solved && isvarchar(mathomatic, '\'')) {
len = list_var(mathomatic, mathomatic->lhs[i][0].token.variable, 0);
for (l1 = 0; l1 < integrate_order && len > 0 && mathomatic->var_str[len-1] == '\''; l1++) {
mathomatic->var_str[--len] = '\0';
}
parse_var(&lhs[i][0].token.variable, var_str);
parse_var(mathomatic, &mathomatic->lhs[i][0].token.variable, mathomatic->var_str);
}
}
cur_equation = i;
return return_result(cur_equation);
mathomatic->cur_equation = i;
return return_result(mathomatic, mathomatic->cur_equation);
}
/*
@ -437,17 +436,13 @@ char *cp;
* Return true if successful.
*/
static int
laplace_sub(equation, np, loc, eloc, v)
token_type *equation;
int *np;
int loc, eloc;
long v;
laplace_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v)
{
int i, j, k;
int len;
int level, mlevel;
mlevel = min_level(&equation[loc], eloc - loc) + 1;
mlevel = min_level(mathomatic, &equation[loc], eloc - loc) + 1;
for (j = loc; j < eloc; j++)
equation[j].level += 2;
for (i = loc; i < eloc; i += 2) {
@ -460,8 +455,8 @@ long v;
for (j = i; j < eloc && equation[j].level >= level; j++)
equation[j].level++;
len = j - i;
if (*np + len + 7 > n_tokens)
error_huge();
if (*np + len + 7 > mathomatic->n_tokens)
error_huge(mathomatic);
blt(&equation[j+4], &equation[j], (*np - j) * sizeof(token_type));
*np += 4;
eloc += 4;
@ -502,8 +497,8 @@ long v;
return true;
}
}
if (*np + 2 > n_tokens) {
error_huge();
if (*np + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[eloc+2], &equation[eloc], (*np - eloc) * sizeof(token_type));
*np += 2;
@ -523,17 +518,13 @@ long v;
* Return true if successful.
*/
static int
inv_laplace_sub(equation, np, loc, eloc, v)
token_type *equation;
int *np;
int loc, eloc;
long v;
inv_laplace_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v)
{
int i, j, k;
int len;
int level, mlevel;
mlevel = min_level(&equation[loc], eloc - loc) + 1;
mlevel = min_level(mathomatic, &equation[loc], eloc - loc) + 1;
for (j = loc; j < eloc; j++)
equation[j].level += 2;
for (i = loc; i < eloc; i += 2) {
@ -548,8 +539,8 @@ long v;
for (j = i; j < eloc && equation[j].level >= level; j++)
equation[j].level++;
len = j - i;
if (*np + len + 7 > n_tokens)
error_huge();
if (*np + len + 7 > mathomatic->n_tokens)
error_huge(mathomatic);
equation[i-3].token.operatr = TIMES;
blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type));
*np += 2;
@ -589,8 +580,7 @@ long v;
* The laplace command.
*/
int
laplace_cmd(cp)
char *cp;
laplace_cmd(MathoMatic* mathomatic, char *cp)
{
int i;
long v = 0;
@ -598,84 +588,83 @@ char *cp;
token_type *source, *dest;
int n1, *nps, *np;
if (current_not_defined()) {
if (current_not_defined(mathomatic)) {
return false;
}
solved = solved_equation(cur_equation);
i = next_espace();
if (n_rhs[cur_equation]) {
solved = solved_equation(mathomatic, mathomatic->cur_equation);
i = next_espace(mathomatic);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
if (!solved) {
warning(_("Not a solved equation."));
warning(mathomatic, _("Not a solved equation."));
}
#if !SILENT
fprintf(gfp, _("Only the RHS will be transformed.\n"));
fprintf(mathomatic->gfp, _("Only the RHS will be transformed.\n"));
#endif
source = rhs[cur_equation];
nps = &n_rhs[cur_equation];
dest = rhs[i];
np = &n_rhs[i];
source = mathomatic->rhs[mathomatic->cur_equation];
nps = &mathomatic->n_rhs[mathomatic->cur_equation];
dest = mathomatic->rhs[i];
np = &mathomatic->n_rhs[i];
} else {
source = lhs[cur_equation];
nps = &n_lhs[cur_equation];
dest = lhs[i];
np = &n_lhs[i];
source = mathomatic->lhs[mathomatic->cur_equation];
nps = &mathomatic->n_lhs[mathomatic->cur_equation];
dest = mathomatic->lhs[i];
np = &mathomatic->n_lhs[i];
}
inverse_flag = (strcmp_tospace(cp, "inverse") == 0);
if (inverse_flag) {
cp = skip_param(cp);
}
if (*cp) {
cp = parse_var2(&v, cp);
cp = parse_var2(mathomatic, &v, cp);
if (cp == NULL) {
return false;
}
if (extra_characters(cp)) {
if (extra_characters(mathomatic, cp)) {
return false;
}
}
show_usage = false;
mathomatic->show_usage = false;
if (v == 0) {
if (!prompt_var(&v)) {
if (!prompt_var(mathomatic, &v)) {
return false;
}
}
partial_flag = false;
uf_simp(source, nps);
partial_flag = true;
factorv(source, nps, v);
mathomatic->partial_flag = false;
uf_simp(mathomatic, source, nps);
mathomatic->partial_flag = true;
factorv(mathomatic, source, nps, v);
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)) {
error(_("Inverse Laplace transformation failed."));
if (!poly_in_v(mathomatic, dest, n1, v, true) || !int_dispatch(mathomatic, dest, &n1, v, inv_laplace_sub)) {
error(mathomatic, _("Inverse Laplace transformation failed."));
return false;
}
} else {
if (!poly_in_v(dest, n1, v, false) || !int_dispatch(dest, &n1, v, laplace_sub)) {
error(_("Laplace transformation failed, not a polynomial."));
if (!poly_in_v(mathomatic, dest, n1, v, false) || !int_dispatch(mathomatic, dest, &n1, v, laplace_sub)) {
error(mathomatic, _("Laplace transformation failed, not a polynomial."));
return false;
}
}
#if 1
simp_loop(dest, &n1);
simp_loop(mathomatic, dest, &n1);
#else
simpa_side(dest, &n1, false, false);
simpa_side(mathomatic, dest, &n1, false, false);
#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];
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
blt(mathomatic->lhs[i], mathomatic->lhs[mathomatic->cur_equation], mathomatic->n_lhs[mathomatic->cur_equation] * sizeof(token_type));
mathomatic->n_lhs[i] = mathomatic->n_lhs[mathomatic->cur_equation];
}
*np = n1;
cur_equation = i;
return return_result(cur_equation);
mathomatic->cur_equation = i;
return return_result(mathomatic, mathomatic->cur_equation);
}
/*
* Numerical integrate command.
*/
int
nintegrate_cmd(cp)
char *cp;
nintegrate_cmd(MathoMatic* mathomatic, char *cp)
{
long v = 0; /* Mathomatic variable */
int i, j, k, i1, i2;
@ -689,33 +678,33 @@ char *cp;
char *cp_start;
cp_start = cp;
if (current_not_defined()) {
if (current_not_defined(mathomatic)) {
return false;
}
n_tlhs = 0;
n_trhs = 0;
solved = solved_equation(cur_equation);
i = next_espace();
if (n_rhs[cur_equation]) {
mathomatic->n_tlhs = 0;
mathomatic->n_trhs = 0;
solved = solved_equation(mathomatic, mathomatic->cur_equation);
i = next_espace(mathomatic);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
if (!solved) {
warning(_("Not a solved equation."));
warning(mathomatic, _("Not a solved equation."));
}
source = rhs[cur_equation];
nps = &n_rhs[cur_equation];
dest = rhs[i];
np = &n_rhs[i];
source = mathomatic->rhs[mathomatic->cur_equation];
nps = &mathomatic->n_rhs[mathomatic->cur_equation];
dest = mathomatic->rhs[i];
np = &mathomatic->n_rhs[i];
} else {
source = lhs[cur_equation];
nps = &n_lhs[cur_equation];
dest = lhs[i];
np = &n_lhs[i];
source = mathomatic->lhs[mathomatic->cur_equation];
nps = &mathomatic->n_lhs[mathomatic->cur_equation];
dest = mathomatic->lhs[i];
np = &mathomatic->n_lhs[i];
}
trap_flag = (strncasecmp(cp, "trap", 4) == 0);
if (trap_flag) {
cp = skip_param(cp);
}
if (*cp) {
cp = parse_var2(&v, cp);
cp = parse_var2(mathomatic, &v, cp);
if (cp == NULL) {
return false;
}
@ -723,38 +712,38 @@ char *cp;
iterations = decstrtol(cp, &cp);
}
if (iterations <= 0 || (iterations % 2) != 0) {
error(_("Number of partitions must be a positive, even integer."));
error(mathomatic, _("Number of partitions must be a positive, even integer."));
return false;
}
}
if (*cp) {
input_column += (cp - cp_start);
cp = parse_expr(tlhs, &n_tlhs, cp, false);
if (cp == NULL || n_tlhs <= 0) {
mathomatic->input_column += (cp - cp_start);
cp = parse_expr(mathomatic, mathomatic->tlhs, &mathomatic->n_tlhs, cp, false);
if (cp == NULL || mathomatic->n_tlhs <= 0) {
return false;
}
}
if (*cp) {
cp_start = cp;
cp = skip_comma_space(cp);
input_column += (cp - cp_start);
cp = parse_expr(trhs, &n_trhs, cp, false);
if (cp == NULL || extra_characters(cp) || n_trhs <= 0) {
mathomatic->input_column += (cp - cp_start);
cp = parse_expr(mathomatic, mathomatic->trhs, &mathomatic->n_trhs, cp, false);
if (cp == NULL || extra_characters(mathomatic, cp) || mathomatic->n_trhs <= 0) {
return false;
}
}
show_usage = false;
mathomatic->show_usage = false;
if (v == 0) {
if (!prompt_var(&v)) {
if (!prompt_var(mathomatic, &v)) {
return false;
}
}
#if !SILENT
list_var(v, 0);
if (n_rhs[cur_equation]) {
fprintf(gfp, _("Numerically integrating the RHS with respect to %s...\n"), var_str);
list_var(mathomatic, v, 0);
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
fprintf(mathomatic->gfp, _("Numerically integrating the RHS with respect to %s...\n"), mathomatic->var_str);
} else {
fprintf(gfp, _("Numerically integrating with respect to %s...\n"), var_str);
fprintf(mathomatic->gfp, _("Numerically integrating with respect to %s...\n"), mathomatic->var_str);
}
#endif
singularity = false;
@ -770,72 +759,72 @@ char *cp;
}
}
if (singularity) {
warning(_("Singularity detected, result of numerical integration might be wrong."));
warning(mathomatic, _("Singularity detected, result of numerical integration might be wrong."));
}
if (n_tlhs == 0) {
my_strlcpy(prompt_str, _("Enter lower bound: "), sizeof(prompt_str));
if (!get_expr(tlhs, &n_tlhs)) {
if (mathomatic->n_tlhs == 0) {
my_strlcpy(mathomatic->prompt_str, _("Enter lower bound: "), sizeof(mathomatic->prompt_str));
if (!get_expr(mathomatic, mathomatic->tlhs, &mathomatic->n_tlhs)) {
return false;
}
}
subst_constants(tlhs, &n_tlhs);
simp_loop(tlhs, &n_tlhs);
if (exp_contains_infinity(tlhs, n_tlhs)) {
error(_("Not computable because: Lower bound contains infinity or NaN."));
subst_constants(mathomatic->tlhs, &mathomatic->n_tlhs);
simp_loop(mathomatic, mathomatic->tlhs, &mathomatic->n_tlhs);
if (exp_contains_infinity(mathomatic->tlhs, mathomatic->n_tlhs)) {
error(mathomatic, _("Not computable because: Lower bound contains infinity or NaN."));
return false;
}
if (n_trhs == 0) {
my_strlcpy(prompt_str, _("Enter upper bound: "), sizeof(prompt_str));
if (!get_expr(trhs, &n_trhs)) {
if (mathomatic->n_trhs == 0) {
my_strlcpy(mathomatic->prompt_str, _("Enter upper bound: "), sizeof(mathomatic->prompt_str));
if (!get_expr(mathomatic, mathomatic->trhs, &mathomatic->n_trhs)) {
return false;
}
}
subst_constants(trhs, &n_trhs);
simp_loop(trhs, &n_trhs);
if (exp_contains_infinity(trhs, n_trhs)) {
error(_("Not computable because: Upper bound contains infinity or NaN."));
subst_constants(mathomatic->trhs, &mathomatic->n_trhs);
simp_loop(mathomatic, mathomatic->trhs, &mathomatic->n_trhs);
if (exp_contains_infinity(mathomatic->trhs, mathomatic->n_trhs)) {
error(mathomatic, _("Not computable because: Upper bound contains infinity or NaN."));
return false;
}
if ((n_tlhs + n_trhs + 3) > n_tokens) {
error_huge();
if ((mathomatic->n_tlhs + mathomatic->n_trhs + 3) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
#if !SILENT
fprintf(gfp, _("Approximating the definite integral\n"));
fprintf(mathomatic->gfp, _("Approximating the definite integral\n"));
if (trap_flag) {
fprintf(gfp, _("using the trapezoid method (%d partitions)...\n"), iterations);
fprintf(mathomatic->gfp, _("using the trapezoid method (%d partitions)...\n"), iterations);
} else {
fprintf(gfp, _("using Simpson's rule (%d partitions)...\n"), iterations);
fprintf(mathomatic->gfp, _("using Simpson's rule (%d partitions)...\n"), iterations);
}
#endif
subst_constants(source, nps);
simp_loop(source, nps);
for (j = 0; j < n_trhs; j++) {
trhs[j].level += 2;
simp_loop(mathomatic, source, nps);
for (j = 0; j < mathomatic->n_trhs; j++) {
mathomatic->trhs[j].level += 2;
}
trhs[n_trhs].level = 2;
trhs[n_trhs].kind = OPERATOR;
trhs[n_trhs].token.operatr = MINUS;
n_trhs++;
j = n_trhs;
blt(&trhs[n_trhs], tlhs, n_tlhs * sizeof(token_type));
n_trhs += n_tlhs;
for (; j < n_trhs; j++) {
trhs[j].level += 2;
mathomatic->trhs[mathomatic->n_trhs].level = 2;
mathomatic->trhs[mathomatic->n_trhs].kind = OPERATOR;
mathomatic->trhs[mathomatic->n_trhs].token.operatr = MINUS;
mathomatic->n_trhs++;
j = mathomatic->n_trhs;
blt(&mathomatic->trhs[mathomatic->n_trhs], mathomatic->tlhs, mathomatic->n_tlhs * sizeof(token_type));
mathomatic->n_trhs += mathomatic->n_tlhs;
for (; j < mathomatic->n_trhs; j++) {
mathomatic->trhs[j].level += 2;
}
trhs[n_trhs].level = 1;
trhs[n_trhs].kind = OPERATOR;
trhs[n_trhs].token.operatr = DIVIDE;
n_trhs++;
trhs[n_trhs].level = 1;
trhs[n_trhs].kind = CONSTANT;
trhs[n_trhs].token.constant = iterations;
n_trhs++;
simp_loop(trhs, &n_trhs);
dest[0] = zero_token;
mathomatic->trhs[mathomatic->n_trhs].level = 1;
mathomatic->trhs[mathomatic->n_trhs].kind = OPERATOR;
mathomatic->trhs[mathomatic->n_trhs].token.operatr = DIVIDE;
mathomatic->n_trhs++;
mathomatic->trhs[mathomatic->n_trhs].level = 1;
mathomatic->trhs[mathomatic->n_trhs].kind = CONSTANT;
mathomatic->trhs[mathomatic->n_trhs].token.constant = iterations;
mathomatic->n_trhs++;
simp_loop(mathomatic, mathomatic->trhs, &mathomatic->n_trhs);
dest[0] = mathomatic->zero_token;
n1 = 1;
for (j = 0; j <= iterations; j++) {
if ((n1 + 1 + *nps) > n_tokens)
error_huge();
if ((n1 + 1 + *nps) > mathomatic->n_tokens)
error_huge(mathomatic);
for (k = 0; k < n1; k++) {
dest[k].level++;
}
@ -853,14 +842,14 @@ char *cp;
for (k = i1; k < n1; k += 2) {
if (dest[k].kind == VARIABLE && dest[k].token.variable == v) {
level = dest[k].level;
i2 = n_tlhs + 2 + n_trhs;
if ((n1 + i2) > n_tokens)
error_huge();
i2 = mathomatic->n_tlhs + 2 + mathomatic->n_trhs;
if ((n1 + i2) > mathomatic->n_tokens)
error_huge(mathomatic);
blt(&dest[k+1+i2], &dest[k+1], (n1 - (k + 1)) * sizeof(token_type));
n1 += i2;
i2 = k;
blt(&dest[k], tlhs, n_tlhs * sizeof(token_type));
k += n_tlhs;
blt(&dest[k], mathomatic->tlhs, mathomatic->n_tlhs * sizeof(token_type));
k += mathomatic->n_tlhs;
level++;
for (; i2 < k; i2++) {
dest[i2].level += level;
@ -880,8 +869,8 @@ char *cp;
ep->token.operatr = TIMES;
k += 3;
i2 = k;
blt(&dest[k], trhs, n_trhs * sizeof(token_type));
k += n_trhs;
blt(&dest[k], mathomatic->trhs, mathomatic->n_trhs * sizeof(token_type));
k += mathomatic->n_trhs;
for (; i2 < k; i2++) {
dest[i2].level += level;
}
@ -889,8 +878,8 @@ char *cp;
}
}
if (j > 0 && j < iterations) {
if ((n1 + 2) > n_tokens)
error_huge();
if ((n1 + 2) > mathomatic->n_tokens)
error_huge(mathomatic);
ep = &dest[n1];
ep->level = 2;
ep->kind = OPERATOR;
@ -911,16 +900,16 @@ char *cp;
}
/* simplify and approximate the partial result quickly: */
approximate_roots = true;
elim_loop(dest, &n1);
ufactor(dest, &n1);
simp_divide(dest, &n1);
factor_imaginary(dest, &n1);
approximate_roots = false;
side_debug(1, dest, n1);
mathomatic->approximate_roots = true;
elim_loop(mathomatic, dest, &n1);
ufactor(mathomatic, dest, &n1);
simp_divide(mathomatic, dest, &n1);
factor_imaginary(mathomatic, dest, &n1);
mathomatic->approximate_roots = false;
side_debug(mathomatic, 1, dest, n1);
if (exp_contains_infinity(dest, n1)) {
error(_("Integration failed because result contains infinity or NaN (a singularity)."));
error(mathomatic, _("Integration failed because result contains infinity or NaN (a singularity)."));
return false;
}
/* detect an ever growing result: */
@ -934,14 +923,14 @@ char *cp;
break;
default:
if ((n1 / 8) >= first_size) {
error(_("Result growing, integration failed."));
error(mathomatic, _("Result growing, integration failed."));
return false;
}
break;
}
}
if ((n1 + 3 + n_trhs) > n_tokens)
error_huge();
if ((n1 + 3 + mathomatic->n_trhs) > mathomatic->n_tokens)
error_huge(mathomatic);
for (k = 0; k < n1; k++)
dest[k].level++;
ep = &dest[n1];
@ -962,34 +951,34 @@ char *cp;
ep->token.operatr = TIMES;
n1 += 3;
k = n1;
blt(&dest[k], trhs, n_trhs * sizeof(token_type));
n1 += n_trhs;
blt(&dest[k], mathomatic->trhs, mathomatic->n_trhs * sizeof(token_type));
n1 += mathomatic->n_trhs;
for (; k < n1; k++)
dest[k].level++;
/* simplify and approximate the result even more: */
approximate_roots = true;
mathomatic->approximate_roots = true;
do {
elim_loop(dest, &n1);
ufactor(dest, &n1);
simp_divide(dest, &n1);
} while (factor_imaginary(dest, &n1));
approximate_roots = false;
elim_loop(mathomatic, dest, &n1);
ufactor(mathomatic, dest, &n1);
simp_divide(mathomatic, dest, &n1);
} while (factor_imaginary(mathomatic, dest, &n1));
mathomatic->approximate_roots = false;
#if !SILENT
fprintf(gfp, _("Numerical integration successful:\n"));
fprintf(mathomatic->gfp, _("Numerical integration successful:\n"));
#endif
*np = n1;
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];
if (solved && isvarchar('\'')) {
len = list_var(lhs[i][0].token.variable, 0);
if (len > 0 && var_str[len-1] == '\'') {
var_str[--len] = '\0';
if (mathomatic->n_rhs[mathomatic->cur_equation]) {
blt(mathomatic->lhs[i], mathomatic->lhs[mathomatic->cur_equation], mathomatic->n_lhs[mathomatic->cur_equation] * sizeof(token_type));
mathomatic->n_lhs[i] = mathomatic->n_lhs[mathomatic->cur_equation];
if (solved && isvarchar(mathomatic, '\'')) {
len = list_var(mathomatic, mathomatic->lhs[i][0].token.variable, 0);
if (len > 0 && mathomatic->var_str[len-1] == '\'') {
mathomatic->var_str[--len] = '\0';
}
parse_var(&lhs[i][0].token.variable, var_str);
parse_var(mathomatic, &mathomatic->lhs[i][0].token.variable, mathomatic->var_str);
}
}
return return_result(i);
return return_result(mathomatic, i);
}

View File

@ -10,23 +10,26 @@
int
main()
{
MathoMatic *mathomatic;
mathomatic = newtMathoMatic();
#if WANT_LEAKS /* Causes memory leaks, wrong code to use, but will work in a pinch. */
char *output;
matho_init();
matho_parse("x^2=4", NULL);
matho_process("solve x", &output);
matho_init(mathomatic);
matho_parse(mathomatic, "x^2=4", NULL);
matho_process(mathomatic, "solve x", &output);
printf("%s\n", output);
#else /* right code to use */
char *output;
int rv;
if (!matho_init()) {
if (!matho_init(mathomatic)) {
printf("Not enough memory.\n");
exit(1);
}
matho_parse((char *) "x^2=4", NULL);
rv = matho_process((char *) "solve x", &output);
matho_parse(mathomatic, (char *) "x^2=4", NULL);
rv = matho_process(mathomatic, (char *) "solve x", &output);
if (output) {
printf("%s\n", output);
if (rv) {
@ -37,5 +40,6 @@ main()
}
#endif
closetMathoMatic(mathomatic);
exit(0);
}

100
lib/lib.c
View File

@ -25,12 +25,12 @@
* and Mathomatic cannot be used.
*/
int
matho_init(void)
matho_init(MathoMatic* mathomatic)
{
init_gvars();
default_out = stdout; /* if default_out is a file that is not stdout, output is logged to that file */
gfp = default_out;
if (!init_mem()) {
init_gvars(mathomatic);
mathomatic->default_out = stdout; /* if default_out is a file that is not stdout, output is logged to that file */
mathomatic->gfp = mathomatic->default_out;
if (!init_mem(mathomatic)) {
return false;
}
signal(SIGFPE, fphandler); /* handle floating point exceptions, currently ignored */
@ -47,9 +47,9 @@ matho_init(void)
* to initialize the Mathomatic symbolic math engine.
*/
void
matho_clear(void)
matho_clear(MathoMatic* mathomatic)
{
clear_all();
clear_all(mathomatic);
}
/** 3
@ -85,57 +85,57 @@ matho_clear(void)
* this function with "outputp" set to NULL.
*/
int
matho_process(char *input, char **outputp)
matho_process(MathoMatic* mathomatic, char *input, char **outputp)
{
int i;
int rv;
if (outputp)
*outputp = NULL;
result_str = NULL;
result_en = -1;
error_str = NULL;
warning_str = NULL;
mathomatic->result_str = NULL;
mathomatic->result_en = -1;
mathomatic->error_str = NULL;
mathomatic->warning_str = NULL;
if (input == NULL)
return false;
input = strdup(input);
if ((i = setjmp(jmp_save)) != 0) {
clean_up(); /* Mathomatic processing was interrupted, so do a clean up. */
if ((i = setjmp(mathomatic->jmp_save)) != 0) {
clean_up(mathomatic); /* Mathomatic processing was interrupted, so do a clean up. */
if (i == 14) {
error(_("Expression too large."));
error(mathomatic, _("Expression too large."));
}
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
if (mathomatic->error_str) {
*outputp = (char *) mathomatic->error_str;
} else {
*outputp = _("Processing was interrupted.");
}
}
free_result_str();
free_result_str(mathomatic);
free(input);
previous_return_value = 0;
mathomatic->previous_return_value = 0;
return false;
}
set_error_level(input);
rv = process(input);
set_error_level(mathomatic, input);
rv = process(mathomatic, input);
if (rv) {
if (outputp) {
*outputp = result_str;
*outputp = mathomatic->result_str;
} else {
if (result_str) {
free(result_str);
result_str = NULL;
if (mathomatic->result_str) {
free(mathomatic->result_str);
mathomatic->result_str = NULL;
}
}
} else {
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
if (mathomatic->error_str) {
*outputp = (char *) mathomatic->error_str;
} else {
*outputp = _("Unknown error.");
}
}
free_result_str();
free_result_str(mathomatic);
}
free(input);
return rv;
@ -167,61 +167,61 @@ matho_process(char *input, char **outputp)
* Returns true (non-zero) if successful.
*/
int
matho_parse(char *input, char **outputp)
matho_parse(MathoMatic* mathomatic, char *input, char **outputp)
{
int i;
int rv;
if (outputp)
*outputp = NULL;
result_str = NULL;
result_en = -1;
error_str = NULL;
warning_str = NULL;
mathomatic->result_str = NULL;
mathomatic->result_en = -1;
mathomatic->error_str = NULL;
mathomatic->warning_str = NULL;
if (input == NULL)
return false;
input = strdup(input);
if ((i = setjmp(jmp_save)) != 0) {
clean_up(); /* Mathomatic processing was interrupted, so do a clean up. */
if ((i = setjmp(mathomatic->jmp_save)) != 0) {
clean_up(mathomatic); /* Mathomatic processing was interrupted, so do a clean up. */
if (i == 14) {
error(_("Expression too large."));
error(mathomatic, _("Expression too large."));
}
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
if (mathomatic->error_str) {
*outputp = (char *) mathomatic->error_str;
} else {
*outputp = _("Processing was interrupted.");
}
}
free_result_str();
free_result_str(mathomatic);
free(input);
return false;
}
set_error_level(input);
i = next_espace();
set_error_level(mathomatic, input);
i = next_espace(mathomatic);
#if 1 /* Leave this as 1 if you want to be able to enter single variable or constant expressions with no solving or selecting. */
rv = parse(i, input); /* All set auto options ignored. */
rv = parse(mathomatic, i, input); /* All set auto options ignored. */
#else
rv = process_parse(i, input); /* All set auto options respected. */
rv = process_parse(mathomatic, i, input); /* All set auto options respected. */
#endif
if (rv) {
if (outputp) {
*outputp = result_str;
*outputp = mathomatic->result_str;
} else {
if (result_str) {
free(result_str);
result_str = NULL;
if (mathomatic->result_str) {
free(mathomatic->result_str);
mathomatic->result_str = NULL;
}
}
} else {
if (outputp) {
if (error_str) {
*outputp = (char *) error_str;
if (mathomatic->error_str) {
*outputp = (char *) mathomatic->error_str;
} else {
*outputp = _("Unknown error.");
}
}
free_result_str();
free_result_str(mathomatic);
}
free(input);
return rv;

View File

@ -1,25 +1,34 @@
/*
* Include file for user programs using the Mathomatic symbolic math library API.
*/
#ifndef MATHO_EXTERNS_H
typedef struct MathoMatic MathoMatic;
#endif
extern int matho_init(void); /* one-time Mathomatic initialization */
extern int matho_process(char *input, char **outputp); /* Mathomatic command or expression input */
extern int matho_parse(char *input, char **outputp); /* Mathomatic expression or equation input */
extern void matho_clear(void); /* Restart Mathomatic quickly and cleanly, replaces clear_all(). */
extern MathoMatic *newtMathoMatic(void);
extern void closetMathoMatic(MathoMatic *mathomatic);
extern int matho_init(MathoMatic* mathomatic); /* one-time Mathomatic initialization */
extern int matho_process(MathoMatic* mathomatic, char *input, char **outputp); /* Mathomatic command or expression input */
extern int matho_parse(MathoMatic* mathomatic, char *input, char **outputp); /* Mathomatic expression or equation input */
extern void matho_clear(MathoMatic* mathomatic); /* Restart Mathomatic quickly and cleanly, replaces clear_all(). */
extern void free_mem(void); /* Free all allocated memory before quitting Mathomatic, if operating system doesn't when done. */
/* Mathomatic becomes unusable after free_mem(), until matho_init() is called again. */
/* Only Symbian OS is known to need a call to free_mem() before quitting. */
extern int load_rc(int return_true_if_no_file, FILE *ofp); /* Load Mathomatic startup set options from ~/.mathomaticrc, should allow "set save" to work. */
extern int load_rc(MathoMatic* mathomatic, int return_true_if_no_file, FILE *ofp); /* Load Mathomatic startup set options from ~/.mathomaticrc, should allow "set save" to work. */
extern int cur_equation; /* current equation space number (origin 0) */
extern int matho_cur_equation(MathoMatic * mathomatic); /* current equation space number (origin 0) */
extern int result_en; /* Equation number of the API's returned result, */
extern int matho_result_en(MathoMatic * mathomatic); /* Equation number of the API's returned result, */
/* if the result is also stored in an equation space, */
/* otherwise -1 for no equation number associated with result. */
/* Set by the last call to matho_parse() or matho_process(). */
/* Useful if you want to know where the result string is from, */
/* to act on it with further commands. */
extern const char *warning_str; /* optional warning message generated by the last command */
extern const char *matho_get_warning_str(MathoMatic * mathomatic); /* optional warning message generated by the last command */
extern void matho_set_warning_str(MathoMatic * mathomatic, const char *ws);
extern void matho_set_error_str(MathoMatic * mathomatic, const char *ws);
extern int matho_get_abort_flag(MathoMatic* mathomatic);
extern void matho_inc_abort_flag(MathoMatic* mathomatic);

View File

@ -17,15 +17,17 @@ main(int argc, char **argv)
int rv; /* return value */
char buf[10000]; /* input buffer */
char *version; /* version number of the library */
MathoMatic *mathomatic;
mathomatic = newtMathoMatic();
printf("Mathomatic library test/example program.\n");
/* Initialize all global variables and arrays so that Mathomatic will work properly. */
if (!matho_init()) { /* call this library function exactly once in your program */
if (!matho_init(mathomatic)) { /* call this library function exactly once in your program */
fprintf(stderr, "Not enough memory.\n");
exit(1);
}
/* Mathomatic is ready for use. */
if (matho_process((char *) "version", &version)) {
if (matho_process(mathomatic, (char *) "version", &version)) {
printf("Mathomatic library version %s\n", version);
} else {
fprintf(stderr, "Error getting Symbolic Math Library version number.\n");
@ -39,20 +41,20 @@ main(int argc, char **argv)
/* This is a standard input/output loop for testing. */
printf("Press the EOF character (Control-D) to exit.\n");
for (;;) {
printf("%d-> ", cur_equation + 1);
printf("%d-> ", matho_cur_equation(mathomatic) + 1);
fflush(stdout);
if ((cp = fgets(buf, sizeof(buf), stdin)) == NULL)
break;
/* Run the Mathomatic symbolic math engine. */
rv = matho_process(cp, &ocp);
if (warning_str) {
rv = matho_process(mathomatic, cp, &ocp);
if (matho_get_warning_str(mathomatic)) {
/* Optionally display any warnings (not required, but helpful). */
printf("Warning: %s\n", warning_str);
printf("Warning: %s\n", matho_get_warning_str(mathomatic));
}
if (ocp) {
if (rv && result_en >= 0) {
if (rv && matho_result_en(mathomatic) >= 0) {
/* Display the result equation number. */
printf("%d: ", result_en + 1);
printf("%d: ", matho_result_en(mathomatic) + 1);
}
/* Display the result. */
printf("Library result string:\n%s\n", ocp);
@ -68,5 +70,6 @@ main(int argc, char **argv)
free_mem(); /* reclaim all memory to check for memory leaks with something like valgrind(1) */
#endif
printf("\n");
closetMathoMatic(mathomatic);
exit(0);
}

567
list.c

File diff suppressed because it is too large Load Diff

201
main.c
View File

@ -70,6 +70,8 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#if !LIBRARY /* This comments out this whole file if compiling as the symbolic math library. */
#include "includes.h"
#include "lib/mathomatic.h"
#if !NO_GETOPT_H
#include <getopt.h>
#endif
@ -81,15 +83,16 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
HANDLE hOut;
#endif
MathoMatic *mathomatic;
/*
* Display invocation usage info.
*/
void
usage(fp)
FILE *fp;
usage(FILE *fp)
{
fprintf(fp, _("Mathomatic computer algebra system, version %s\n"), VERSION);
fprintf(fp, _("Usage: %s [ options ] [ input_files or input ]\n\n"), prog_name);
fprintf(fp, _("Usage: %s [ options ] [ input_files or input ]\n\n"), mathomatic->prog_name);
fprintf(fp, _("Options:\n"));
fprintf(fp, _(" -a Enable alternative color mode.\n"));
fprintf(fp, _(" -b Enable bold color mode.\n"));
@ -134,45 +137,46 @@ char **argv;
#if I18N
/* Initialize internationalization so that messages are in the right language. */
setlocale(LC_ALL, "");
bindtextdomain(prog_name, LOCALEDIR);
textdomain(prog_name);
bindtextdomain(mathomatic->prog_name, LOCALEDIR);
textdomain(mathomatic->prog_name);
#endif
#if CYGWIN || MINGW
dir_path = strdup(dirname_win(argv[0])); /* set dir_path to this executable's directory */
#endif
mathomatic = newtMathoMatic();
/* initialize the global variables */
init_gvars();
default_out = stdout; /* set default_out to any file you want to redirect output to */
gfp = default_out;
get_screen_size();
init_gvars(mathomatic);
mathomatic->default_out = stdout; /* set default_out to any file you want to redirect output to */
mathomatic->gfp = mathomatic->default_out;
get_screen_size(mathomatic);
/* process command line options */
while ((i = getopt(argc, argv, "s:abqrtdchuvwxm:e")) >= 0) {
switch (i) {
case 's':
if (optarg) {
security_level = strtod(optarg, &cp);
mathomatic->security_level = strtod(optarg, &cp);
#if SECURE
if (security_level != 4) {
fprintf(stderr, _("%s: Already compiled for maximum security (level 4), therefore setting security level ignored.\n"), prog_name);
if (mathomatic->security_level != 4) {
fprintf(stderr, _("%s: Already compiled for maximum security (level 4), therefore setting security level ignored.\n"), mathomatic->prog_name);
}
#endif
}
if (optarg == NULL || cp == NULL || (cp == optarg && *cp != ':') || (*cp != '\0' && *cp != ':')) {
fprintf(stderr, _("%s: Error in setting security level.\n"), prog_name);
fprintf(stderr, _("%s: Error in setting security level.\n"), mathomatic->prog_name);
exit(2);
}
if (*cp == ':') {
time_out_seconds = strtol(cp + 1, &cp, 10);
if (!(*cp == '\0' && time_out_seconds > 0)) {
fprintf(stderr, _("%s: Error in setting time out seconds.\n"), prog_name);
fprintf(stderr, _("%s: Error in setting time out seconds.\n"), mathomatic->prog_name);
exit(2);
}
}
#if !SECURE
if (time_out_seconds > 0) {
printf(_("Security level is %d, time out seconds is %d.\n"), security_level, time_out_seconds);
printf(_("Security level is %d, time out seconds is %d.\n"), mathomatic->security_level, time_out_seconds);
}
#endif
break;
@ -189,34 +193,34 @@ char **argv;
coption++;
break;
case 'x':
html_flag = 1;
mathomatic->html_flag = 1;
wide_flag = true;
break;
case 'm':
if (optarg)
new_size = strtod(optarg, &cp) * DEFAULT_N_TOKENS;
if (optarg == NULL || cp == NULL || *cp || new_size <= 0 || new_size >= (INT_MAX / sizeof(token_type))) {
fprintf(stderr, _("%s: Invalid memory size multiplier specified.\n"), prog_name);
fprintf(stderr, _("%s: Invalid memory size multiplier specified.\n"), mathomatic->prog_name);
exit(2);
}
n_tokens = (int) new_size;
mathomatic->n_tokens = (int) new_size;
break;
case 'q':
quiet_mode = true;
mathomatic->quiet_mode = true;
break;
case 'r':
readline_enabled = false;
mathomatic->readline_enabled = false;
break;
case 't':
readline_enabled = false;
mathomatic->readline_enabled = false;
wide_flag = true;
test_mode = true;
mathomatic->test_mode = true;
break;
case 'd':
demo_mode = true;
mathomatic->demo_mode = true;
break;
case 'u':
echo_input = true;
mathomatic->echo_input = true;
setbuf(stdout, NULL); /* make output unbuffered */
setbuf(stderr, NULL);
break;
@ -228,30 +232,30 @@ char **argv;
printf(_("Mathomatic version %s\n"), VERSION);
exit(0);
case 'e':
eoption = true;
autoselect = false;
mathomatic->eoption = true;
mathomatic->autoselect = false;
break;
default:
usage(stdout);
exit(2);
}
}
if (n_tokens < 100 || n_tokens >= (INT_MAX / sizeof(token_type))) {
fprintf(stderr, _("%s: Standard expression array size %d out of range!\n"), prog_name, n_tokens);
if (mathomatic->n_tokens < 100 || mathomatic->n_tokens >= (INT_MAX / sizeof(token_type))) {
fprintf(stderr, _("%s: Standard expression array size %d out of range!\n"), mathomatic->prog_name, mathomatic->n_tokens);
}
if (!init_mem()) {
fprintf(stderr, _("%s: Not enough memory.\n"), prog_name);
if (!init_mem(mathomatic)) {
fprintf(stderr, _("%s: Not enough memory.\n"), mathomatic->prog_name);
exit(2);
}
#if READLINE
if (readline_enabled) { /* readline_enabled flag must not change after this */
if (mathomatic->readline_enabled) { /* readline_enabled flag must not change after this */
if ((cp = getenv("HOME"))) {
#if MINGW
snprintf(history_filename_storage, sizeof(history_filename_storage), "%s/matho_history", cp);
snprintf(mathomatic->history_filename_storage, sizeof(mathomatic->history_filename_storage), "%s/matho_history", cp);
#else
snprintf(history_filename_storage, sizeof(history_filename_storage), "%s/.matho_history", cp);
snprintf(mathomatic->history_filename_storage, sizeof(mathomatic->history_filename_storage), "%s/.matho_history", cp);
#endif
history_filename = history_filename_storage;
mathomatic->history_filename = mathomatic->history_filename_storage;
}
using_history(); /* initialize readline history */
rl_initialize(); /* initialize readline */
@ -259,58 +263,58 @@ char **argv;
rl_inhibit_completion = true; /* turn off readline file name completion */
#if 0 /* not 100% tested and this might confuse the user with the -c toggle */
#if !WIN32_CONSOLE_COLORS
if (!html_flag) { /* If doing ANSI color: */
color_flag = (tigetnum("colors") >= 8); /* autoset color output mode. Requires ncurses. */
if (!mathomatic->html_flag) { /* If doing ANSI color: */
mathomatic->color_flag = (tigetnum("colors") >= 8); /* autoset color output mode. Requires ncurses. */
}
#endif
#endif
#if !SECURE
if (security_level <= 3) {
read_history(history_filename); /* restore readline history of previous session */
if (mathomatic->security_level <= 3) {
read_history(mathomatic->history_filename); /* restore readline history of previous session */
}
#endif
}
#endif
if (html_flag) {
if (mathomatic->html_flag) {
printf("<pre>\n");
}
if (!test_mode && !quiet_mode && !eoption) {
display_startup_message(stdout);
if (!mathomatic->test_mode && !mathomatic->quiet_mode && !mathomatic->eoption) {
display_startup_message(mathomatic, stdout);
}
fflush(stdout);
#if !SECURE
/* read the user options initialization file */
if (security_level <= 3 && !test_mode && !demo_mode && !load_rc(true, NULL)) {
fprintf(stderr, _("%s: Error loading startup set options from \"%s\".\n"), prog_name, rc_file);
if (mathomatic->security_level <= 3 && !mathomatic->test_mode && !mathomatic->demo_mode && !load_rc(mathomatic, true, NULL)) {
fprintf(stderr, _("%s: Error loading startup set options from \"%s\".\n"), mathomatic->prog_name, mathomatic->rc_file);
fprintf(stderr, _("Use the \"set no save\" command to startup with the program defaults every time.\n\n"));
}
#endif
if (wide_flag) {
screen_columns = 0;
screen_rows = 0;
mathomatic->screen_columns = 0;
mathomatic->screen_rows = 0;
}
if (coption & 1) {
color_flag = !color_flag;
mathomatic->color_flag = !mathomatic->color_flag;
}
if (boption) {
color_flag = 1;
bold_colors = 1;
mathomatic->color_flag = 1;
mathomatic->bold_colors = 1;
}
if (color_flag && aoption) {
color_flag = 2;
if (mathomatic->color_flag && aoption) {
mathomatic->color_flag = 2;
}
if (test_mode) {
color_flag = 0;
} else if (!quiet_mode && !eoption) {
if (color_flag) {
if (mathomatic->test_mode) {
mathomatic->color_flag = 0;
} else if (!mathomatic->quiet_mode && !mathomatic->eoption) {
if (mathomatic->color_flag) {
#if WIN32_CONSOLE_COLORS
if (color_flag == 2) {
printf(_("%s%s color mode enabled"), html_flag ? "HTML" : "ANSI", bold_colors ? " bold" : "");
if (mathomatic->color_flag == 2) {
printf(_("%s%s color mode enabled"), mathomatic->html_flag ? "HTML" : "ANSI", mathomatic->bold_colors ? " bold" : "");
} else {
printf(_("%s%s color mode enabled"), html_flag ? "HTML" : "WIN32 CONSOLE", bold_colors ? " bold" : "");
printf(_("%s%s color mode enabled"), mathomatic->html_flag ? "HTML" : "WIN32 CONSOLE", mathomatic->bold_colors ? " bold" : "");
}
#else
printf(_("%s%s color mode enabled"), html_flag ? "HTML" : "ANSI", bold_colors ? " bold" : "");
printf(_("%s%s color mode enabled"), mathomatic->html_flag ? "HTML" : "ANSI", mathomatic->bold_colors ? " bold" : "");
#endif
printf(_("; manage by typing \"help color\".\n"));
} else {
@ -318,18 +322,18 @@ char **argv;
}
}
fflush(stdout);
if ((i = setjmp(jmp_save)) != 0) {
if ((i = setjmp(mathomatic->jmp_save)) != 0) {
/* for error handling */
clean_up();
clean_up(mathomatic);
switch (i) {
case 14:
error(_("Expression too large."));
error(mathomatic, _("Expression too large."));
default:
printf(_("Operation aborted.\n"));
break;
}
previous_return_value = 0;
if (eoption)
mathomatic->previous_return_value = 0;
if (mathomatic->eoption)
exit_value = 1;
} else {
if ((rv = set_signals(time_out_seconds))) {
@ -339,38 +343,38 @@ char **argv;
#endif
exit_value = 2;
}
if (!f_to_fraction(0.5, &numerator, &denominator)
if (!f_to_fraction(mathomatic, 0.5, &numerator, &denominator)
|| numerator != 1.0 || denominator != 2.0
|| !f_to_fraction(1.0/3.0, &numerator, &denominator)
|| !f_to_fraction(mathomatic, 1.0/3.0, &numerator, &denominator)
|| numerator != 1.0 || denominator != 3.0) {
fprintf(stderr, _("%s: Cannot convert any floating point values to fractions!\n"), prog_name);
fprintf(stderr, _("%s: Cannot convert any floating point values to fractions!\n"), mathomatic->prog_name);
fprintf(stderr, _("Roots will not work properly.\n"));
exit_value = 2;
}
if (max_memory_usage() <= 0) {
fprintf(stderr, _("%s: Calculated maximum memory usage overflows a long integer!\n"), prog_name);
if (max_memory_usage(mathomatic) <= 0) {
fprintf(stderr, _("%s: Calculated maximum memory usage overflows a long integer!\n"), mathomatic->prog_name);
exit_value = 2;
}
if (eoption) {
if (mathomatic->eoption) {
/* process expressions and commands from the command line */
for (i = optind; i < argc && argv[i]; i++) {
if (!display_process(argv[i])) {
if (!display_process(mathomatic, argv[i])) {
exit_value = 1;
}
}
} else {
#if SECURE
if (!quiet_mode && !test_mode)
if (!mathomatic->quiet_mode && !mathomatic->test_mode)
printf(_("Anything done here is temporary.\n"));
if (optind < argc) {
warning(_("File arguments ignored in high security mode."));
warning(mathomatic, _("File arguments ignored in high security mode."));
}
#else
if (!quiet_mode && !test_mode) {
if (!mathomatic->quiet_mode && !mathomatic->test_mode) {
if (optind < argc) {
printf(_("Reading in file%s specified on the command line...\n"), (optind == (argc - 1)) ? "" : "s");
} else {
if (security_level >= 2) {
if (mathomatic->security_level >= 2) {
printf(_("Anything done here is temporary.\n"));
} else {
printf(_("Anything done here is temporary, unless it is saved or redirected.\n"));
@ -381,7 +385,7 @@ char **argv;
for (i = optind; i < argc && argv[i]; i++) {
if (strcmp(argv[i], "-") == 0) {
main_io_loop();
} else if (!read_file(argv[i])) {
} else if (!read_file(mathomatic, argv[i])) {
fflush(NULL); /* flush all output */
fprintf(stderr, _("Read of file \"%s\" failed.\n"), argv[i]);
exit_program(1);
@ -390,7 +394,7 @@ char **argv;
#endif
}
}
if (!eoption)
if (!mathomatic->eoption)
main_io_loop(); /* main input/output loop */
exit_program(exit_value); /* exit Mathomatic, doesn't return */
return(exit_value); /* so the compiler doesn't complain */
@ -405,13 +409,13 @@ main_io_loop(void)
char *cp = NULL;
for (;;) {
error_str = NULL;
warning_str = NULL;
default_color(false);
snprintf(prompt_str, sizeof(prompt_str), "%d%s", cur_equation + 1, html_flag ? HTML_PROMPT_STR : PROMPT_STR);
if ((cp = get_string((char *) tlhs, n_tokens * sizeof(token_type))) == NULL)
matho_set_error_str(mathomatic, NULL);
matho_set_warning_str(mathomatic, NULL);
default_color(mathomatic, false);
snprintf(mathomatic->prompt_str, sizeof(mathomatic->prompt_str), "%d%s", mathomatic->cur_equation + 1, mathomatic->html_flag ? HTML_PROMPT_STR : PROMPT_STR);
if ((cp = get_string(mathomatic, (char *) mathomatic->tlhs, mathomatic->n_tokens * sizeof(token_type))) == NULL)
break;
process(cp);
process(mathomatic, cp);
}
}
@ -466,7 +470,7 @@ fphandler(sig)
int sig;
{
#if DEBUG
warning("Floating point exception.");
warning(mathomatic, "Floating point exception.");
#endif
}
@ -479,8 +483,8 @@ void
inthandler(sig)
int sig;
{
abort_flag++;
switch (abort_flag) {
matho_inc_abort_flag(mathomatic);
switch (matho_get_abort_flag(mathomatic)) {
case 0:
case 1:
/* wait for graceful abort */
@ -505,7 +509,7 @@ alarmhandler(sig)
int sig;
{
printf(_("\nTimeout, quitting...\n"));
exit_program(1);
exit_program(mathomatic, 1);
}
#endif
@ -513,8 +517,7 @@ int sig;
* Signal handler for proper exiting to the operating system.
*/
void
exithandler(sig)
int sig;
exithandler(int sig)
{
exit_program(1);
}
@ -524,11 +527,10 @@ int sig;
* Window resize signal handler.
*/
void
resizehandler(sig)
int sig;
resizehandler(int sig)
{
if (screen_columns)
get_screen_size();
if (mathomatic->screen_columns)
get_screen_size(mathomatic);
}
#endif
@ -536,19 +538,19 @@ int sig;
* Properly exit this program and return to the operating system.
*/
void
exit_program(exit_value)
int exit_value; /* zero if OK, non-zero indicates error return */
exit_program(int exit_value)
//int exit_value; /* zero if OK, non-zero indicates error return */
{
reset_attr();
if (html_flag) {
reset_attr(mathomatic);
if (mathomatic->html_flag) {
printf("</pre>\n");
}
#if READLINE && !SECURE
if (readline_enabled && security_level <= 3) {
write_history(history_filename); /* save readline history */
if (mathomatic->readline_enabled && mathomatic->security_level <= 3) {
write_history(mathomatic->history_filename); /* save readline history */
}
#endif
if (exit_value == 0 && !quiet_mode && !eoption && !html_flag) {
if (exit_value == 0 && !mathomatic->quiet_mode && !mathomatic->eoption && !mathomatic->html_flag) {
printf(_("ByeBye!! from Mathomatic.\n"));
}
#if VALGRIND
@ -556,6 +558,7 @@ int exit_value; /* zero if OK, non-zero indicates error return */
printf("If you are not using valgrind, please compile without -DVALGRIND.\n");
free_mem(); /* Free all known memory buffers to check for memory leaks with something like valgrind(1). */
#endif
closetMathoMatic(mathomatic);
exit(exit_value);
}
#endif

198
parse.c
View File

@ -45,35 +45,34 @@ char *cp;
* followed by the error message, which must be a constant string.
*/
void
put_up_arrow(cnt, cp)
int cnt; /* position of error, relative to "input_column" */
char *cp; /* error message (constant ASCII string) */
put_up_arrow(MathoMatic* mathomatic, int cnt, char *cp)
//int cnt; /* position of error, relative to "input_column" */
//char *cp; /* error message (constant ASCII string) */
{
#if !SILENT && !LIBRARY
int i;
cnt += input_column;
if (!quiet_mode && point_flag && (screen_columns == 0 || cnt < screen_columns)) {
cnt += mathomatic->input_column;
if (!mathomatic->quiet_mode && mathomatic->point_flag && (mathomatic->screen_columns == 0 || cnt < mathomatic->screen_columns)) {
for (i = 0; i < cnt; i++) {
printf(" ");
}
printf("^ ");
}
#endif
error(cp);
error(mathomatic, cp);
}
/*
* Return true if character is a valid starting variable character.
*/
int
isvarchar(ch)
int ch;
isvarchar(MathoMatic* mathomatic, int ch)
{
if (isdigit(ch)) { /* variable names can never start with a digit */
return false;
}
return(ch == '_' || (ch && strchr(special_variable_characters, ch)) || isalpha(ch));
return(ch == '_' || (ch && strchr(mathomatic->special_variable_characters, ch)) || isalpha(ch));
}
/*
@ -130,7 +129,7 @@ int i; /* location of operator to parenthesize in expression */
#if DEBUG
if (i >= (n - 1) || (n & 1) != 1 || (i & 1) != 1 || p1[i].kind != OPERATOR) {
error_bug("Internal error in arguments to binary_parenthesize().");
error_bug(mathomatic, "Internal error in arguments to binary_parenthesize().");
}
#endif
skip_negate = (p1[i].token.operatr != NEGATE);
@ -186,9 +185,9 @@ int *np;
* organize() should be called after this to remove unneeded parentheses.
*/
void
give_priority(equation, np)
token_type *equation; /* pointer to expression */
int *np; /* pointer to expression length */
give_priority(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* pointer to expression */
//int *np; /* pointer to expression length */
{
int i;
@ -199,7 +198,7 @@ int *np; /* pointer to expression length */
}
}
if (right_associative_power) {
if (mathomatic->right_associative_power) {
for (i = *np - 2; i >= 1; i -= 2) { /* count down (for right to left evaluation) */
if (equation[i].token.operatr == POWER) {
binary_parenthesize(equation, *np, i);
@ -236,11 +235,11 @@ int *np; /* pointer to expression length */
* Returns the new string position, or NULL if error.
*/
char *
parse_section(equation, np, cp, allow_space)
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 allow_space; /* if false, any space characters terminate parsing */
parse_section(MathoMatic* mathomatic, token_type *equation, int *np, char *cp, int allow_space)
//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 allow_space; /* if false, any space characters terminate parsing */
{
int i;
int n = 0, old_n; /* position in equation[] */
@ -255,8 +254,8 @@ int allow_space; /* if false, any space characters terminate parsing */
return(NULL);
cp_start = cp;
for (;; cp++) {
if (n > (n_tokens - 10)) {
error_huge();
if (n > (mathomatic->n_tokens - 10)) {
error_huge(mathomatic);
}
switch (*cp) {
case '(':
@ -279,7 +278,7 @@ int allow_space; /* if false, any space characters terminate parsing */
case '}':
cur_level--;
if (cur_level <= 0 || (abs_count > 0 && cur_level < abs_array[abs_count-1])) {
put_up_arrow(cp - cp_start, _("Unmatched parenthesis: too many )"));
put_up_arrow(mathomatic, cp - cp_start, _("Unmatched parenthesis: too many )"));
return(NULL);
}
if (!operand) {
@ -301,7 +300,7 @@ int allow_space; /* if false, any space characters terminate parsing */
continue;
case '\033':
if (cp[1] == '[' || cp[1] == 'O') {
error(_("Cursor or function key string encountered, unable to interpret."));
error(mathomatic, _("Cursor or function key string encountered, unable to interpret."));
return(NULL);
}
continue;
@ -311,7 +310,7 @@ int allow_space; /* if false, any space characters terminate parsing */
case '|':
if (operand) {
if (abs_count >= ARR_CNT(abs_array)) {
error(_("Too many nested absolute values."));
error(mathomatic, _("Too many nested absolute values."));
return(NULL);
}
cur_level += 3;
@ -347,7 +346,7 @@ int allow_space; /* if false, any space characters terminate parsing */
goto syntax_error;
}
if (cp[1] == '!' && cp[2] != '!') {
warning(_("Multifactorial not implemented, using x!! = (x!)!"));
warning(mathomatic, _("Multifactorial not implemented, using x!! = (x!)!"));
}
equation[n].level = cur_level;
equation[n].kind = OPERATOR;
@ -425,7 +424,7 @@ parse_power:
if (strncmp(cp, "+/-", 3) == 0) {
equation[n].level = cur_level;
equation[n].kind = VARIABLE;
next_sign(&equation[n].token.variable);
next_sign(mathomatic, &equation[n].token.variable);
n++;
equation[n].level = cur_level;
equation[n].kind = OPERATOR;
@ -475,7 +474,7 @@ parse_power:
goto syntax_error;
}
if (errno) {
put_up_arrow(cp1 - cp_start, _("Constant out of range."));
put_up_arrow(mathomatic, cp1 - cp_start, _("Constant out of range."));
return(NULL);
}
equation[n].kind = CONSTANT;
@ -494,42 +493,42 @@ parse_power:
case '+':
case '-':
i = strtol(cp, &cp1, 10);
i = cur_equation + i;
i = mathomatic->cur_equation + i;
break;
default:
i = strtol(cp, &cp1, 10) - 1;
break;
}
if (cp1 == NULL || cp == cp1) {
put_up_arrow(cp - cp_start, _("Error parsing equation space number after #."));
put_up_arrow(mathomatic, cp - cp_start, _("Error parsing equation space number after #."));
return NULL;
}
if (empty_equation_space(i)) {
put_up_arrow(cp - cp_start, _("No expression available in # specified equation space."));
if (empty_equation_space(mathomatic, i)) {
put_up_arrow(mathomatic, cp - cp_start, _("No expression available in # specified equation space."));
return NULL;
}
cp = cp1 - 1;
old_n = n;
if (n_rhs[i]) {
n += n_rhs[i];
if (n > n_tokens) {
error_huge();
if (mathomatic->n_rhs[i]) {
n += mathomatic->n_rhs[i];
if (n > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[old_n], rhs[i], n_rhs[i] * sizeof(token_type));
blt(&equation[old_n], mathomatic->rhs[i], mathomatic->n_rhs[i] * sizeof(token_type));
} else {
n += n_lhs[i];
if (n > n_tokens) {
error_huge();
n += mathomatic->n_lhs[i];
if (n > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[old_n], lhs[i], n_lhs[i] * sizeof(token_type));
blt(&equation[old_n], mathomatic->lhs[i], mathomatic->n_lhs[i] * sizeof(token_type));
}
for (; old_n < n; old_n++) {
equation[old_n].level += cur_level;
}
break;
default:
if (!isvarchar(*cp)) {
put_up_arrow(cp - cp_start, _("Unrecognized character."));
if (!isvarchar(mathomatic, *cp)) {
put_up_arrow(mathomatic, cp - cp_start, _("Unrecognized character."));
return(NULL);
}
if (!operand) {
@ -541,18 +540,18 @@ parse_power:
}
cp1 = cp;
if (strncasecmp(cp, "inf", strlen("inf")) == 0
&& !isvarchar(cp[strlen("inf")])) {
&& !isvarchar(mathomatic, cp[strlen("inf")])) {
equation[n].kind = CONSTANT;
equation[n].token.constant = INFINITY; /* the infinity constant */
cp += strlen("inf");
} else if (strncasecmp(cp, INFINITY_NAME, strlen(INFINITY_NAME)) == 0
&& !isvarchar(cp[strlen(INFINITY_NAME)])) {
&& !isvarchar(mathomatic, cp[strlen(INFINITY_NAME)])) {
equation[n].kind = CONSTANT;
equation[n].token.constant = INFINITY; /* the infinity constant */
cp += strlen(INFINITY_NAME);
} else {
equation[n].kind = VARIABLE;
cp = parse_var(&equation[n].token.variable, cp);
cp = parse_var(mathomatic, &equation[n].token.variable, cp);
if (cp == NULL) {
return(NULL);
}
@ -560,9 +559,9 @@ parse_power:
if (*cp == '(') {
/* Named functions currently not implemented, except when using m4. */
#if LIBRARY
put_up_arrow(cp1 - cp_start, _("Unknown function."));
put_up_arrow(mathomatic, cp1 - cp_start, _("Unknown function."));
#else
put_up_arrow(cp1 - cp_start, _("Unknown function; try using rmath, which allows basic functions."));
put_up_arrow(mathomatic, cp1 - cp_start, _("Unknown function; try using rmath, which allows basic functions."));
#endif
return(NULL);
}
@ -577,21 +576,21 @@ p_out:
goto syntax_error;
}
if (cur_level != 1) {
put_up_arrow(cp - cp_start, _("Unmatched parenthesis: missing )"));
put_up_arrow(mathomatic, cp - cp_start, _("Unmatched parenthesis: missing )"));
return(NULL);
}
while (*cp == '=')
cp++;
*np = n;
if (n) {
give_priority(equation, np);
organize(equation, np);
give_priority(mathomatic, equation, np);
organize(mathomatic, equation, np);
}
input_column += (cp - cp_start);
mathomatic->input_column += (cp - cp_start);
return cp;
syntax_error:
put_up_arrow(cp - cp_start, _("Syntax error."));
put_up_arrow(mathomatic, cp - cp_start, _("Syntax error."));
return(NULL);
}
@ -604,18 +603,18 @@ syntax_error:
* Currently, there can be no more to parse in the string when this returns.
*/
char *
parse_equation(n, cp)
int n; /* equation space number */
char *cp; /* pointer to the beginning of the equation character string */
parse_equation(MathoMatic* mathomatic, int n, char *cp)
//int n; /* equation space number */
//char *cp; /* pointer to the beginning of the equation character string */
{
if ((cp = parse_expr(lhs[n], &n_lhs[n], cp, true)) != NULL) {
if ((cp = parse_expr(rhs[n], &n_rhs[n], cp, true)) != NULL) {
if (!extra_characters(cp))
if ((cp = parse_expr(mathomatic, mathomatic->lhs[n], &mathomatic->n_lhs[n], cp, true)) != NULL) {
if ((cp = parse_expr(mathomatic, mathomatic->rhs[n], &mathomatic->n_rhs[n], cp, true)) != NULL) {
if (!extra_characters(mathomatic, cp))
return cp;
}
}
n_lhs[n] = 0;
n_rhs[n] = 0;
mathomatic->n_lhs[n] = 0;
mathomatic->n_rhs[n] = 0;
return NULL;
}
@ -626,18 +625,18 @@ char *cp; /* pointer to the beginning of the equation character string */
* Returns the new string position, or NULL if error.
*/
char *
parse_expr(equation, np, cp, allow_space)
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 allow_space; /* if true, allow and ignore space characters; if false, space means terminate parsing */
parse_expr(MathoMatic* mathomatic, token_type *equation, int *np, char *cp, int allow_space)
//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 allow_space; /* if true, allow and ignore space characters; if false, space means terminate parsing */
{
if (cp == NULL)
return NULL;
if (!case_sensitive_flag) {
if (!mathomatic->case_sensitive_flag) {
str_tolower(cp);
}
cp = parse_section(equation, np, cp, allow_space);
cp = parse_section(mathomatic, equation, np, cp, allow_space);
return cp;
}
@ -651,9 +650,7 @@ int allow_space; /* if true, allow and ignore space characters; if false, space
* Display error message and return NULL on failure.
*/
char *
parse_var(vp, cp)
long *vp;
char *cp;
parse_var(MathoMatic* mathomatic, long *vp, char *cp)
{
int i, j;
long vtmp;
@ -663,17 +660,17 @@ char *cp;
int level; /* parentheses level */
int (*strcmpfunc)();
if (case_sensitive_flag) {
if (mathomatic->case_sensitive_flag) {
strcmpfunc = strcmp;
} else {
strcmpfunc = strcasecmp;
}
if (!isvarchar(*cp) || paren_increment(*cp) < 0) {
error(_("Invalid variable."));
if (!isvarchar(mathomatic, *cp) || paren_increment(*cp) < 0) {
error(mathomatic, _("Invalid variable."));
return(NULL); /* variable name must start with a valid variable character */
}
for (level = 0, cp1 = cp, i = 0; *cp1;) {
if (level <= 0 && !isvarchar(*cp1)) {
if (level <= 0 && !isvarchar(mathomatic, *cp1)) {
break;
}
j = paren_increment(*cp1);
@ -681,7 +678,7 @@ char *cp;
if (level < 0)
break;
if (i >= MAX_VAR_LEN) {
error(_("Variable name too long."));
error(mathomatic, _("Variable name too long."));
return(NULL);
}
buf[i++] = *cp1++;
@ -690,15 +687,15 @@ char *cp;
}
buf[i] = '\0';
if (level > 0) {
error(_("Unmatched parenthesis: missing )"));
error(mathomatic, _("Unmatched parenthesis: missing )"));
return(NULL);
}
if (strcasecmp(buf, NAN_NAME) == 0) {
warning(_("Attempt to enter NaN (Not a Number); Converted to variable."));
warning(mathomatic, _("Attempt to enter NaN (Not a Number); Converted to variable."));
}
if (strcasecmp(buf, "inf") == 0 || strcasecmp(buf, INFINITY_NAME) == 0) {
error(_("Infinity cannot be used as a variable."));
error(mathomatic, _("Infinity cannot be used as a variable."));
return(NULL);
} else if ((*strcmpfunc)(buf, "sign") == 0) {
vtmp = SIGN;
@ -716,7 +713,7 @@ char *cp;
return(cp + 3);
}
for (level = 0, cp1 = cp, i = 0; *cp1;) {
if (level <= 0 && !isvarchar(*cp1) && !isdigit(*cp1)) {
if (level <= 0 && !isvarchar(mathomatic, *cp1) && !isdigit(*cp1)) {
break;
}
j = paren_increment(*cp1);
@ -724,7 +721,7 @@ char *cp;
if (level < 0)
break;
if (i >= MAX_VAR_LEN) {
error(_("Variable name too long."));
error(mathomatic, _("Variable name too long."));
return(NULL);
}
buf[i++] = *cp1++;
@ -732,12 +729,12 @@ char *cp;
break;
}
if (i <= 0) {
error(_("Empty variable name parsed!"));
error(mathomatic, _("Empty variable name parsed!"));
return(NULL);
}
buf[i] = '\0';
if (level > 0) {
error(_("Unmatched parenthesis: missing )"));
error(mathomatic, _("Unmatched parenthesis: missing )"));
return(NULL);
}
if ((*strcmpfunc)(buf, "i") == 0) {
@ -753,33 +750,33 @@ char *cp;
return(cp1);
}
if (is_all(buf)) {
error(_("\"all\" is a reserved word and may not be used as a variable name."));
error(mathomatic, _("\"all\" is a reserved word and may not be used as a variable name."));
return(NULL);
}
vtmp = 0;
for (i = 0; var_names[i]; i++) {
if ((*strcmpfunc)(buf, var_names[i]) == 0) {
for (i = 0; mathomatic->var_names[i]; i++) {
if ((*strcmpfunc)(buf, mathomatic->var_names[i]) == 0) {
vtmp = i + VAR_OFFSET;
break;
}
}
if (vtmp == 0) {
if (i >= (MAX_VAR_NAMES - 1)) {
error(_("Maximum number of variable names reached."));
error(mathomatic, _("Maximum number of variable names reached."));
#if !SILENT
printf(_("Please restart or use \"clear all\".\n"));
#endif
return(NULL);
}
len = strlen(buf) + 1;
var_names[i] = (char *) malloc(len);
if (var_names[i] == NULL) {
error(_("Out of memory (can't malloc(3) variable name)."));
mathomatic->var_names[i] = (char *) malloc(len);
if (mathomatic->var_names[i] == NULL) {
error(mathomatic, _("Out of memory (can't malloc(3) variable name)."));
return(NULL);
}
blt(var_names[i], buf, len);
blt(mathomatic->var_names[i], buf, len);
vtmp = i + VAR_OFFSET;
var_names[i+1] = NULL;
mathomatic->var_names[i+1] = NULL;
}
*vp = vtmp;
return cp1;
@ -788,15 +785,15 @@ char *cp;
if (isdigit(*cp1)) {
j = strtol(cp1, &cp1, 10);
if (j < 0 || j > MAX_SUBSCRIPT) {
error(_("Maximum subscript exceeded in special variable name."));
error(mathomatic, _("Maximum subscript exceeded in special variable name."));
return(NULL);
}
if (vtmp == SIGN) {
sign_array[j+1] = true;
mathomatic->sign_array[j+1] = true;
}
vtmp += ((long) (j + 1)) << VAR_SHIFT;
} else if (vtmp == SIGN) {
sign_array[0] = true;
mathomatic->sign_array[0] = true;
}
*vp = vtmp;
return cp1;
@ -806,8 +803,7 @@ char *cp;
* Remove trailing spaces from a string.
*/
void
remove_trailing_spaces(cp)
char *cp;
remove_trailing_spaces(char *cp)
{
int i;
@ -824,20 +820,20 @@ char *cp;
* Truncate string to the actual content.
*/
void
set_error_level(cp)
char *cp; /* input string */
set_error_level(MathoMatic* mathomatic, char *cp)
//char *cp; /* input string */
{
char *cp1;
int len;
point_flag = true;
mathomatic->point_flag = true;
/* handle comments, line breaks, and the DOS EOF character (control-Z) by truncating the string where found */
cp1 = cp;
while ((cp1 = strpbrk(cp1, ";\n\r\032"))) {
if (cp1 > cp && *(cp1 - 1) == '\\') {
if (*cp1 == ';') {
/* skip backslash escaped semicolon */
point_flag = false;
mathomatic->point_flag = false;
len = strlen(cp1);
blt(cp1 - 1, cp1, len + 1);
continue;
@ -852,7 +848,7 @@ char *cp; /* input string */
/* set point_flag to false if non-printable characters encountered */
for (cp1 = cp; *cp1; cp1++) {
if (!isprint(*cp1)) {
point_flag = false;
mathomatic->point_flag = false;
}
}
}

1143
poly.c

File diff suppressed because it is too large Load Diff

458
proto.h
View File

@ -3,47 +3,47 @@
/* This file is required to compile Mathomatic quietly with the -Wall compiler option. */
/* am.c */
void display_startup_message(FILE *fp);
void error(const char *str);
void reset_error(void);
void warning(const char *str);
void error_huge(void);
void error_bug(const char *str);
void check_err(void);
int get_screen_size(void);
int malloc_vscreen(void);
int init_mem(void);
void display_startup_message(MathoMatic* mathomatic, FILE *fp);
void error(MathoMatic* mathomatic, const char *str);
void reset_error(MathoMatic* mathomatic);
void warning(MathoMatic* mathomatic, const char *str);
void error_huge(MathoMatic* mathomatic);
void error_bug(MathoMatic* mathomatic, const char *str);
void check_err(MathoMatic* mathomatic);
int get_screen_size(MathoMatic* mathomatic);
int malloc_vscreen(MathoMatic* mathomatic);
int init_mem(MathoMatic* mathomatic);
int check_gvars(void);
void init_gvars(void);
void clean_up(void);
void set_sign_array(void);
int next_sign(long *vp);
void clear_all(void);
int alloc_espace(int i);
int alloc_to_espace(int en);
int alloc_next_espace(void);
int next_espace(void);
void copy_espace(int src, int dest);
int solved_equation(int i);
void init_gvars(MathoMatic* mathomatic);
void clean_up(MathoMatic* mathomatic);
void set_sign_array(MathoMatic* mathomatic);
int next_sign(MathoMatic* mathomatic, long *vp);
void clear_all(MathoMatic* mathomatic);
int alloc_espace(MathoMatic* mathomatic, int i);
int alloc_to_espace(MathoMatic* mathomatic, int en);
int alloc_next_espace(MathoMatic* mathomatic);
int next_espace(MathoMatic* mathomatic);
void copy_espace(MathoMatic* mathomatic, int src, int dest);
int solved_equation(MathoMatic* mathomatic, int i);
int found_var(token_type *p1, int n, long v);
int var_in_equation(int i, long v);
int search_all_for_var(long v, int forward_direction);
void rename_var_in_es(int en, long from_v, long to_v);
int subst_var_with_exp(token_type *equation, int *np, token_type *expression, int len, long v);
int min_level(token_type *expression, int n);
int get_default_en(char *cp);
int get_expr(token_type *equation, int *np);
int prompt_var(long *vp);
int not_defined(int i);
int current_not_defined(void);
char *get_string(char *string, int n);
int get_yes_no(void);
int return_result(int en);
void free_result_str(void);
int var_in_equation(MathoMatic* mathomatic, int i, long v);
int search_all_for_var(MathoMatic* mathomatic, long v, int forward_direction);
void rename_var_in_es(MathoMatic* mathomatic, int en, long from_v, long to_v);
int subst_var_with_exp(MathoMatic* mathomatic, token_type *equation, int *np, token_type *expression, int len, long v);
int min_level(MathoMatic* mathomatic, token_type *expression, int n);
int get_default_en(MathoMatic* mathomatic, char *cp);
int get_expr(MathoMatic* mathomatic, token_type *equation, int *np);
int prompt_var(MathoMatic* mathomatic, long *vp);
int not_defined(MathoMatic* mathomatic, int i);
int current_not_defined(MathoMatic* mathomatic);
char *get_string(MathoMatic* mathomatic, char *string, int n);
int get_yes_no(MathoMatic* mathomatic);
int return_result(MathoMatic* mathomatic, int en);
void free_result_str(MathoMatic* mathomatic);
int is_all(char *cp);
int get_range(char **cpp, int *ip, int *jp);
int extra_characters(char *cp);
int get_range_eol(char **cpp, int *ip, int *jp);
int get_range(MathoMatic* mathomatic, char **cpp, int *ip, int *jp);
int extra_characters(MathoMatic* mathomatic, char *cp);
int get_range_eol(MathoMatic* mathomatic, char **cpp, int *ip, int *jp);
char *skip_space(char *cp);
char *skip_comma_space(char *cp);
long decstrtol(char *cp, char **cpp);
@ -51,71 +51,71 @@ int isdelimiter(int ch);
char *skip_param(char *cp);
int strcmp_tospace(char *cp1, char *cp2);
int level_plus_count(token_type *p1, int n1, int level);
int level1_plus_count(token_type *p1, int n1);
int level1_plus_count(MathoMatic* mathomatic, token_type *p1, int n1);
int var_count(token_type *p1, int n1);
int no_vars(token_type *source, int n, long *vp);
int exp_contains_infinity(token_type *p1, int n1);
int exp_contains_nan(token_type *p1, int n1);
int exp_is_numeric(token_type *p1, int n1);
int exp_is_absolute(token_type *p1, int n1);
int check_divide_by_zero(double denominator);
int load_rc(int return_true_if_no_file, FILE *ofp);
int check_divide_by_zero(MathoMatic* mathomatic, double denominator);
int load_rc(MathoMatic* mathomatic, int return_true_if_no_file, FILE *ofp);
/* cmds.c */
int plot_cmd(char *cp);
int version_cmd(char *cp);
long max_memory_usage(void);
int plot_cmd(MathoMatic* mathomatic, char *cp);
int version_cmd(MathoMatic* mathomatic, char *cp);
long max_memory_usage(MathoMatic* mathomatic);
int show_status(FILE *ofp);
int version_report(void);
int solve_cmd(char *cp);
int sum_cmd(char *cp);
int product_cmd(char *cp);
int for_cmd(char *cp);
int optimize_cmd(char *cp);
int output_current_directory(FILE *ofp);
int version_report(MathoMatic* mathomatic);
int solve_cmd(MathoMatic* mathomatic, char *cp);
int sum_cmd(MathoMatic* mathomatic, char *cp);
int product_cmd(MathoMatic* mathomatic, char *cp);
int for_cmd(MathoMatic* mathomatic, char *cp);
int optimize_cmd(MathoMatic* mathomatic, char *cp);
int output_current_directory(MathoMatic* mathomatic, FILE *ofp);
int fprintf_escaped(FILE *ofp, char *cp);
void output_options(FILE *ofp, int all_set_options);
void output_options(MathoMatic* mathomatic, FILE *ofp, int all_set_options);
int skip_no(char **cpp);
int save_set_options(char *cp);
int set_options(char *cp, int loading_startup_file);
int set_cmd(char *cp);
int echo_cmd(char *cp);
int pause_cmd(char *cp);
int copy_cmd(char *cp);
int real_cmd(char *cp);
int imaginary_cmd(char *cp);
int tally_cmd(char *cp);
int calculate_cmd(char *cp);
int clear_cmd(char *cp);
int compare_es(int i, int j);
int compare_cmd(char *cp);
int display_fraction(double value);
int divide_cmd(char *cp);
int eliminate_cmd(char *cp);
int display_cmd(char *cp);
int list_cmd(char *cp);
int code_cmd(char *cp);
int variables_cmd(char *cp);
int approximate_cmd(char *cp);
int replace_cmd(char *cp);
int simplify_cmd(char *cp);
int factor_cmd(char *cp);
int display_term_count(int en);
int unfactor_cmd(char *cp);
int div_loc_find(token_type *expression, int n);
int fraction_cmd(char *cp);
int quit_cmd(char *cp);
int read_cmd(char *cp);
int read_file(char *cp);
int read_sub(FILE *fp, char *filename);
int edit_cmd(char *cp);
int save_cmd(char *cp);
int save_set_options(MathoMatic* mathomatic, char *cp);
int set_options(MathoMatic* mathomatic, char *cp, int loading_startup_file);
int set_cmd(MathoMatic* mathomatic, char *cp);
int echo_cmd(MathoMatic* mathomatic, char *cp);
int pause_cmd(MathoMatic* mathomatic, char *cp);
int copy_cmd(MathoMatic* mathomatic, char *cp);
int real_cmd(MathoMatic* mathomatic, char *cp);
int imaginary_cmd(MathoMatic* mathomatic, char *cp);
int tally_cmd(MathoMatic* mathomatic, char *cp);
int calculate_cmd(MathoMatic* mathomatic, char *cp);
int clear_cmd(MathoMatic* mathomatic, char *cp);
int compare_es(MathoMatic* mathomatic, int i, int j);
int compare_cmd(MathoMatic* mathomatic, char *cp);
int display_fraction(MathoMatic* mathomatic, double value);
int divide_cmd(MathoMatic* mathomatic, char *cp);
int eliminate_cmd(MathoMatic* mathomatic, char *cp);
int display_cmd(MathoMatic* mathomatic, char *cp);
int list_cmd(MathoMatic* mathomatic, char *cp);
int code_cmd(MathoMatic* mathomatic, char *cp);
int variables_cmd(MathoMatic* mathomatic, char *cp);
int approximate_cmd(MathoMatic* mathomatic, char *cp);
int replace_cmd(MathoMatic* mathomatic, char *cp);
int simplify_cmd(MathoMatic* mathomatic, char *cp);
int factor_cmd(MathoMatic* mathomatic, char *cp);
int display_term_count(MathoMatic* mathomatic, int en);
int unfactor_cmd(MathoMatic* mathomatic, char *cp);
int div_loc_find(MathoMatic* mathomatic, token_type *expression, int n);
int fraction_cmd(MathoMatic* mathomatic, char *cp);
int quit_cmd(MathoMatic* mathomatic, char *cp);
int read_cmd(MathoMatic* mathomatic, char *cp);
int read_file(MathoMatic* mathomatic, char *cp);
int read_sub(MathoMatic* mathomatic, FILE *fp, char *filename);
int edit_cmd(MathoMatic* mathomatic, char *cp);
int save_cmd(MathoMatic* mathomatic, char *cp);
/* complex.c */
void rect_to_polar(double x, double y, double *radiusp, double *thetap);
int roots_cmd(char *cp);
int complex_root_simp(token_type *equation, int *np);
int approximate_complex_roots(token_type *equation, int *np);
int get_constant(token_type *p1, int n, double *dp);
int parse_complex(token_type *p1, int n, complexs *cp);
int roots_cmd(MathoMatic * mathomatic, char *cp);
int complex_root_simp(MathoMatic* mathomatic, token_type *equation, int *np);
int approximate_complex_roots(MathoMatic* mathomatic, token_type *equation, int *np);
int get_constant(MathoMatic* mathomatic, token_type *p1, int n, double *dp);
int parse_complex(MathoMatic* mathomatic, token_type *p1, int n, complexs *cp);
/* complex_lib.c */
int complex_fixup(complexs *ap);
complexs complex_add(complexs a, complexs b);
@ -126,76 +126,76 @@ complexs complex_log(complexs a);
complexs complex_exp(complexs a);
complexs complex_pow(complexs a, complexs b);
/* diff.c */
int differentiate(token_type *equation, int *np, long v);
int derivative_cmd(char *cp);
int extrema_cmd(char *cp);
int taylor_cmd(char *cp);
int limit_cmd(char *cp);
int differentiate(MathoMatic* mathomatic, token_type *equation, int *np, long v);
int derivative_cmd(MathoMatic* mathomatic, char *cp);
int extrema_cmd(MathoMatic* mathomatic, char *cp);
int taylor_cmd(MathoMatic* mathomatic, char *cp);
int limit_cmd(MathoMatic* mathomatic, char *cp);
/* factor.c */
int factor_divide(token_type *equation, int *np, long v, double d);
int subtract_itself(token_type *equation, int *np);
int factor_plus(token_type *equation, int *np, long v, double d);
int factor_times(token_type *equation, int *np);
int factor_power(token_type *equation, int *np);
int factor_divide(MathoMatic* mathomatic, token_type *equation, int *np, long v, double d);
int subtract_itself(MathoMatic* mathomatic, token_type *equation, int *np);
int factor_plus(MathoMatic* mathomatic, token_type *equation, int *np, long v, double d);
int factor_times(MathoMatic* mathomatic, token_type *equation, int *np);
int factor_power(MathoMatic* mathomatic, token_type *equation, int *np);
/* factor_int.c */
int factor_one(double value);
double multiply_out_unique(void);
int display_unique(void);
int is_prime(void);
int factor_int(token_type *equation, int *np);
int factor_int_equation(int n);
int list_factor(token_type *equation, int *np, int factor_flag);
int factor_constants(token_type *equation, int *np, int level_code);
int factor_one(MathoMatic* mathomatic, double value);
double multiply_out_unique(MathoMatic* mathomatic);
int display_unique(MathoMatic* mathomatic);
int is_prime(MathoMatic* mathomatic);
int factor_int(MathoMatic* mathomatic, token_type *equation, int *np);
int factor_int_equation(MathoMatic* mathomatic, int n);
int list_factor(MathoMatic* mathomatic, token_type *equation, int *np, int factor_flag);
int factor_constants(MathoMatic* mathomatic, token_type *equation, int *np, int level_code);
/* gcd.c */
double gcd(double d1, double d2);
double gcd_verified(double d1, double d2);
double gcd(MathoMatic* mathomatic, double d1, double d2);
double gcd_verified(MathoMatic* mathomatic, double d1, double d2);
double my_round(double d1);
int f_to_fraction(double d, double *numeratorp, double *denominatorp);
int make_fractions(token_type *equation, int *np);
int make_simple_fractions(token_type *equation, int *np);
int make_mixed_fractions(token_type *equation, int *np);
int f_to_fraction(MathoMatic* mathomatic, double d, double *numeratorp, double *denominatorp);
int make_fractions(MathoMatic* mathomatic, token_type *equation, int *np);
int make_simple_fractions(MathoMatic* mathomatic, token_type *equation, int *np);
int make_mixed_fractions(MathoMatic* mathomatic, token_type *equation, int *np);
/* globals.c */
/* help.c */
int parse(int n, char *cp);
int process_parse(int n, char *cp);
int process(char *cp);
int process_rv(char *cp);
int display_process(char *cp);
int shell_out(char *cp);
char *parse_var2(long *vp, char *cp);
int display_usage(char *pstr, int i);
int display_command(int i);
int display_repeat_command(void);
int read_examples(char **cpp);
void underline_title(int count);
int help_cmd(char *cp);
int parse(MathoMatic* mathomatic, int n, char *cp);
int process_parse(MathoMatic* mathomatic, int n, char *cp);
int process(MathoMatic* mathomatic, char *cp);
int process_rv(MathoMatic* mathomatic, char *cp);
int display_process(MathoMatic* mathomatic, char *cp);
int shell_out(MathoMatic* mathomatic, char *cp);
char *parse_var2(MathoMatic* mathomatic, long *vp, char *cp);
int display_usage(MathoMatic* mathomatic, char *pstr, int i);
int display_command(MathoMatic* mathomatic, int i);
int display_repeat_command(MathoMatic* mathomatic);
int read_examples(MathoMatic* mathomatic, char **cpp);
void underline_title(MathoMatic* mathomatic, int count);
int help_cmd(MathoMatic* mathomatic, char *cp);
/* integrate.c */
void make_powers(token_type *equation, int *np, long v);
int int_dispatch(token_type *equation, int *np, long v, int (*func)(token_type *equation, int *np, int loc, int eloc, long v));
int integrate_cmd(char *cp);
int laplace_cmd(char *cp);
int nintegrate_cmd(char *cp);
void make_powers(MathoMatic* mathomatic, token_type *equation, int *np, long v);
int int_dispatch(MathoMatic* mathomatic, token_type *equation, int *np, long v, int (*func)(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int eloc, long v));
int integrate_cmd(MathoMatic* mathomatic, char *cp);
int laplace_cmd(MathoMatic* mathomatic, char *cp);
int nintegrate_cmd(MathoMatic* mathomatic, char *cp);
/* list.c */
void reset_attr(void);
int set_color(int color);
void default_color(int set_no_color_flag);
int display_all_colors(void);
int list1_sub(int n, int export_flag);
int list_sub(int n);
void list_debug(int level, token_type *p1, int n1, token_type *p2, int n2);
char *var_name(long v);
int list_var(long v, int lang_code);
int list_proc(token_type *p1, int n, int export_flag);
char *list_equation(int n, int export_flag);
char *list_expression(token_type *p1, int n, int export_flag);
int list_string(token_type *p1, int n, char *string, int export_flag);
int list_string_sub(token_type *p1, int n, int outflag, char *string, int export_flag);
void reset_attr(MathoMatic* mathomatic);
int set_color(MathoMatic* mathomatic, int color);
void default_color(MathoMatic* mathomatic, int set_no_color_flag);
int display_all_colors(MathoMatic* mathomatic);
int list1_sub(MathoMatic* mathomatic, int n, int export_flag);
int list_sub(MathoMatic* mathomatic, int n);
void list_debug(MathoMatic* mathomatic, int level, token_type *p1, int n1, token_type *p2, int n2);
char *var_name(MathoMatic* mathomatic, long v);
int list_var(MathoMatic* mathomatic, long v, int lang_code);
int list_proc(MathoMatic* mathomatic, token_type *p1, int n, int export_flag);
char *list_equation(MathoMatic* mathomatic, int n, int export_flag);
char *list_expression(MathoMatic* mathomatic, token_type *p1, int n, int export_flag);
int list_string(MathoMatic* mathomatic, token_type *p1, int n, char *string, int export_flag);
int list_string_sub(MathoMatic* mathomatic, token_type *p1, int n, int outflag, char *string, int export_flag);
int int_expr(token_type *p1, int n);
int list_code_equation(int en, enum language_list language, int int_flag);
char *string_code_equation(int en, enum language_list language, int int_flag);
int list_code(token_type *equation, int *np, int outflag, char *string, enum language_list language, int int_flag);
char *flist_equation_string(int n);
int flist_equation(int n);
int list_code_equation(MathoMatic* mathomatic, int en, enum language_list language, int int_flag);
char *string_code_equation(MathoMatic* mathomatic, int en, enum language_list language, int int_flag);
int list_code(MathoMatic* mathomatic, token_type *equation, int *np, int outflag, char *string, enum language_list language, int int_flag);
char *flist_equation_string(MathoMatic* mathomatic, int n);
int flist_equation(MathoMatic* mathomatic, int n);
/* main.c */
void usage(FILE *fp);
int main(int argc, char **argv);
@ -208,97 +208,97 @@ void resizehandler(int sig);
void exit_program(int exit_value);
/* parse.c */
void str_tolower(char *cp);
void put_up_arrow(int cnt, char *cp);
int isvarchar(int ch);
void put_up_arrow(MathoMatic* mathomatic, int cnt, char *cp);
int isvarchar(MathoMatic* mathomatic, int ch);
int paren_increment(int ch);
int is_mathomatic_operator(int ch);
void binary_parenthesize(token_type *p1, int n, int i);
void handle_negate(token_type *equation, int *np);
void give_priority(token_type *equation, int *np);
char *parse_section(token_type *equation, int *np, char *cp, int allow_space);
char *parse_equation(int n, char *cp);
char *parse_expr(token_type *equation, int *np, char *cp, int allow_space);
char *parse_var(long *vp, char *cp);
void give_priority(MathoMatic* mathomatic, token_type *equation, int *np);
char *parse_section(MathoMatic* mathomatic, token_type *equation, int *np, char *cp, int allow_space);
char *parse_equation(MathoMatic* mathomatic, int n, char *cp);
char *parse_expr(MathoMatic* mathomatic, token_type *equation, int *np, char *cp, int allow_space);
char *parse_var(MathoMatic* mathomatic, long *vp, char *cp);
void remove_trailing_spaces(char *cp);
void set_error_level(char *cp);
void set_error_level(MathoMatic* mathomatic, char *cp);
int var_is_const(long v, double *dp);
int subst_constants(token_type *equation, int *np);
int my_strlcpy(char *dest, char *src, int n);
/* poly.c */
int poly_in_v_sub(token_type *p1, int n, long v, int allow_divides);
int poly_in_v(token_type *p1, int n, long v, int allow_divides);
int poly_factor(token_type *equation, int *np, int do_repeat);
int remove_factors(void);
int poly_gcd(token_type *larger, int llen, token_type *smaller, int slen, long v);
int poly2_gcd(token_type *larger, int llen, token_type *smaller, int slen, long v, int require_additive);
int is_integer_var(long v);
int is_integer_expr(token_type *p1, int n);
int mod_simp(token_type *equation, int *np);
int poly_gcd_simp(token_type *equation, int *np);
int div_remainder(token_type *equation, int *np, int poly_flag, int quick_flag);
int poly_div(token_type *d1, int len1, token_type *d2, int len2, long *vp);
int smart_div(token_type *d1, int len1, token_type *d2, int len2);
int basic_size(token_type *p1, int len);
int poly_in_v_sub(MathoMatic* mathomatic, token_type *p1, int n, long v, int allow_divides);
int poly_in_v(MathoMatic* mathomatic, token_type *p1, int n, long v, int allow_divides);
int poly_factor(MathoMatic* mathomatic, token_type *equation, int *np, int do_repeat);
int remove_factors(MathoMatic* mathomatic);
int poly_gcd(MathoMatic* mathomatic, token_type *larger, int llen, token_type *smaller, int slen, long v);
int poly2_gcd(MathoMatic* mathomatic, token_type *larger, int llen, token_type *smaller, int slen, long v, int require_additive);
int is_integer_var(MathoMatic* mathomatic, long v);
int is_integer_expr(MathoMatic* mathomatic, token_type *p1, int n);
int mod_simp(MathoMatic* mathomatic, token_type *equation, int *np);
int poly_gcd_simp(MathoMatic* mathomatic, token_type *equation, int *np);
int div_remainder(MathoMatic* mathomatic, token_type *equation, int *np, int poly_flag, int quick_flag);
int poly_div(MathoMatic* mathomatic, token_type *d1, int len1, token_type *d2, int len2, long *vp);
int smart_div(MathoMatic* mathomatic, token_type *d1, int len1, token_type *d2, int len2);
int basic_size(MathoMatic* mathomatic, token_type *p1, int len);
int get_term(token_type *p1, int n1, int count, int *tp1, int *lentp1);
void term_value(double *dp, token_type *p1, int n1, int loc);
int find_greatest_power(token_type *p1, int n1, long *vp1, double *pp1, int *tp1, int *lentp1, int *dcodep);
/* simplify.c */
void organize(token_type *equation, int *np);
void elim_loop(token_type *equation, int *np);
void simp_ssub(token_type *equation, int *np, long v, double d, int power_flag, int times_flag, int fc_level);
void simp_equation(int n);
void mid_simp_side(token_type *equation, int *np);
void mid_simp_equation(int n);
void simps_side(token_type *equation, int *np, int zsolve);
void simpv_side(token_type *equation, int *np, long v);
void simpv_equation(int n, long v);
int factor_imaginary(token_type *equation, int *np);
void factorv(token_type *equation, int *np, long v);
void calc_simp(token_type *equation, int *np);
void approximate(token_type *equation, int *np);
int simp_i(token_type *equation, int *np);
void simp_divide(token_type *equation, int *np);
void simp2_divide(token_type *equation, int *np, long v, int fc_level);
void simpb_side(token_type *equation, int *np, int uf_power_flag, int power_flag, int fc_level);
void simple_frac_side(token_type *equation, int *np);
void simpa_side(token_type *equation, int *np, int quick_flag, int frac_flag);
void simpa_repeat_side(token_type *equation, int *np, int quick_flag, int frac_flag);
void simpa_repeat(int n, int quick_flag, int frac_flag);
void simple_frac_repeat_side(token_type *equation, int *np);
int simp_loop(token_type *equation, int *np);
int simp_pp(token_type *equation, int *np);
int integer_root_simp(token_type *equation, int *np);
int simp_constant_power(token_type *equation, int *np);
int simp2_power(token_type *equation, int *np);
void organize(MathoMatic* mathomatic, token_type *equation, int *np);
void elim_loop(MathoMatic* mathomatic, token_type *equation, int *np);
void simp_ssub(MathoMatic* mathomatic, token_type *equation, int *np, long v, double d, int power_flag, int times_flag, int fc_level);
void simp_equation(MathoMatic* mathomatic, int n);
void mid_simp_side(MathoMatic* mathomatic, token_type *equation, int *np);
void mid_simp_equation(MathoMatic* mathomatic, int n);
void simps_side(MathoMatic* mathomatic, token_type *equation, int *np, int zsolve);
void simpv_side(MathoMatic* mathomatic, token_type *equation, int *np, long v);
void simpv_equation(MathoMatic* mathomatic, int n, long v);
int factor_imaginary(MathoMatic* mathomatic, token_type *equation, int *np);
void factorv(MathoMatic* mathomatic, token_type *equation, int *np, long v);
void calc_simp(MathoMatic* mathomatic, token_type *equation, int *np);
void approximate(MathoMatic* mathomatic, token_type *equation, int *np);
int simp_i(MathoMatic* mathomatic, token_type *equation, int *np);
void simp_divide(MathoMatic* mathomatic, token_type *equation, int *np);
void simp2_divide(MathoMatic* mathomatic, token_type *equation, int *np, long v, int fc_level);
void simpb_side(MathoMatic* mathomatic, token_type *equation, int *np, int uf_power_flag, int power_flag, int fc_level);
void simple_frac_side(MathoMatic* mathomatic, token_type *equation, int *np);
void simpa_side(MathoMatic* mathomatic, token_type *equation, int *np, int quick_flag, int frac_flag);
void simpa_repeat_side(MathoMatic* mathomatic, token_type *equation, int *np, int quick_flag, int frac_flag);
void simpa_repeat(MathoMatic* mathomatic, int n, int quick_flag, int frac_flag);
void simple_frac_repeat_side(MathoMatic* mathomatic, token_type *equation, int *np);
int simp_loop(MathoMatic* mathomatic, token_type *equation, int *np);
int simp_pp(MathoMatic* mathomatic, token_type *equation, int *np);
int integer_root_simp(MathoMatic* mathomatic, token_type *equation, int *np);
int simp_constant_power(MathoMatic* mathomatic, token_type *equation, int *np);
int simp2_power(MathoMatic* mathomatic, token_type *equation, int *np);
double fixed_fmod(double k1, double k2);
int combine_constants(token_type *equation, int *np, int iflag);
int calc(int *op1p, double *k1p, int op2, double k2);
int elim_k(token_type *equation, int *np);
int se_compare(token_type *p1, int n1, token_type *p2, int n2, int *diff_signp);
int elim_sign(token_type *equation, int *np);
int div_imaginary(token_type *equation, int *np);
int reorder(token_type *equation, int *np);
int rationalize(token_type *equation, int *np);
int combine_constants(MathoMatic* mathomatic, token_type *equation, int *np, int iflag);
int calc(MathoMatic* mathomatic, int *op1p, double *k1p, int op2, double k2);
int elim_k(MathoMatic* mathomatic, token_type *equation, int *np);
int se_compare(MathoMatic* mathomatic, token_type *p1, int n1, token_type *p2, int n2, int *diff_signp);
int elim_sign(MathoMatic* mathomatic, token_type *equation, int *np);
int div_imaginary(MathoMatic* mathomatic, token_type *equation, int *np);
int reorder(MathoMatic* mathomatic, token_type *equation, int *np);
int rationalize(MathoMatic* mathomatic, token_type *equation, int *np);
/* solve.c */
int solve_espace(int want, int have);
int solve_sub(token_type *wantp, int wantn, token_type *leftp, int *leftnp, token_type *rightp, int *rightnp);
int solve_espace(MathoMatic* mathomatic, int want, int have);
int solve_sub(MathoMatic* mathomatic, token_type *wantp, int wantn, token_type *leftp, int *leftnp, token_type *rightp, int *rightnp);
/* super.c */
void group_proc(token_type *equation, int *np);
int fractions_and_group(token_type *equation, int *np);
int make_fractions_and_group(int n);
int super_factor(token_type *equation, int *np, int start_flag);
void group_proc(MathoMatic* mathomatic, token_type *equation, int *np);
int fractions_and_group(MathoMatic* mathomatic, token_type *equation, int *np);
int make_fractions_and_group(MathoMatic* mathomatic, int n);
int super_factor(MathoMatic* mathomatic, token_type *equation, int *np, int start_flag);
/* unfactor.c */
int uf_tsimp(token_type *equation, int *np);
int uf_power(token_type *equation, int *np);
int uf_pplus(token_type *equation, int *np);
void uf_allpower(token_type *equation, int *np);
void uf_repeat(token_type *equation, int *np);
void uf_repeat_always(token_type *equation, int *np);
void uf_simp(token_type *equation, int *np);
void uf_simp_no_repeat(token_type *equation, int *np);
int ufactor(token_type *equation, int *np);
int uf_times(token_type *equation, int *np);
int sub_ufactor(token_type *equation, int *np, int ii);
int unsimp_power(token_type *equation, int *np);
void uf_neg_help(token_type *equation, int *np);
int patch_root_div(token_type *equation, int *np);
int uf_tsimp(MathoMatic* mathomatic, token_type *equation, int *np);
int uf_power(MathoMatic* mathomatic, token_type *equation, int *np);
int uf_pplus(MathoMatic* mathomatic, token_type *equation, int *np);
void uf_allpower(MathoMatic* mathomatic, token_type *equation, int *np);
void uf_repeat(MathoMatic* mathomatic, token_type *equation, int *np);
void uf_repeat_always(MathoMatic* mathomatic, token_type *equation, int *np);
void uf_simp(MathoMatic* mathomatic, token_type *equation, int *np);
void uf_simp_no_repeat(MathoMatic* mathomatic, token_type *equation, int *np);
int ufactor(MathoMatic* mathomatic, token_type *equation, int *np);
int uf_times(MathoMatic* mathomatic, token_type *equation, int *np);
int sub_ufactor(MathoMatic* mathomatic, token_type *equation, int *np, int ii);
int unsimp_power(MathoMatic* mathomatic, token_type *equation, int *np);
void uf_neg_help(token_type *equation, int *np, MathoMatic* mathomatic);
int patch_root_div(MathoMatic* mathomatic, token_type *equation, int *np);

1009
simplify.c

File diff suppressed because it is too large Load Diff

706
solve.c

File diff suppressed because it is too large Load Diff

256
super.c
View File

@ -24,15 +24,15 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#include "includes.h"
static int sf_recurse(token_type *equation, int *np, int loc, int level, int start_flag);
static int sf_sub(token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level, int start_flag);
static int sf_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, int start_flag);
static int sf_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level, int start_flag);
static void
group_recurse(equation, np, loc, level)
token_type *equation; /* equation side pointer */
int *np; /* pointer to length of equation side */
int loc; /* starting location within equation side */
int level; /* current level of parentheses within the sub-expression starting at "loc" */
group_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level)
//token_type *equation; /* equation side pointer */
//int *np; /* pointer to length of equation side */
//int loc; /* starting location within equation side */
//int level; /* current level of parentheses within the sub-expression starting at "loc" */
{
int i;
int len;
@ -42,7 +42,7 @@ int level; /* current level of parentheses within the sub-expression starting
for (i = loc; i < *np && equation[i].level >= level;) {
if (equation[i].level > level) {
group_recurse(equation, np, i, level + 1);
group_recurse(mathomatic, equation, np, i, level + 1);
i++;
for (; i < *np && equation[i].level > level; i += 2)
;
@ -69,9 +69,9 @@ int level; /* current level of parentheses within the sub-expression starting
edi = i;
continue;
}
blt(scratch, &equation[i], len * sizeof(token_type));
blt(mathomatic->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));
blt(&equation[di], mathomatic->scratch, len * sizeof(token_type));
edi += len;
i += len - 2;
} else {
@ -85,7 +85,7 @@ int level; /* current level of parentheses within the sub-expression starting
if (equation[i].level == level && equation[i].kind == OPERATOR) {
#if DEBUG
if (equation[i].token.operatr != DIVIDE) {
error_bug("Bug in group_recurse().");
error_bug(mathomatic, "Bug in group_recurse().");
}
#endif
equation[i].token.operatr = TIMES;
@ -101,11 +101,11 @@ int level; /* current level of parentheses within the sub-expression starting
* Not guaranteed to put the grouped divisors last, reorder() puts divisors last.
*/
void
group_proc(equation, np)
token_type *equation; /* equation side pointer */
int *np; /* pointer to length of equation side */
group_proc(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* equation side pointer */
//int *np; /* pointer to length of equation side */
{
group_recurse(equation, np, 0, 1);
group_recurse(mathomatic, equation, np, 0, 1);
}
/*
@ -117,17 +117,17 @@ int *np; /* pointer to length of equation side */
* Return true if any fractions were created.
*/
int
fractions_and_group(equation, np)
token_type *equation;
int *np;
fractions_and_group(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation;
//int *np;
{
int rv = false;
elim_loop(equation, np);
if (fractions_display) {
rv = make_fractions(equation, np);
elim_loop(mathomatic, equation, np);
if (mathomatic->fractions_display) {
rv = make_fractions(mathomatic, equation, np);
}
group_proc(equation, np);
group_proc(mathomatic, equation, np);
return rv;
}
@ -138,17 +138,17 @@ int *np;
* Return true if any fractions were created.
*/
int
make_fractions_and_group(n)
int n; /* equation space number */
make_fractions_and_group(MathoMatic* mathomatic, int n)
//int n; /* equation space number */
{
int rv = false;
if (empty_equation_space(n))
if (empty_equation_space(mathomatic, n))
return false;
if (fractions_and_group(lhs[n], &n_lhs[n]))
if (fractions_and_group(mathomatic, mathomatic->lhs[n], &mathomatic->n_lhs[n]))
rv = true;
if (n_rhs[n] > 0) {
if (fractions_and_group(rhs[n], &n_rhs[n]))
if (mathomatic->n_rhs[n] > 0) {
if (fractions_and_group(mathomatic, mathomatic->rhs[n], &mathomatic->n_rhs[n]))
rv = true;
}
return rv;
@ -184,23 +184,21 @@ int n; /* equation space number */
* Return true if the equation side was modified.
*/
int
super_factor(equation, np, start_flag)
token_type *equation; /* pointer to the beginning of the equation side to process */
int *np; /* pointer to the length of the equation side */
int start_flag;
super_factor(MathoMatic* mathomatic, token_type *equation, int *np, int start_flag)
//token_type *equation; /* pointer to the beginning of the equation side to process */
//int *np; /* pointer to the length of the equation side */
//int start_flag;
{
int rv;
group_proc(equation, np);
rv = sf_recurse(equation, np, 0, 1, start_flag);
organize(equation, np);
group_proc(mathomatic, equation, np);
rv = sf_recurse(mathomatic, equation, np, 0, 1, start_flag);
organize(mathomatic, equation, np);
return rv;
}
static int
sf_recurse(equation, np, loc, level, start_flag)
token_type *equation;
int *np, loc, level, start_flag;
sf_recurse(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int level, int start_flag)
{
int modified = false;
int i, j, k;
@ -218,7 +216,7 @@ int *np, loc, level, start_flag;
op = 0;
for (i = loc; i < *np && equation[i].level >= level;) {
if (equation[i].level > level) {
modified |= sf_recurse(equation, np, i, level + 1, start_flag);
modified |= sf_recurse(mathomatic, equation, np, i, level + 1, start_flag);
i++;
for (; i < *np && equation[i].level > level; i += 2)
;
@ -250,11 +248,11 @@ sf_again:
side_debug(0, &equation[i], len1);
side_debug(0, &equation[j], len2);
#endif
if (sf_sub(equation, np, loc, i, len1, j, len2, level + 1, start_flag)) {
if (sf_sub(mathomatic, equation, np, loc, i, len1, j, len2, level + 1, start_flag)) {
#if 0
int junk;
printf("start_flag = %d\n", start_flag);
debug_string(0, "super_factor() successful:");
debug_string(mathomatic, 0, "super_factor() successful:");
for (junk = 1; (loc + junk) < *np && equation[loc+junk].level > level; junk += 2)
;
side_debug(0, &equation[loc], junk);
@ -267,9 +265,7 @@ sf_again:
}
static int
sf_sub(equation, np, loc, i1, n1, i2, n2, level, start_flag)
token_type *equation;
int *np, loc, i1, n1, i2, n2, level, start_flag;
sf_sub(MathoMatic* mathomatic, token_type *equation, int *np, int loc, int i1, int n1, int i2, int n2, int level, int start_flag)
{
int i, j, k;
int b1, b2;
@ -339,30 +335,30 @@ int *np, loc, i1, n1, i2, n2, level, start_flag;
#endif
if (start_flag >= 2 && div_flag1 && div_flag2) {
#if DEBUG
debug_string(1, "Trying to find a polynomial GCD between 2 denominators in sf_sub():");
side_debug(1, &equation[b1], i - b1);
side_debug(1, &equation[b2], j - b2);
debug_string(mathomatic, 1, "Trying to find a polynomial GCD between 2 denominators in sf_sub():");
side_debug(mathomatic, 1, &equation[b1], i - b1);
side_debug(mathomatic, 1, &equation[b2], j - b2);
#endif
if ((rv = poly2_gcd(&equation[b1], i - b1, &equation[b2], j - b2, 0L, true)) > 0) {
p1 = tlhs;
np1 = n_tlhs;
p2 = trhs;
np2 = n_trhs;
if ((rv = poly2_gcd(mathomatic, &equation[b1], i - b1, &equation[b2], j - b2, 0L, true)) > 0) {
p1 = mathomatic->tlhs;
np1 = mathomatic->n_tlhs;
p2 = mathomatic->trhs;
np2 = mathomatic->n_trhs;
goto do_gcd_super;
}
if (rv == 0 && poly2_gcd(&equation[b2], j - b2, &equation[b1], i - b1, 0L, true) > 0) {
p1 = trhs;
np1 = n_trhs;
p2 = tlhs;
np2 = n_tlhs;
if (rv == 0 && poly2_gcd(mathomatic, &equation[b2], j - b2, &equation[b1], i - b1, 0L, true) > 0) {
p1 = mathomatic->trhs;
np1 = mathomatic->n_trhs;
p2 = mathomatic->tlhs;
np2 = mathomatic->n_tlhs;
goto do_gcd_super;
}
#if DEBUG
debug_string(1, "Done; polynomial GCD not found.");
debug_string(mathomatic, 1, "Done; polynomial GCD not found.");
#endif
}
if (n1 + n2 + (i - b1) + (j - b2) + 8 > n_tokens) {
error_huge();
if (n1 + n2 + (i - b1) + (j - b2) + 8 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
if (!div_flag1) {
for (k = i1; k < e1; k++)
@ -373,76 +369,76 @@ int *np, loc, i1, n1, i2, n2, level, start_flag;
equation[k].level++;
}
len = (b1 - i1) - 1;
blt(scratch, &equation[i1], len * sizeof(token_type));
blt(mathomatic->scratch, &equation[i1], len * sizeof(token_type));
if (op1 == MINUS) {
scratch[len].level = level;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = TIMES;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
scratch[len].level = level;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = -1.0;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = -1.0;
len++;
}
if (div_flag1) {
blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
blt(&mathomatic->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;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
blt(&scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
len += j - b2;
}
for (k = 0; k < len; k++)
scratch[k].level += 2;
scratch[len].level = level + 1;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = op2;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = op2;
len++;
k = len;
blt(&scratch[len], &equation[i2], (b2 - i2 - 1) * sizeof(token_type));
blt(&mathomatic->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));
blt(&mathomatic->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;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
len += i - b1;
}
for (; k < len; k++)
scratch[k].level += 2;
scratch[len].level = level;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = DIVIDE;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = DIVIDE;
len++;
k = len;
if (div_flag1) {
blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
blt(&mathomatic->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;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
}
if (div_flag2) {
blt(&scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b2], (j - b2) * sizeof(token_type));
len += j - b2;
}
for (; k < len; k++)
scratch[k].level++;
mathomatic->scratch[k].level++;
end_mess:
if (*np + len - n1 - (n2 + 1) > n_tokens) {
error_huge();
if (*np + len - n1 - (n2 + 1) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
if (op1 == MINUS) {
equation[i1-1].token.operatr = PLUS;
@ -451,16 +447,16 @@ end_mess:
*np -= n2 + 1;
blt(&equation[i1+len], &equation[e1], (*np - e1) * sizeof(token_type));
*np += len - n1;
blt(&equation[i1], scratch, len * sizeof(token_type));
blt(&equation[i1], mathomatic->scratch, len * sizeof(token_type));
return true;
do_gcd_super:
#if DEBUG
debug_string(1, "Found a polynomial GCD between 2 denominators in sf_sub().");
debug_string(mathomatic, 1, "Found a polynomial GCD between 2 denominators in sf_sub().");
#endif
if (5 - i1 + e1 + (2*np2) + b2 - i2 + e2 - j + np1 > n_tokens) {
error_huge();
if (5 - i1 + e1 + (2*np2) + b2 - i2 + e2 - j + np1 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
for (k = 0; k < np1; k++) {
p1[k].level += level;
@ -469,72 +465,72 @@ do_gcd_super:
p2[k].level += level;
}
len = (b1 - i1) - 1;
blt(scratch, &equation[i1], len * sizeof(token_type));
blt(mathomatic->scratch, &equation[i1], len * sizeof(token_type));
if (op1 == MINUS) {
scratch[len].level = level;
scratch[len].kind = OPERATOR;
scratch[len].token.operatr = TIMES;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
scratch[len].level = level;
scratch[len].kind = CONSTANT;
scratch[len].token.constant = -1.0;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = CONSTANT;
mathomatic->scratch[len].token.constant = -1.0;
len++;
}
/* if (div_flag1) { */
blt(&scratch[len], &equation[i], (e1 - i) * sizeof(token_type));
blt(&mathomatic->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;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
blt(&scratch[len], p2, np2 * sizeof(token_type));
blt(&mathomatic->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;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level + 1;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = op2;
len++;
k = len;
blt(&scratch[len], &equation[i2], (b2 - i2 - 1) * sizeof(token_type));
blt(&mathomatic->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));
blt(&mathomatic->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;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
blt(&scratch[len], p1, np1 * sizeof(token_type));
blt(&mathomatic->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;
mathomatic->scratch[k].level += 2;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = DIVIDE;
len++;
k = len;
/* if (div_flag1) { */
blt(&scratch[len], &equation[b1], (i - b1) * sizeof(token_type));
blt(&mathomatic->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;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
mathomatic->scratch[len].token.operatr = TIMES;
len++;
/* } */
/* if (div_flag2) { */
blt(&scratch[len], p2, np2 * sizeof(token_type));
blt(&mathomatic->scratch[len], p2, np2 * sizeof(token_type));
len += np2;
/* } */
for (; k < len; k++)
scratch[k].level++;
mathomatic->scratch[k].level++;
goto end_mess;
}

View File

@ -24,7 +24,7 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
#include "includes.h"
static int unf_sub(token_type *equation, int *np, int b1, int loc, int e1, int level, int ii);
static int unf_sub(MathoMatic* mathomatic, token_type *equation, int *np, int b1, int loc, int e1, int level, int ii);
/*
* Unfactor times and divide only (products of sums) and simplify.
@ -32,17 +32,15 @@ static int unf_sub(token_type *equation, int *np, int b1, int loc, int e1, int l
* Return true if equation side was unfactored.
*/
int
uf_tsimp(equation, np)
token_type *equation;
int *np;
uf_tsimp(MathoMatic* mathomatic, token_type *equation, int *np)
{
int rv;
rv = uf_times(equation, np);
simp_loop(equation, np);
while (uf_times(equation, np)) {
rv = uf_times(mathomatic, equation, np);
simp_loop(mathomatic, equation, np);
while (uf_times(mathomatic, equation, np)) {
rv = true;
simp_loop(equation, np);
simp_loop(mathomatic, equation, np);
}
return rv;
}
@ -54,17 +52,15 @@ int *np;
* Return true if equation side was unfactored.
*/
int
uf_power(equation, np)
token_type *equation;
int *np;
uf_power(MathoMatic* mathomatic, token_type *equation, int *np)
{
int count = -1;
do {
organize(equation, np);
organize(mathomatic, equation, np);
if (++count > 0)
break;
} while (sub_ufactor(equation, np, 2));
} while (sub_ufactor(mathomatic, equation, np, 2));
return count;
}
@ -75,17 +71,15 @@ int *np;
* Return true if equation side was unfactored.
*/
int
uf_pplus(equation, np)
token_type *equation;
int *np;
uf_pplus(MathoMatic* mathomatic, token_type *equation, int *np)
{
int count = -1;
do {
organize(equation, np);
organize(mathomatic, equation, np);
if (++count > 0)
break;
} while (sub_ufactor(equation, np, 4));
} while (sub_ufactor(mathomatic, equation, np, 4));
return count;
}
@ -94,13 +88,11 @@ int *np;
* Same as a call to uf_pplus() and uf_power(), only faster.
*/
void
uf_allpower(equation, np)
token_type *equation;
int *np;
uf_allpower(MathoMatic* mathomatic, token_type *equation, int *np)
{
do {
organize(equation, np);
} while (sub_ufactor(equation, np, 0));
organize(mathomatic, equation, np);
} while (sub_ufactor(mathomatic, equation, np, 0));
}
/*
@ -112,18 +104,16 @@ int *np;
* uf_times() is usually called after this to complete the expansion.
*/
void
uf_repeat(equation, np)
token_type *equation;
int *np;
uf_repeat(MathoMatic* mathomatic, token_type *equation, int *np)
{
int count = -1;
do {
organize(equation, np);
organize(mathomatic, equation, np);
if (++count > 0)
break;
} while (sub_ufactor(equation, np, 6));
patch_root_div(equation, np);
} while (sub_ufactor(mathomatic, equation, np, 6));
patch_root_div(mathomatic, equation, np);
}
/*
@ -132,31 +122,29 @@ int *np;
* Useful for removing all integer powers.
*/
void
uf_repeat_always(equation, np)
token_type *equation;
int *np;
uf_repeat_always(MathoMatic* mathomatic, token_type *equation, int *np)
{
int count = -1;
do {
organize(equation, np);
organize(mathomatic, equation, np);
if (++count > 0)
break;
} while (sub_ufactor(equation, np, 8));
} while (sub_ufactor(mathomatic, equation, np, 8));
}
/*
* Totally unfactor equation side and simplify.
*/
void
uf_simp(equation, np)
token_type *equation; /* pointer to beginning of equation side */
int *np; /* pointer to length of equation side */
uf_simp(MathoMatic* mathomatic, token_type *equation, int *np)
//token_type *equation; /* pointer to beginning of equation side */
//int *np; /* pointer to length of equation side */
{
uf_tsimp(equation, np);
uf_power(equation, np);
uf_repeat(equation, np);
uf_tsimp(equation, np);
uf_tsimp(mathomatic, equation, np);
uf_power(mathomatic, equation, np);
uf_repeat(mathomatic, equation, np);
uf_tsimp(mathomatic, equation, np);
}
/*
@ -164,27 +152,23 @@ int *np; /* pointer to length of equation side */
* Don't call uf_repeat().
*/
void
uf_simp_no_repeat(equation, np)
token_type *equation;
int *np;
uf_simp_no_repeat(MathoMatic* mathomatic, token_type *equation, int *np)
{
uf_power(equation, np);
uf_tsimp(equation, np);
uf_power(mathomatic, equation, np);
uf_tsimp(mathomatic, equation, np);
}
/*
* Totally unfactor equation side with no simplification.
*/
int
ufactor(equation, np)
token_type *equation;
int *np;
ufactor(MathoMatic* mathomatic, token_type *equation, int *np)
{
int rv;
uf_repeat(equation, np);
rv = uf_times(equation, np);
uf_allpower(equation, np);
uf_repeat(mathomatic, equation, np);
rv = uf_times(mathomatic, equation, np);
uf_allpower(mathomatic, equation, np);
return rv;
}
@ -192,9 +176,7 @@ int *np;
* Increase the level of numerators by 2, so that the divide operator is not unfactored.
*/
static void
no_divide(equation, np)
token_type *equation;
int *np;
no_divide(MathoMatic* mathomatic, token_type *equation, int *np)
{
int i, j;
int level;
@ -219,26 +201,24 @@ int *np;
* Return true if equation side was unfactored.
*/
int
uf_times(equation, np)
token_type *equation;
int *np;
uf_times(MathoMatic* mathomatic, token_type *equation, int *np)
{
int i;
int rv = false;
do {
organize(equation, np);
if (reorder(equation, np)) {
organize(equation, np);
organize(mathomatic, equation, np);
if (reorder(mathomatic, equation, np)) {
organize(mathomatic, equation, np);
}
group_proc(equation, np);
if (partial_flag) {
no_divide(equation, np);
group_proc(mathomatic, equation, np);
if (mathomatic->partial_flag) {
no_divide(mathomatic, equation, np);
}
i = sub_ufactor(equation, np, 1);
i = sub_ufactor(mathomatic, equation, np, 1);
rv |= i;
} while (i);
organize(equation, np);
organize(mathomatic, equation, np);
return rv;
}
@ -250,10 +230,7 @@ int *np;
* Return true if equation side was modified.
*/
int
sub_ufactor(equation, np, ii)
token_type *equation;
int *np;
int ii;
sub_ufactor(MathoMatic* mathomatic, token_type *equation, int *np, int ii)
{
int modified = false;
int i;
@ -283,7 +260,7 @@ int ii;
if (equation[e1].level < level)
break;
}
if (unf_sub(equation, np, b1, i, e1, level, ii)) {
if (unf_sub(mathomatic, equation, np, b1, i, e1, level, ii)) {
modified = true;
i = b1 - 1;
continue;
@ -293,11 +270,7 @@ int ii;
}
static int
unf_sub(equation, np, b1, loc, e1, level, ii)
token_type *equation;
int *np;
int b1, loc, e1, level;
int ii;
unf_sub(MathoMatic* mathomatic, token_type *equation, int *np, int b1, int loc, int e1, int level, int ii)
{
int i, j, k;
int b2, eb1, be1;
@ -332,24 +305,24 @@ int ii;
}
len = 0;
u_again:
if (len + (eb1 - b1) + (i - b2) + (e1 - be1) + 1 > n_tokens) {
error_huge();
if (len + (eb1 - b1) + (i - b2) + (e1 - be1) + 1 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&scratch[len], &equation[b1], (eb1 - b1) * sizeof(token_type));
blt(&mathomatic->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(token_type));
mathomatic->scratch[j].level++;
blt(&mathomatic->scratch[len], &equation[b2], (i - b2) * sizeof(token_type));
len += (i - b2);
blt(&scratch[len], &equation[be1], (e1 - be1) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[be1], (e1 - be1) * sizeof(token_type));
j = len;
len += (e1 - be1);
for (; j < len; j++)
scratch[j].level++;
mathomatic->scratch[j].level++;
if (i < be1) {
scratch[len] = equation[i];
scratch[len].level--;
mathomatic->scratch[len] = equation[i];
mathomatic->scratch[len].level--;
len++;
b2 = i + 1;
for (i += 2; i < be1; i += 2) {
@ -358,12 +331,12 @@ u_again:
}
goto u_again;
} else {
if (*np - (e1 - b1) + len > n_tokens) {
error_huge();
if (*np - (e1 - b1) + len > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(token_type));
*np += len - (e1 - b1);
blt(&equation[b1], scratch, len * sizeof(token_type));
blt(&equation[b1], mathomatic->scratch, len * sizeof(token_type));
return true;
}
}
@ -396,19 +369,19 @@ u_again:
b2 = b1;
len = 0;
u1_again:
if (len + (i - b2) + (e1 - loc) + 1 > n_tokens) {
error_huge();
if (len + (i - b2) + (e1 - loc) + 1 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&scratch[len], &equation[b2], (i - b2) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[b2], (i - b2) * sizeof(token_type));
len += (i - b2);
blt(&scratch[len], &equation[loc], (e1 - loc) * sizeof(token_type));
blt(&mathomatic->scratch[len], &equation[loc], (e1 - loc) * sizeof(token_type));
j = len;
len += (e1 - loc);
for (; j < len; j++)
scratch[j].level++;
mathomatic->scratch[j].level++;
if (i < loc) {
scratch[len] = equation[i];
scratch[len].level--;
mathomatic->scratch[len] = equation[i];
mathomatic->scratch[len].level--;
len++;
b2 = i + 1;
for (i += 2; i < loc; i += 2) {
@ -417,12 +390,12 @@ u1_again:
}
goto u1_again;
} else {
if (*np - (e1 - b1) + len > n_tokens) {
error_huge();
if (*np - (e1 - b1) + len > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(token_type));
*np += len - (e1 - b1);
blt(&equation[b1], scratch, len * sizeof(token_type));
blt(&equation[b1], mathomatic->scratch, len * sizeof(token_type));
return true;
}
}
@ -442,23 +415,23 @@ do_pplus:
b2 = loc + 1;
len = 0;
u2_again:
if (len + (loc - b1) + (i - b2) + 2 > n_tokens) {
error_huge();
if (len + (loc - b1) + (i - b2) + 2 > mathomatic->n_tokens) {
error_huge(mathomatic);
}
j = len;
blt(&scratch[len], &equation[b1], (loc + 1 - b1) * sizeof(token_type));
blt(&mathomatic->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(token_type));
mathomatic->scratch[j].level++;
blt(&mathomatic->scratch[len], &equation[b2], (i - b2) * sizeof(token_type));
len += (i - b2);
if (i < e1) {
scratch[len].level = level;
scratch[len].kind = OPERATOR;
mathomatic->scratch[len].level = level;
mathomatic->scratch[len].kind = OPERATOR;
if (equation[i].token.operatr == PLUS)
scratch[len].token.operatr = TIMES;
mathomatic->scratch[len].token.operatr = TIMES;
else
scratch[len].token.operatr = DIVIDE;
mathomatic->scratch[len].token.operatr = DIVIDE;
len++;
b2 = i + 1;
for (i += 2; i < e1; i += 2) {
@ -467,12 +440,12 @@ u2_again:
}
goto u2_again;
} else {
if (*np - (e1 - b1) + len > n_tokens) {
error_huge();
if (*np - (e1 - b1) + len > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[b1+len], &equation[e1], (*np - e1) * sizeof(token_type));
*np += len - (e1 - b1);
blt(&equation[b1], scratch, len * sizeof(token_type));
blt(&equation[b1], mathomatic->scratch, len * sizeof(token_type));
return true;
}
}
@ -497,7 +470,7 @@ do_repeat:
}
d1 = ceil(d1) - 1.0;
d2 = d1 * ((i - b1) + 1.0);
if ((*np + d2) > (n_tokens - 10)) {
if ((*np + d2) > (mathomatic->n_tokens - 10)) {
break; /* too big to expand, do nothing */
}
j = d1;
@ -526,9 +499,7 @@ do_repeat:
}
static int
usp_sub(equation, np, i)
token_type *equation;
int *np, i;
usp_sub(MathoMatic* mathomatic, token_type *equation, int *np, int i)
{
int level;
int j;
@ -544,8 +515,8 @@ int *np, i;
return false;
}
}
if ((*np + 2) > n_tokens) {
error_huge();
if ((*np + 2) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
equation[j].token.operatr = TIMES;
for (j = i + 1;; j++) {
@ -573,9 +544,7 @@ int *np, i;
* Return true if equation side is modified.
*/
int
unsimp_power(equation, np)
token_type *equation;
int *np;
unsimp_power(MathoMatic* mathomatic, token_type *equation, int *np)
{
int modified = false;
int i;
@ -585,7 +554,7 @@ int *np;
if (equation[i].level == equation[i+1].level
&& equation[i+1].kind == CONSTANT)
continue;
modified |= usp_sub(equation, np, i);
modified |= usp_sub(mathomatic, equation, np, i);
}
}
return modified;
@ -599,9 +568,7 @@ int *np;
* Return true if equation side is modified.
*/
int
unsimp2_power(equation, np)
token_type *equation;
int *np;
unsimp2_power(token_type *equation, int *np)
{
int modified = false;
int i;
@ -615,9 +582,7 @@ int *np;
}
int
usp2_sub(equation, np, i)
token_type *equation;
int *np, i;
usp2_sub(token_type *equation, int *np, int i)
{
int level;
int j, k;
@ -636,8 +601,8 @@ int *np, i;
return false;
}
}
if ((*np + 2) > n_tokens) {
error_huge();
if ((*np + 2) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
equation[j].token.operatr = TIMES;
j++;
@ -664,9 +629,7 @@ int *np, i;
* attempted to be negated, possibly getting rid of unneeded times -1.
*/
void
uf_neg_help(equation, np)
token_type *equation;
int *np;
uf_neg_help(token_type *equation, int *np, MathoMatic* mathomatic)
{
int i;
int level;
@ -678,8 +641,8 @@ int *np;
switch (equation[i+1].token.operatr) {
case TIMES:
case DIVIDE:
if ((*np + 2) > n_tokens) {
error_huge();
if ((*np + 2) > mathomatic->n_tokens) {
error_huge(mathomatic);
}
blt(&equation[i+3], &equation[i+1], (*np - (i + 1)) * sizeof(token_type));
*np += 2;
@ -707,9 +670,7 @@ int *np;
* Return true if equation side was modified.
*/
int
patch_root_div(equation, np)
token_type *equation;
int *np;
patch_root_div(MathoMatic* mathomatic, token_type *equation, int *np)
{
int i;
int level;
@ -724,14 +685,14 @@ int *np;
&& equation[i+3].level == level
&& equation[i+3].kind == CONSTANT) {
if (fmod(equation[i+1].token.constant, 1.0) == 0.0) {
if (!rationalize_denominators
if (!mathomatic->rationalize_denominators
|| !isfinite(equation[i+3].token.constant)
|| equation[i+3].token.constant <= 0.0
|| equation[i+3].token.constant >= 1.0) {
continue;
}
if (*np + 2 > n_tokens)
error_huge();
if (*np + 2 > mathomatic->n_tokens)
error_huge(mathomatic);
equation[i+3].token.constant -= 1.0;
blt(&equation[i+2], &equation[i], (*np - i) * sizeof(token_type));
*np += 2;