mirror of
https://github.com/mfillpot/mathomatic.git
synced 2026-01-09 21:09:40 +00:00
Merge 938d83c21f into 6eb4cc1674
This commit is contained in:
commit
3d32a5d7e9
28
am.h
28
am.h
@ -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
2
blt.h
@ -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) {
|
||||
|
||||
125
complex.c
125
complex.c
@ -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
|
||||
|
||||
@ -27,8 +27,10 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
|
||||
#include "complex.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define epsilon 0.00000000000005 /* a good value for doubles */
|
||||
|
||||
@ -165,3 +167,5 @@ complexs a, b;
|
||||
complex_fixup(&r);
|
||||
return(r);
|
||||
}
|
||||
|
||||
#undef epsilon
|
||||
|
||||
521
diff.c
521
diff.c
@ -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);
|
||||
}
|
||||
|
||||
255
externs.h
255
externs.h
@ -22,115 +22,172 @@ 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 */
|
||||
|
||||
/* from poly.c*/
|
||||
/*
|
||||
* The following static expression storage areas are of non-standard size
|
||||
* and must only be used for temporary storage.
|
||||
* Most Mathomatic expression manipulation and simplification routines should not be used
|
||||
* on non-standard or constant size expression storage areas.
|
||||
* Standard size expression storage areas that may be
|
||||
* manipulated or simplified are the equation spaces, tlhs[], trhs[], and tes[] only.
|
||||
*/
|
||||
token_type divisor[DIVISOR_SIZE]; /* static expression storage areas for polynomial and smart division */
|
||||
int n_divisor; /* length of expression in divisor[] */
|
||||
token_type quotient[DIVISOR_SIZE];
|
||||
int n_quotient; /* length of expression in quotient[] */
|
||||
token_type gcd_divisor[DIVISOR_SIZE]; /* static expression storage area for polynomial GCD routine */
|
||||
int len_d; /* length of expression in gcd_divisor[] */
|
||||
|
||||
} MathoMatic;
|
||||
|
||||
//extern MathoMatic *mathomatic;
|
||||
|
||||
#endif /*MATHO_EXTERNS_H*/
|
||||
|
||||
424
factor.c
424
factor.c
@ -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;
|
||||
|
||||
211
factor_int.c
211
factor_int.c
@ -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
76
gcd.c
@ -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, "ient1);
|
||||
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
219
globals.c
@ -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;
|
||||
}
|
||||
|
||||
@ -24,8 +24,10 @@ George Gesslein II, P.O. Box 224, Lansing, NY 14882-0224 USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define _REENTRANT 1 /* Can be defined before including math.h for Mac OS X. Mac OS X allows a few re-entrant functions with this. iOS requires this commented out. */
|
||||
@ -113,7 +115,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 */
|
||||
|
||||
531
integrate.c
531
integrate.c
@ -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);
|
||||
}
|
||||
|
||||
@ -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
100
lib/lib.c
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
217
main.c
217
main.c
@ -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"));
|
||||
@ -110,9 +113,7 @@ FILE *fp;
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
#if NO_GETOPT_H /* if no getopt.h is available */
|
||||
extern char *optarg; /* set by getopt(3) */
|
||||
@ -134,45 +135,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 +191,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 +230,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 +261,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 +320,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 +341,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 +383,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 +392,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 +407,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,8 +424,7 @@ main_io_loop(void)
|
||||
* Return zero on success, or a non-zero unsettable signal number on error.
|
||||
*/
|
||||
int
|
||||
set_signals(time_out_seconds)
|
||||
unsigned int time_out_seconds;
|
||||
set_signals(unsigned int time_out_seconds)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
@ -462,11 +463,10 @@ unsigned int time_out_seconds;
|
||||
* Floating point exceptions are currently ignored.
|
||||
*/
|
||||
void
|
||||
fphandler(sig)
|
||||
int sig;
|
||||
fphandler(int sig)
|
||||
{
|
||||
#if DEBUG
|
||||
warning("Floating point exception.");
|
||||
warning(mathomatic, "Floating point exception.");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -476,11 +476,10 @@ int sig;
|
||||
* If it can't, repeated calls terminate this program.
|
||||
*/
|
||||
void
|
||||
inthandler(sig)
|
||||
int sig;
|
||||
inthandler(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 */
|
||||
@ -501,11 +500,10 @@ int sig;
|
||||
* Alarm signal handler.
|
||||
*/
|
||||
void
|
||||
alarmhandler(sig)
|
||||
int sig;
|
||||
alarmhandler(int sig)
|
||||
{
|
||||
printf(_("\nTimeout, quitting...\n"));
|
||||
exit_program(1);
|
||||
exit_program(mathomatic, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -513,8 +511,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 +521,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 +532,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 +552,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
|
||||
|
||||
120
mk-mathomatic-amalgamation.lua
Normal file
120
mk-mathomatic-amalgamation.lua
Normal file
@ -0,0 +1,120 @@
|
||||
local base_dir = "./";
|
||||
local includes_base = {"lib/"}
|
||||
local sq_sources = [==[
|
||||
globals.c
|
||||
am.c
|
||||
solve.c
|
||||
help.c
|
||||
parse.c
|
||||
cmds.c
|
||||
simplify.c
|
||||
factor.c
|
||||
super.c
|
||||
unfactor.c
|
||||
poly.c
|
||||
diff.c
|
||||
integrate.c
|
||||
complex.c
|
||||
complex_lib.c
|
||||
list.c
|
||||
gcd.c
|
||||
factor_int.c
|
||||
main.c
|
||||
]==];
|
||||
|
||||
local included = {};
|
||||
local inc_sys = {};
|
||||
local inc_sys_count = 0;
|
||||
local out = io.stdout
|
||||
|
||||
function CopyWithInline(prefix, filename)
|
||||
if included[filename] then return end
|
||||
included[filename] = true
|
||||
print('//--Start of', filename);
|
||||
--if(filename:match("luac?.c"))
|
||||
local inp = io.open(prefix .. filename, "r")
|
||||
if not inp then
|
||||
for idx in ipairs(includes_base) do
|
||||
local sdir = includes_base[idx]
|
||||
local fn = prefix .. sdir .. filename
|
||||
--print(fn)
|
||||
inp = io.open(fn, "r")
|
||||
if inp then break end
|
||||
end
|
||||
end
|
||||
if not inp then
|
||||
if filename == "fzn_picat_sat_bc.h" then
|
||||
print('//--End of', filename);
|
||||
end
|
||||
else
|
||||
assert(inp)
|
||||
for line in inp:lines() do
|
||||
if line:match('#define LUA_USE_READLINE') then
|
||||
out:write("//" .. line .. "\n")
|
||||
else
|
||||
local inc = line:match('#include%s+(["<].-)[">]')
|
||||
if inc then
|
||||
out:write("//" .. line .. "\n")
|
||||
if inc:sub(1,1) == '"' or inc:match('[<"]sq') then
|
||||
CopyWithInline(prefix, inc:sub(2))
|
||||
else
|
||||
local fn = inc:sub(2)
|
||||
if inc_sys[fn] == null then
|
||||
inc_sys_count = inc_sys_count +1
|
||||
inc_sys[fn] = inc_sys_count
|
||||
end
|
||||
end
|
||||
else
|
||||
out:write(line .. "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
print('//--End of', filename);
|
||||
end
|
||||
end
|
||||
|
||||
print([==[
|
||||
#ifdef WITH_COSMOPOLITAN
|
||||
|
||||
STATIC_STACK_SIZE(0x400000);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __COSMOPOLITAN__
|
||||
//gcc -Wall -DUNIX -DVERSION=\"16.0.5\" -o mathomatic mathomatic-am.c -lm
|
||||
#include <sys/resource.h> //7
|
||||
#include <readline/history.h> //21
|
||||
#include <unistd.h> //3
|
||||
#include <limits.h> //8
|
||||
#include <setjmp.h> //11
|
||||
#include <getopt.h> //27
|
||||
//#include <wincon.h> //26
|
||||
#include <readline/readline.h> //20
|
||||
#include <math.h> //10
|
||||
#include <editline.h> //22
|
||||
#include <string.h> //13
|
||||
//#include <windows.h> //25
|
||||
#include <float.h> //9
|
||||
#include <libgen.h> //4
|
||||
#include <termios.h> //24
|
||||
#include <libintl.h> //16
|
||||
#include <term.h> //19
|
||||
#include <curses.h> //18
|
||||
#include <locale.h> //17
|
||||
#include <ctype.h> //12
|
||||
#include <stdlib.h> //2
|
||||
#include <sys/ioctl.h> //23
|
||||
#include <errno.h> //14
|
||||
#include <signal.h> //15
|
||||
#include <stdio.h> //1
|
||||
//#include <ieeefp.h> //5
|
||||
#include <sys/time.h> //6
|
||||
|
||||
#endif
|
||||
]==])
|
||||
|
||||
local prefix = base_dir; local src_files = sq_sources;
|
||||
for filename in src_files:gmatch('([^\n]+)') do
|
||||
CopyWithInline(prefix, filename);
|
||||
end
|
||||
--for k, v in pairs(inc_sys) do print("#include <" .. k .. "> //" .. v ) end
|
||||
16
mk-mathomatic.sh
Executable file
16
mk-mathomatic.sh
Executable file
@ -0,0 +1,16 @@
|
||||
# run gcc compiler in freestanding mode
|
||||
gcc -g -Os -static -fno-pie -no-pie -nostdlib -nostdinc \
|
||||
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs \
|
||||
-o mathomatic.com.dbg mathomatic-am.c \
|
||||
-DUNIX -DVERSION=\"16.0.5\" \
|
||||
-DWITH_COSMOPOLITAN \
|
||||
-Wl,--gc-sections -fuse-ld=bfd -Wl,--gc-sections \
|
||||
-Wl,-T,ape.lds -include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
|
||||
objcopy -S -O binary mathomatic.com.dbg mathomatic.com
|
||||
|
||||
|
||||
# NOTE: scp it to windows/mac/etc. *before* you run it!
|
||||
# ~40kb static binary (can be ~16kb w/ MODE=tiny)
|
||||
./ape.elf ./mathomatic.com
|
||||
# -DSTACK_FRAME_UNLIMITED \
|
||||
# -fno-gcse -ffunction-sections -fdata-sections \
|
||||
198
parse.c
198
parse.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
458
proto.h
458
proto.h
@ -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, const 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
1009
simplify.c
File diff suppressed because it is too large
Load Diff
256
super.c
256
super.c
@ -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;
|
||||
}
|
||||
|
||||
239
unfactor.c
239
unfactor.c
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user