/* * Mathomatic integration routines and commands. * * Copyright (C) 1987-2012 George Gesslein II. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA The chief copyright holder can be contacted at gesslein@mathomatic.org, or 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 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 */ { int i; int level; for (i = 0; i < *np;) { level = equation[i].level; if (equation[i].kind == OPERATOR && equation[i].token.operatr == POWER) { for (i += 2; i < *np && equation[i].level >= level; i += 2) ; continue; } 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(); } level++; equation[i].level = level; i++; blt(&equation[i+2], &equation[i], (*np - i) * sizeof(token_type)); *np += 2; equation[i].level = level; equation[i].kind = OPERATOR; equation[i].token.operatr = POWER; i++; equation[i].level = level; equation[i].kind = CONSTANT; equation[i].token.constant = 1.0; } } i++; } } /* * Integration dispatch routine for polynomials. * Handles the level 1 additive operators, * sending each polynomial term to the specified integration function. * * 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 i, j; make_powers(equation, np, v); for (j = 0, i = 1;; i += 2) { if (i >= *np) { return((*func)(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)) { return false; } for (i = j + 1;; i += 2) { if (i >= *np) { return true; } if (equation[i].level == 1) { j = i + 1; break; } } } } return true; } /* * Do the actual integration of a polynomial term. * * 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 */ { int i, j, k; int len; int level, vlevel, mlevel; int count; int div_flag; level = min_level(&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) { count++; if (count > 1) return false; vlevel = equation[i].level; if (vlevel == level || vlevel == (level + 1)) { for (k = loc + 1; k < eloc; k += 2) { if (equation[k].level == level) { switch (equation[k].token.operatr) { case DIVIDE: case TIMES: continue; case POWER: if (k == (i + 1)) continue; default: return false; } } } if (vlevel == (level + 1)) { if ((i + 1) < eloc && equation[i+1].level == vlevel && equation[i+1].token.operatr == POWER) { continue; } } else { continue; } } return false; } } mlevel = level + 1; for (j = loc; j < eloc; j++) equation[j].level += 2; for (i = loc; i < eloc; i += 2) { if (equation[i].kind == VARIABLE && equation[i].token.variable == v) { div_flag = (i > loc && equation[i-1].token.operatr == DIVIDE); i++; if (i >= eloc || equation[i].token.operatr != POWER) return false; level = equation[i].level; i++; if (div_flag) { if (equation[i].level == level && equation[i].kind == CONSTANT && equation[i].token.constant == 1.0) return false; if (*np + 2 > n_tokens) error_huge(); for (j = i; j < eloc && equation[j].level >= level; j++) equation[j].level++; equation[i-3].token.operatr = TIMES; blt(&equation[i+2], &equation[i], (*np - i) * sizeof(token_type)); *np += 2; eloc += 2; equation[i].level = level + 1; equation[i].kind = CONSTANT; equation[i].token.constant = -1.0; equation[i+1].level = level + 1; equation[i+1].kind = OPERATOR; equation[i+1].token.operatr = TIMES; } for (j = i; j < eloc && equation[j].level >= level; j++) equation[j].level++; len = j - i; if (*np + len + 5 > n_tokens) error_huge(); blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type)); *np += 2; eloc += 2; len += 2; level++; equation[j].level = level; equation[j].kind = OPERATOR; equation[j].token.operatr = PLUS; j++; equation[j].level = level; equation[j].kind = CONSTANT; equation[j].token.constant = 1.0; blt(&equation[eloc+len+1], &equation[eloc], (*np - eloc) * sizeof(token_type)); *np += len + 1; equation[eloc].level = mlevel; equation[eloc].kind = OPERATOR; equation[eloc].token.operatr = DIVIDE; blt(&equation[eloc+1], &equation[i], len * sizeof(token_type)); return true; } } if (*np + 2 > n_tokens) { error_huge(); } blt(&equation[eloc+2], &equation[eloc], (*np - eloc) * sizeof(token_type)); *np += 2; equation[eloc].level = mlevel; equation[eloc].kind = OPERATOR; equation[eloc].token.operatr = TIMES; eloc++; equation[eloc].level = mlevel; equation[eloc].kind = VARIABLE; equation[eloc].token.variable = v; return true; } /* * The integrate command. */ int integrate_cmd(cp) char *cp; { int i, j; int len; long v = 0; token_type *source, *dest; int n1, n2, *nps, *np; int definite_flag = false, constant_flag = false, solved; double integrate_order = 1.0; char var_name_buf[MAX_VAR_LEN], *cp_start; long l1; cp_start = cp; if (current_not_defined()) { return false; } n_tlhs = 0; n_trhs = 0; solved = solved_equation(cur_equation); i = next_espace(); for (;; cp = skip_param(cp)) { if (strcmp_tospace(cp, "definite") == 0) { definite_flag = true; continue; } if (strcmp_tospace(cp, "constant") == 0) { constant_flag = true; continue; } break; } if (constant_flag && definite_flag) { error(_("Conflicting options given.")); return false; } if (n_rhs[cur_equation]) { if (!solved) { warning(_("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]; } else { source = lhs[cur_equation]; nps = &n_lhs[cur_equation]; dest = lhs[i]; np = &n_lhs[i]; } if (*cp) { if (isvarchar(*cp)) { cp = parse_var2(&v, cp); if (cp == NULL) { return false; } } if (*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.")); 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) { 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) { return false; } } show_usage = false; if (v == 0) { if (!prompt_var(&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); } else { fprintf(gfp, _("Integrating with respect to %s"), var_str); } if (integrate_order != 1.0) { fprintf(gfp, _(" %.*g times"), precision, integrate_order); } fprintf(gfp, _(" and simplifying...\n")); #endif partial_flag = false; uf_simp(source, nps); partial_flag = true; factorv(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.")); return false; } if (constant_flag) { if (n1 + 2 > n_tokens) { error_huge(); } for (j = 0; j < n1; j++) { dest[j].level++; } dest[n1].kind = OPERATOR; dest[n1].level = 1; dest[n1].token.operatr = PLUS; 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) { return false; } n1++; constant_var_number++; if (constant_var_number < 0) { constant_var_number = 1; } } simp_loop(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)) { return false; } } if (n_trhs == 0) { my_strlcpy(prompt_str, _("Enter upper bound: "), sizeof(prompt_str)); if (!get_expr(trhs, &n_trhs)) { return false; } } blt(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(); } for (j = 0; j < n1; j++) { dest[j].level++; } for (j = 0; j < n2; j++) { 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)); n1 += n2; } simpa_side(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'; } parse_var(&lhs[i][0].token.variable, var_str); } } cur_equation = i; return return_result(cur_equation); } /* * Do the actual Laplace transformation of a polynomial term. * * Return true if successful. */ static int laplace_sub(equation, np, loc, eloc, v) token_type *equation; int *np; int loc, eloc; long v; { int i, j, k; int len; int level, mlevel; mlevel = min_level(&equation[loc], eloc - loc) + 1; for (j = loc; j < eloc; j++) equation[j].level += 2; for (i = loc; i < eloc; i += 2) { if (equation[i].kind == VARIABLE && equation[i].token.variable == v) { i++; if (i >= eloc || equation[i].token.operatr != POWER) return false; level = equation[i].level; i++; for (j = i; j < eloc && equation[j].level >= level; j++) equation[j].level++; len = j - i; if (*np + len + 7 > n_tokens) error_huge(); blt(&equation[j+4], &equation[j], (*np - j) * sizeof(token_type)); *np += 4; eloc += 4; level++; equation[j].level = level; equation[j].kind = OPERATOR; equation[j].token.operatr = PLUS; j++; equation[j].level = level; equation[j].kind = CONSTANT; equation[j].token.constant = 1.0; j++; for (k = i; k < j; k++) equation[k].level++; equation[j].level = level; equation[j].kind = OPERATOR; equation[j].token.operatr = TIMES; j++; equation[j].level = level; equation[j].kind = CONSTANT; equation[j].token.constant = -1.0; blt(&equation[eloc+len+3], &equation[eloc], (*np - eloc) * sizeof(token_type)); *np += len + 3; k = eloc; equation[k].level = mlevel; equation[k].kind = OPERATOR; equation[k].token.operatr = TIMES; k++; blt(&equation[k], &equation[i], len * sizeof(token_type)); k += len; equation[k].level = mlevel + 1; equation[k].kind = OPERATOR; equation[k].token.operatr = FACTORIAL; k++; equation[k].level = mlevel + 1; equation[k].kind = CONSTANT; equation[k].token.constant = 1.0; return true; } } if (*np + 2 > n_tokens) { error_huge(); } blt(&equation[eloc+2], &equation[eloc], (*np - eloc) * sizeof(token_type)); *np += 2; equation[eloc].level = mlevel; equation[eloc].kind = OPERATOR; equation[eloc].token.operatr = DIVIDE; eloc++; equation[eloc].level = mlevel; equation[eloc].kind = VARIABLE; equation[eloc].token.variable = v; return true; } /* * Do the actual inverse Laplace transformation of a polynomial term. * * Return true if successful. */ static int inv_laplace_sub(equation, np, loc, eloc, v) token_type *equation; int *np; int loc, eloc; long v; { int i, j, k; int len; int level, mlevel; mlevel = min_level(&equation[loc], eloc - loc) + 1; for (j = loc; j < eloc; j++) equation[j].level += 2; for (i = loc; i < eloc; i += 2) { if (equation[i].kind == VARIABLE && equation[i].token.variable == v) { i++; if (i >= eloc || equation[i].token.operatr != POWER) return false; if ((i - 2) <= loc || equation[i-2].token.operatr != DIVIDE) return false; level = equation[i].level; i++; for (j = i; j < eloc && equation[j].level >= level; j++) equation[j].level++; len = j - i; if (*np + len + 7 > n_tokens) error_huge(); equation[i-3].token.operatr = TIMES; blt(&equation[j+2], &equation[j], (*np - j) * sizeof(token_type)); *np += 2; eloc += 2; len += 2; level++; equation[j].level = level; equation[j].kind = OPERATOR; equation[j].token.operatr = MINUS; j++; equation[j].level = level; equation[j].kind = CONSTANT; equation[j].token.constant = 1.0; blt(&equation[eloc+len+3], &equation[eloc], (*np - eloc) * sizeof(token_type)); *np += len + 3; k = eloc; equation[k].level = mlevel; equation[k].kind = OPERATOR; equation[k].token.operatr = DIVIDE; k++; blt(&equation[k], &equation[i], len * sizeof(token_type)); k += len; equation[k].level = mlevel + 1; equation[k].kind = OPERATOR; equation[k].token.operatr = FACTORIAL; k++; equation[k].level = mlevel + 1; equation[k].kind = CONSTANT; equation[k].token.constant = 1.0; return true; } } return false; } /* * The laplace command. */ int laplace_cmd(cp) char *cp; { int i; long v = 0; int inverse_flag, solved; token_type *source, *dest; int n1, *nps, *np; if (current_not_defined()) { return false; } solved = solved_equation(cur_equation); i = next_espace(); if (n_rhs[cur_equation]) { if (!solved) { warning(_("Not a solved equation.")); } #if !SILENT fprintf(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]; } else { source = lhs[cur_equation]; nps = &n_lhs[cur_equation]; dest = lhs[i]; np = &n_lhs[i]; } inverse_flag = (strcmp_tospace(cp, "inverse") == 0); if (inverse_flag) { cp = skip_param(cp); } if (*cp) { cp = parse_var2(&v, cp); if (cp == NULL) { return false; } if (extra_characters(cp)) { return false; } } show_usage = false; if (v == 0) { if (!prompt_var(&v)) { return false; } } partial_flag = false; uf_simp(source, nps); partial_flag = true; factorv(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.")); 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.")); return false; } } #if 1 simp_loop(dest, &n1); #else simpa_side(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]; } *np = n1; cur_equation = i; return return_result(cur_equation); } /* * Numerical integrate command. */ int nintegrate_cmd(cp) char *cp; { long v = 0; /* Mathomatic variable */ int i, j, k, i1, i2; int len; int level; int iterations = 1000; /* must be even */ int first_size = 0; int trap_flag, singularity, solved; token_type *ep, *source, *dest; int n1, *nps, *np; char *cp_start; cp_start = cp; if (current_not_defined()) { return false; } n_tlhs = 0; n_trhs = 0; solved = solved_equation(cur_equation); i = next_espace(); if (n_rhs[cur_equation]) { if (!solved) { warning(_("Not a solved equation.")); } source = rhs[cur_equation]; nps = &n_rhs[cur_equation]; dest = rhs[i]; np = &n_rhs[i]; } else { source = lhs[cur_equation]; nps = &n_lhs[cur_equation]; dest = lhs[i]; np = &n_lhs[i]; } trap_flag = (strncasecmp(cp, "trap", 4) == 0); if (trap_flag) { cp = skip_param(cp); } if (*cp) { cp = parse_var2(&v, cp); if (cp == NULL) { return false; } if (*cp) { iterations = decstrtol(cp, &cp); } if (iterations <= 0 || (iterations % 2) != 0) { error(_("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) { 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) { return false; } } show_usage = false; if (v == 0) { if (!prompt_var(&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); } else { fprintf(gfp, _("Numerically integrating with respect to %s...\n"), var_str); } #endif singularity = false; for (j = 1; j < *nps; j += 2) { if (source[j].token.operatr == DIVIDE) { for (k = j + 1; k < *nps && source[k].level >= source[j].level; k++) { if (source[k].kind == VARIABLE && source[k].token.variable == v) { singularity = true; } if (source[k].kind == OPERATOR && source[k].level == source[j].level) break; } } } if (singularity) { warning(_("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)) { 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.")); return false; } if (n_trhs == 0) { my_strlcpy(prompt_str, _("Enter upper bound: "), sizeof(prompt_str)); if (!get_expr(trhs, &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.")); return false; } if ((n_tlhs + n_trhs + 3) > n_tokens) { error_huge(); } #if !SILENT fprintf(gfp, _("Approximating the definite integral\n")); if (trap_flag) { fprintf(gfp, _("using the trapezoid method (%d partitions)...\n"), iterations); } else { fprintf(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; } 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; } 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; n1 = 1; for (j = 0; j <= iterations; j++) { if ((n1 + 1 + *nps) > n_tokens) error_huge(); for (k = 0; k < n1; k++) { dest[k].level++; } ep = &dest[n1]; ep->level = 1; ep->kind = OPERATOR; ep->token.operatr = PLUS; n1++; i1 = n1; blt(&dest[i1], source, *nps * sizeof(token_type)); n1 += *nps; for (k = i1; k < n1; k++) { dest[k].level += 2; } 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(); 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; level++; for (; i2 < k; i2++) { dest[i2].level += level; } ep = &dest[k]; ep->level = level; ep->kind = OPERATOR; ep->token.operatr = PLUS; ep++; level++; ep->level = level; ep->kind = CONSTANT; ep->token.constant = j; ep++; ep->level = level; ep->kind = OPERATOR; ep->token.operatr = TIMES; k += 3; i2 = k; blt(&dest[k], trhs, n_trhs * sizeof(token_type)); k += n_trhs; for (; i2 < k; i2++) { dest[i2].level += level; } k--; } } if (j > 0 && j < iterations) { if ((n1 + 2) > n_tokens) error_huge(); ep = &dest[n1]; ep->level = 2; ep->kind = OPERATOR; ep->token.operatr = TIMES; ep++; ep->level = 2; ep->kind = CONSTANT; if (trap_flag) { ep->token.constant = 2.0; } else { if ((j & 1) == 1) { ep->token.constant = 4.0; } else { ep->token.constant = 2.0; } } n1 += 2; } /* 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); if (exp_contains_infinity(dest, n1)) { error(_("Integration failed because result contains infinity or NaN (a singularity).")); return false; } /* detect an ever growing result: */ switch (j) { case 0: break; case 1: first_size = n1; if (first_size < 4) first_size = 4; break; default: if ((n1 / 8) >= first_size) { error(_("Result growing, integration failed.")); return false; } break; } } if ((n1 + 3 + n_trhs) > n_tokens) error_huge(); for (k = 0; k < n1; k++) dest[k].level++; ep = &dest[n1]; ep->level = 1; ep->kind = OPERATOR; ep->token.operatr = DIVIDE; ep++; ep->level = 1; ep->kind = CONSTANT; if (trap_flag) { ep->token.constant = 2.0; } else { ep->token.constant = 3.0; } ep++; ep->level = 1; ep->kind = OPERATOR; ep->token.operatr = TIMES; n1 += 3; k = n1; blt(&dest[k], trhs, n_trhs * sizeof(token_type)); n1 += n_trhs; for (; k < n1; k++) dest[k].level++; /* simplify and approximate the result even more: */ approximate_roots = true; do { elim_loop(dest, &n1); ufactor(dest, &n1); simp_divide(dest, &n1); } while (factor_imaginary(dest, &n1)); approximate_roots = false; #if !SILENT fprintf(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'; } parse_var(&lhs[i][0].token.variable, var_str); } } return return_result(i); }