Sindbad~EG File Manager
/* M. Beeson */
/* code for determining which of Mathpert's command menus to display */
/* actual text of the menus is in mtext.c */
/* This is a pure ANSI file, it does not involve interface code */
/*
9.16.90 original date
3.26.99 last modified
2.27.00 added series_convergence2
9.5.04 changed i+i to i+1 at line 544
*/
#define AUTOMODE_DLL
#include <string.h>
#include "globals.h"
#include "tdefn.h"
#include "probtype.h"
#include "calc.h"
#include "operator.h"
#include "mtext.h"
#include "cmdmenus.h"
#include "order.h" /* numerical */
#include "pvalaux.h" /* contains_sqrt */
#include "userfunc.h" /* nuserfunctions() */
#include "mathmode.h" /* get_currenttopic */
#include "menusize.h"
#include "pvalaux.h" /* isinteger */
#define GRAPHMODE 2
/*________________________________________________________________*/
static menu menus[MAXMENUS]; /* MAXMENUS is #-defined in mtext.h */
static int trigfunction(unsigned);
static int hyper_function(unsigned);
static int has_compound_fractions(term t);
static int more_important(unsigned,unsigned);
static unsigned hpf(term);
static void menus_needed_aux(int,term,int,int,int,int);
/*____________________________________________________________________*/
MEXPORT_AUTOMODE menu * get_menus(void)
/* return base of menus array */
{ return menus;
}
/*_____________________________________________________________________*/
MEXPORT_AUTOMODE void setup_menus(void)
/* initialize menus[] array */
/* assumes menutext[] is already set up */
{ int i,q;
for(i=0;i<MAXMENUS; i++)
{ menusize(i,&q); /* get width and number of items of menu i */
menus[i].nitems =q;
menus[i].text_visible = 0;
menus[i].kind =2; /* expect string array at menus[i].text */
menus[i].needed = 0;
menus[i].item = 1;
menus[i].text = (char *) cmdmenu(i); /* cmdmenu(i) is const */
if(i==definite_integration || i == fundamental_theorem || i == oddandeven)
menus[i].item_height = 3;
else
menus[i].item_height = 1;
}
}
/*_____________________________________________________________________*/
MEXPORT_AUTOMODE void menus_needed(int problemtype, term p)
/* Determine, using problemtype and p, which is passed
as p = history[currentline] in most cases, but not
always (see below).
whether menus[i] is needed or not.
Mark menus[i].needed 1 if it is needed, 0 if it is not.
Does not necessarily mark menus[currentmenu] as needed.
Cases in which p is not history[currentline] include:
(1) when there is a selected equation, so that the
other equations are invisible and irrelevant.
(2) when the last line (or lines) was (were) generated
by a 'specialop', so that the previous line should be used,
as when evaluating a term to numerical values for various n.
*/
{ int i;
int currenttopic;
for(i=0;i<MAXMENUS;i++)
menus[i].needed = 0; /* erase old values */
menus[get_complex() ? complex_arithmetic : numerical_calculation1].needed = 1;
menus[numerical_calculation2].needed = 1;
menus[functions_menu].needed = (nuserfunctions() ? 1: 0); /* throw it in iff there are function definitions */
if(problemtype >=200) /* doing calculus */
menus[simplify_calculus].needed = 1;
else
menus[simplify].needed = 1;
switch(problemtype)
{ case FACTOR:
menus[factoring].needed = 1;
if(get_complex())
menus[complex_numbers].needed = 1; /* e.g. for a^2+b^2=(a-bi)(a+bi) */
break;
case MINMAX:
menus[minima_and_maxima].needed = 1;
break;
case RELATED_RATES:
menus[related_rates].needed = 1;
break;
case IMPLICIT_DIFF:
menus[implicit_diff].needed =1 ;
break;
case TRIG_IDENTITY:
menus[verify_identities].needed = 1;
break;
case SOLVE_EQUATION:
currenttopic = get_currenttopic();
menus[solve_equations].needed = 1;
menus[numerical_equations].needed = 1;
if(get_complex())
menus[complex_numbers].needed = 1;
if(currenttopic == _complex_cubics ||
currenttopic == _cubic_one_root
)
menus[cubic_equations].needed = 1;
break;
case LINEAR_EQUATIONS:
menus[cramers_rule].needed = 1;
menus[several_linear_equations].needed = 1;
menus[linear_equations_by_substitution].needed = 1;
menus[matrix_methods].needed = 1;
break;
case INTEGRATION:
menus[basic_integration].needed = 1;
menus[trig_integration].needed = 1;
if(status(intsub) > LEARNING)
menus[trig_integration2].needed = 1;
menus[integrate_exp].needed = 1;
menus[integrate_by_substitution].needed = 1;
menus[integrate_by_parts].needed = 1;
break;
case COMPLEX_NUMBERS:
menus[complex_numbers].needed = 1;
menus[complex_polar_form].needed = 1;
break;
case LIMITS: /* fall-through */
case LHOPITAL:
case DIFFERENTIATE_FROM_DEFN:
menus[limits].needed = 1;
menus[special_limits].needed = 1;
if(contains(p,SINH) || contains(p,COSH) || contains(p,TANH))
menus[hyper_limits].needed = 1;
menus[advanced_limits].needed = 1;
menus[limits_of_quotients].needed = 1;
break;
case INDUCTION:
menus[prove_by_induction].needed = 1;
break;
}
/* Now traverse the term p and throw in menus corresponding to the
functors encountered */
menus_needed_aux(problemtype,p,0,0,0,0);
}
/*______________________________________________________________*/
static void menus_needed_aux(int problemtype, term p, int sumflag, int fractflag,int ineqflag,int intflag)
/* traverse the term p and throw in menus needed as indicated by the
functors encountered */
/* sumflag means there is a sum somewhere above this point, that
is p is a descendant node of a sum;
fractflag means there is a fraction somewhere above this point;
ineqflag means there's an inequality somewhere above this point;
ineqflag = 1 means strict, ineqflag = 2 means nonstrict inequality;
intflag = 1 means inside an integral
*/
{ unsigned f = FUNCTOR(p);
unsigned g;
term u;
int i,j,kind;
if(equals(p,complexi))
{ menus[complex_numbers].needed = 1;
menus[complex_polar_form].needed = 1;
return;
}
if(ATOMIC(p))
{ if(f==INFINITY)
{ menus[infinities].needed = 1;
menus[more_infinities].needed = 1;
}
return;
}
switch(f)
{ case '+':
menus[simplify_sums].needed = 1;
break;
case '*':
menus[simplify_products].needed = 1;
if(sumflag)
{ menus[advanced_factoring].needed = 1; /* as in 1 -x^2y^2 */
/* and also as in x + x cos x + 1 + cos x, where we need
factorbygrouping */
menus[factoring].needed = 1;
menus[expand_menu].needed = 1;
}
break;
case '/':
menus[fractions].needed = 1;
menus[signed_fractions].needed = 1;
if(fractflag)
menus[compound_fractions].needed = 1;
if(sumflag)
menus[common_denominators].needed = 1;
if(ZERO(ARG(1,p)))
menus[zero_denom].needed = 1;
break;
case ROOT:
menus[nth_roots].needed = 1;
menus[roots_and_fractions].needed = 1;
menus[fractional_exponents].needed = 1;
if(NEGATIVE(ARG(0,p)))
menus[complex_numbers].needed = 1;
if(ineqflag)
menus[ineqflag==1 ? root_ineq1 : root_ineq2].needed = 1;
break;
case SQRT:
menus[square_roots].needed = 1;
menus[advanced_square_roots].needed = 1;
menus[fractional_exponents].needed = 1;
if(fractflag || !numerical(ARG(0,p)))
menus[advanced_square_roots].needed = 1;
if(NEGATIVE(ARG(0,p)))
menus[complex_numbers].needed = 1;
if(ineqflag)
menus[ineqflag==1 ? root_ineq1 : root_ineq2].needed = 1;
if(intflag && contains(ARG(0,p),'^'))
menus[trig_substitutions].needed = 1;
break;
case '^':
menus[exponents].needed = 1;
menus[expand_powers].needed = 1;
menus[negative_exponents].needed = 1;
g = FUNCTOR(ARG(0,p));
if(g==SIN || g == COS || g == TAN || g == SEC)
{ menus[half_angle_identities].needed = 1;
menus[trig_squares].needed = 1;
}
if(g == CSC || g == COT)
{ menus[half_angle_identities].needed = 1;
menus[csc_and_cot_identities].needed = 1;
}
u = ARG(1,p);
if(equals(u,two))
menus[simplify_products].needed = 1; /* for (a+b)^2=a^2+2ab+b^2 */
if(FRACTION(u) || (NEGATIVE(u) && FRACTION(ARG(0,u))) )
menus[fractional_exponents].needed = 1;
if(ineqflag)
menus[ineqflag==1 ? root_ineq1 : root_ineq2].needed = 1;
if(intflag && contains(ARG(0,p),'^') && contains(ARG(1,p),'/'))
/* example integrand: (1+x^2)^(3/2) */
menus[trig_substitutions].needed = 1;
if( ( !constant(ARG(1,p)) ||
iscomplex(ARG(1,p))
) &&
( !isinteger(ARG(1,p)) && /* e.g. x^a */
!(NEGATIVE(ARG(1,p)) && isinteger(ARG(0,ARG(1,p))))
/* don't show these menus on x^n, x^(2n), x^(-3), x^(-1/3) */
)
)
{ menus[natural_logarithms].needed = 1;
menus[logarithms_base_e].needed = 1;
menus[change_base].needed = 1;
}
/* so we can get a^b = e^(b ln a) */
if(sumflag)
menus[factoring].needed = 1;
if(sumflag && !equals(ARG(1,p),two))
/* a power other than 2 inside a sum */
{ menus[advanced_factoring].needed = 1;
menus[factor_expansion].needed = 1;
}
if(fractflag && sumflag) /* example: 1-1/x^2 */
menus[advanced_factoring].needed = 1;
if(equals(ARG(0,p),eulere) && iscomplex(p))
menus[complex_functions].needed = 1;
break;
case ABS:
menus[absolute_value].needed = 1;
if(ineqflag)
{ menus[absolute_value_ineq1].needed = 1;
menus[absolute_value_ineq2].needed = 1;
}
if(problemtype==INTEGRATION && contains2(p,INTEGRAL,2))
/* sg_function is used only for indefinite integrals */
{ menus[sg_function1].needed = 1;
menus[sg_function2].needed = 1;
}
break;
case LOG:
menus[logarithms].needed = 1;
menus[logarithms_base10].needed = 1;
menus[change_base].needed = 1;
break;
case LN:
menus[natural_logarithms].needed = 1;
menus[logarithms_base_e].needed = 1;
menus[change_base].needed = 1;
if(iscomplex(ARG(0,p)))
{ menus[complex_functions].needed = 1;
}
break;
case LOGB:
menus[logs_to_any_base].needed = 1;
menus[change_base].needed = 1;
break;
case SG:
menus[sg_function1].needed = 1;
menus[sg_function2].needed = 1;
break;
case BESSELJ: /* fall-through */
case BESSELK:
case BESSELY:
case BESSELI:
menus[bessel_functions].needed = 1;
break;
case ATANH:
case ACOSH:
case ASECH:
case ACSCH:
case ACOTH:
case ASINH:
menus[inverse_hyperbolic].needed = 1;
break;
case MATRIX:
menus[advanced_matrix_methods].needed = 1;
break;
case PR: /* fall-through */
case DIFF:
menus[derivatives].needed = 1; /* derivatives */
menus[polynomial_derivs].needed = 1;
g = FUNCTOR(ARG(0,p));
if(g == INTEGRAL)
menus[fundamental_theorem].needed = 1;
if(g == SIN || g == COS || g == TAN || g == COT || g==SEC || g==CSC)
menus[dif_trig].needed =1;
else if( g == LOG || g == LOGB || g == LN)
menus[dif_explog].needed = 1;
else if( g == ACOS || g == ASIN || g == ACOT || g == ATAN || g == ACSC || g == ASEC)
menus[dif_inversetrig].needed = 1;
else if( g == SINH || g == COSH || g == TANH || g == SECH || g == COTH || g == CSCH)
menus[dif_hyperbolic].needed = 1;
else if( g == ACOSH || g == ASINH || g == ACOTH || g == ATANH || g == ACSCH || g == ASECH)
menus[dif_inversehyperbolic].needed = 1;
if(g == '/' && (FUNCTOR(ARG(0,ARG(0,p)))=='*' || FUNCTOR(ARG(1,ARG(0,p)))=='*'))
menus[dif_explog].needed = 1; /* logarithmic differentiation */
if(g == '*' && ARITY(ARG(0,p)) > 2)
menus[dif_explog].needed = 1; /* logarithmic differentiation */
if( g == '^' && ! OBJECT(ARG(1,ARG(0,p)))) /* exponent not a number */
{ menus[dif_explog].needed = 1; /* differentiate u� = e^(n ln u) */
menus[chain_rule].needed = 1; /* chain rule */
}
if( g == '^' && ARITY(p)==2 && !equals(ARG(0,ARG(0,p)),ARG(1,p)))
{ menus[chain_rule].needed = 1; /* d/dx y^n */
}
if(ARITY(p) == 2)
/* maybe chain rule is needed */
{ term u = ARG(0,p);
if(ARITY(u)==1 && !equals(ARG(0,u),ARG(1,p)))
menus[chain_rule].needed = 1;
}
break;
}
kind = trigfunction(f); /* 1 for trig function, -1 for arctrig, 2 for DEG */
if(kind)
{ menus[evaluate_trig_function].needed = 1;
menus[basic_trig].needed = 1; /* basic trig */
menus[trig_reciprocals].needed = 1;
menus[trig_squares].needed = 1;
if(get_complex())
menus[complex_functions].needed = 1;
if(SOLVETYPE(problemtype))
menus[inverse_trig_functions].needed = 1;
if(ineqflag)
menus[trig_ineq].needed = 1;
if(! ATOMIC(ARG(0,p)))
{ menus[trig_sum].needed = 1; /* trig sum or double angle */
menus[double_angle].needed = 1;
menus[product_and_factor_identities].needed = 1;
if(contains(ARG(0,p),DEG))
menus[complementary_degrees].needed = 1;
else
menus[complementary_trig].needed = 1;
menus[trig_periodic].needed = 1;
menus[trig_odd_and_even].needed = 1;
}
if(iscomplex(ARG(0,p)))
{ menus[complex_functions].needed = 1;
}
if(FUNCTOR(ARG(0,p)) == '/')
{ menus[half_angle_identities].needed = 1;
}
if(intflag)
menus[trig_integration].needed = 1;
if(kind==1 && !ATOMIC(ARG(0,p)))
{ g = FUNCTOR(ARG(0,p));
if(trigfunction(g)== -1) /* e.g. tan(arccos x) */
menus[invsimp].needed = 1;
}
}
if( f == ASIN || f == ATAN || f == ACOS || f == ACOT || f == ACSC || f == ASEC)
{ menus[inverse_trig_functions].needed = 1;
menus[adding_arctrig_functions].needed = 1;
}
if(problemtype==SOLVE_EQUATION && f == '^' && iseven(ARG(1,p)))
{ menus[quadratic_equations].needed = 1;
}
if( f == '=' && problemtype != TRIG_IDENTITY && problemtype != LINEAR_EQUATIONS)
{ menus[solve_equations].needed = 1;
}
if( f == '=' && problemtype == DIFFERENTIATE)
{ menus[higher_derivatives].needed = 1;
}
if( f == OR && FUNCTOR(ARG(0,p)) == '=' )
{ menus[advanced_equations].needed = 1;
menus[numerical_equations].needed = 1;
}
if( problemtype==SOLVE_EQUATION &&
f != '+' && f != '*' && f != '-' && f != '^' && f != '='
)
{ menus[advanced_equations].needed = 1;
menus[logarithmic_equations].needed = 1;
menus[numerical_equations].needed = 1;
}
if( problemtype==SOLVE_EQUATION && f == '^' && !equals(ARG(1,p),two))
{ menus[advanced_equations].needed = 1;
menus[logarithmic_equations].needed = 1;
menus[numerical_equations].needed = 1;
}
if( problemtype==SOLVE_EQUATION && trigfunction(f))
{ menus[solve_by_30_60_90].needed = 1;
menus[solve_by_45_45_90].needed = 1;
menus[zeroes_of_trig_functions].needed = 1;
}
if( f == INTEGRAL)
{ if(IMPROPER(p))
menus[improper_integrals].needed = 1;
menus[integrate_by_substitution].needed = 1;
menus[integrate_by_parts].needed = 1;
if(FUNCTOR(ARG(0,p)) == DIFF)
menus[fundamental_theorem].needed = 1;
menus_needed_aux(problemtype,ARG(0,p),sumflag,1,ineqflag,1);
}
if( (f == INTEGRAL && ARITY(p) == 4) || f == EVAL)
{ term a = ARG(2,p);
term b = ARG(3,p);
if( (NEGATIVE(a) && equals(ARG(0,a),b)) ||
(NEGATIVE(b) && equals(ARG(0,b),a))
)
menus[oddandeven].needed = 1;
menus[definite_integration].needed = 1;
}
if( f == INTEGRAL )
{ term u = ARG(0,p);
unsigned h = FUNCTOR(u);
if(ACOS <= h && h <= ATAN && equals(ARG(0,u),ARG(1,p)))
menus[integrate_arctrig].needed = 1;
}
if( hyper_function(f))
{ menus[hyperbolic_functions].needed = 1;
if((f != SINH && f != COSH) || !ATOMIC(ARG(0,p)))
menus[more_hyperbolic].needed = 1;
}
if( hyper_function(f) && intflag)
{ menus[integrate_hyperbolic].needed = 1;
}
if( f == LIMIT)
{ term u = ARITY(p)==2 ? ARG(1,p): ARG(2,p); /* the limitand */
unsigned g = FUNCTOR(u);
term a = ARG(1,ARG(0,p)); /* limit as x->a */
term x = ARG(0,ARG(0,p));
menus[limits].needed = 1;
if(g != '+' && g != '*' && g != '^' && g!= '/' && g != '-')
{ menus[advanced_limits].needed = 1;
menus[special_limits].needed = 1;
}
if(g == '/' &&
( equals(ARG(0,u),x) || equals(ARG(1,u),x) ||
(FUNCTOR(ARG(1,u)) == '^' && equals(ARG(0,ARG(1,u)),x))
)
)
{ if(contains(u,SIN) || contains(u,COS) || contains(u,TAN))
menus[special_limits].needed =1 ;
if(contains(u,SINH) || contains(u,COSH) || contains(u,TANH))
menus[hyper_limits].needed =1 ;
}
if(g == '^' && ! OBJECT(ARG(1,u)))
{ menus[advanced_limits].needed = 1;
menus[special_limits].needed = 1;
}
if(equals(a,infinity) || equals(a,minusinfinity))
{ menus[limits_at_infinity].needed = 1;
if(contains(u,LN))
menus[logarithmic_limits].needed = 1;
}
if(g == '*' && ARITY(u) == 2 && contains(u,LN))
menus[logarithmic_limits].needed = 1;
if(g=='/')
{ menus[infinite_limits].needed = 1;
if(contains(u,LN) && ZERO(a))
menus[logarithmic_limits].needed = 1;
menus[limits_of_quotients].needed = 1;
if(contains_sqrt(ARG(0,u)) || contains_sqrt(ARG(1,u)))
menus[quotients_of_roots].needed = 1;
menus[lhopitalmenu].needed = 1;
}
if(g == LN && ZERO(a))
menus[infinite_limits].needed = 1;
if(g == TAN || g == COT || g == SEC || g == CSC)
menus[infinite_limits].needed = 1;
}
if(f == SUM)
{ menus[sigma_notation].needed = 1;
menus[advanced_sigma_notation].needed = 1;
menus[series_convergence_tests].needed = 1;
menus[series_convergence2].needed = 1;
if(contains(p,INFINITY))
{ menus[series_appearance].needed = 1;
menus[series_algebra].needed = 1;
menus[series_manipulations].needed = 1;
if(!contains(p,FACTORIAL))
{ menus[series_geom1].needed = 1;
menus[series_geom2].needed = 1;
menus[series_geom3].needed = 1;
menus[series_geom4].needed = 1;
menus[series_ln].needed = 1;
menus[series_atan].needed = 1;
}
else
{ menus[series_trig].needed = 1;
menus[series_exp].needed = 1;
}
}
}
if(f == BINOMIAL || f == FACTORIAL)
menus[binomial_theorem].needed = 1; /* binomial theorem */
if(f == '^' && FUNCTOR(ARG(0,p))== '+' && !equals(ARG(1,p),two))
menus[binomial_theorem].needed = 1; /* binomial theorem */
if( f== '*' )
{ for(i=0;i<ARITY(p);i++)
{ if(FUNCTOR(ARG(i,p))==SIN || FUNCTOR(ARG(i,p))==COS)
for(j=i+1;j<ARITY(p);j++)
{ if(FUNCTOR(ARG(j,p))==COS || FUNCTOR(ARG(j,p))==SIN)
{ menus[product_and_factor_identities].needed = 1;
menus[half_angle_identities].needed = 1;
}
}
}
}
if( f== '+' )
{ for(i=0;i<ARITY(p);i++)
{ if(FUNCTOR(ARG(i,p))==SIN || FUNCTOR(ARG(i,p))==COS)
for(j=i+1;j<ARITY(p);j++)
{ if(
(FUNCTOR(ARG(j,p))==COS || FUNCTOR(ARG(j,p))==SIN)
&& ! equals(ARG(0,ARG(j,p)),ARG(0,ARG(i,p)))
)
menus[product_and_factor_identities].needed = 1;
}
}
}
if( f == '^' && intflag)
{ menus[integrate_exp].needed = 1;
if(trigfunction(FUNCTOR(ARG(0,p))))
{ menus[trigonometric_integrals].needed = 1;
menus[trigrationalize].needed = 1;
}
}
if( f == '<')
{ menus[less_than].needed = 1;
if(ZERO(ARG(0,p)) || ZERO(ARG(1,p)))
menus[zero_ineq1].needed = 1;
}
if( f == '>')
{ menus[less_than].needed = 1;
menus[greater_than].needed = 1;
if(ZERO(ARG(0,p)) || ZERO(ARG(1,p)))
{ menus[zero_ineq1].needed = 1;
menus[zero_ineq3].needed = 1;
}
}
if (f == LE)
{ menus[less_than_or_equals].needed = 1;
if(ZERO(ARG(0,p)) || ZERO(ARG(1,p)))
menus[zero_ineq2].needed = 1;
}
if (f == GE)
{ menus[less_than_or_equals].needed = 1;
menus[greater_than_or_equals].needed = 1;
if(ZERO(ARG(0,p)) || ZERO(ARG(1,p)))
{ menus[zero_ineq2].needed = 1;
menus[zero_ineq4].needed = 1;
}
}
/* Now recursively traverse the args of p */
if( f == '/')
{ if(intflag)
{ menus[integrate_rational].needed = 1;
if(contains(ARG(1,p),SQRT))
menus[integrate_sqrtdenom].needed = 1;
}
for(i= 0; i< 2; i++)
menus_needed_aux(problemtype,ARG(i,p),sumflag,1,ineqflag,intflag);
}
else if( f == '+')
{ for(i= 0; i< ARITY(p); i++)
menus_needed_aux(problemtype,ARG(i,p),1,fractflag,ineqflag,intflag);
}
else if( f == '<' || f == '>')
{ for(i= 0; i< ARITY(p); i++)
menus_needed_aux(problemtype, ARG(i,p),1,fractflag,1,intflag);
}
else if( f == LE || f == GE)
{ for(i= 0; i< ARITY(p); i++)
menus_needed_aux(problemtype, ARG(i,p),1,fractflag,2,intflag);
}
else for(i=0;i<ARITY(p); i++)
menus_needed_aux(problemtype, ARG(i,p),sumflag,fractflag,ineqflag,intflag);
}
/*__________________________________________________________________*/
static int trigfunction(unsigned f)
/* return �1 if f is a trigonometric or arctrig functor; 2 for DEG;
else return zero */
{ switch (f)
{ case DEG : return 2;
case SIN : return 1;
case COS : return 1;
case TAN : return 1;
case CSC : return 1;
case SEC : return 1;
case COT : return 1;
case ASEC: return -1;
case ACSC: return -1;
case ATAN: return -1;
case ACOT: return -1;
case ASIN: return -1;
case ACOS: return -1;
default: return 0;
}
}
/*_____________________________________________________________________*/
static int hyper_function(unsigned f)
/* return 1 f is a hyperbolic functor else zero */
{ switch (f)
{
case SINH : /* fall-through */
case COSH :
case TANH :
case SECH :
case COTH :
case CSCH : return 1;
default: return 0;
}
}
/*__________________________________________________________________*/
static int has_compound_fractions(term t)
/* return 1 if t contains compound fractions, 0 if not */
{ int i;
if(ATOMIC(t))
return 0;
if(FUNCTOR(t) != '/')
{ for(i=0;i<ARITY(t);i++)
{ if(has_compound_fractions(ARG(i,t)))
return 1;
}
return 0;
}
/* so now FUNCTOR(t) == '/' */
for(i=0;i<ARITY(t);i++)
{ if(contains(ARG(i,t),'/'))
return 1;
}
return 0;
}
/*________________________________________________________________*/
static int half_angle(term p)
/* return 1 if p has a subexpression f(x/y) where f is a trigfunction
return 2 if p has a subexpression f(x�y) where f is a trigfunction;
return 3 if p has a numerical argument;
in case it has more than one of these return whichever is encountered first;
return 0 otherwise */
{ int i;
unsigned f = FUNCTOR(p);
if(ATOMIC(p))
return 0;
if(trigfunction(f))
{ if(FUNCTOR(ARG(0,p))== '/')
return 1;
if(FUNCTOR(ARG(0,p))== '+')
return 2;
if(numerical(ARG(0,p)) )
return 3;
}
for(i=0;i<ARITY(p);i++)
{ if(half_angle(ARG(i,p)))
return 1;
}
return 0;
}
/*___________________________________________________________________*/
static int im_aux(term p)
/* does p contain any exponent other than 2? if so return 1 */
{ unsigned i,n;
if(ATOMIC(p))
return 0;
if(FUNCTOR(p)=='^')
{ if(!ISINTEGER(ARG(1,p)))
return 1;
if(!equals(ARG(1,p),two))
return 1;
return im_aux(ARG(0,p));
}
n = ARITY(p);
for(i=0;i<n;i++)
{ if(im_aux(ARG(i,p)))
return 1;
}
return 0;
}
/* go through p and find the highest-priority functor */
static unsigned hpf(term p)
{ int i;
unsigned ans,temp;
unsigned g=FUNCTOR(p);
if(ATOMIC(p))
return 0;
ans = 0;
for(i=0;i<ARITY(p);i++)
{ temp = hpf(ARG(i,p));
if( more_important(temp,ans))
ans = temp;
}
if(more_important(g,ans))
ans = g;
return ans;
}
#define DIMORDERARRAY 34
static unsigned orderarray[DIMORDERARRAY] =
{ BESSELI,BESSELK,BESSELY,BESSELJ,INTEGRAL, DIFF, PR, SIN, COS, TAN, SEC, CSC,COT,
ASIN, ACOS,ATAN,ASEC,ACSC,ACOT, LN,LOGB,LOG, ROOT,SQRT, SUM, '+',
'/','^', ABS, FACTORIAL,DET,MATRIX,'*','-' };
static int more_important(unsigned f,unsigned g)
/* f is "more important than" g, for use in determining initial menu to show */
/* means f is listed before g in 'orderarray' */
{ int i;
if(f == g)
return 0;
if(g==0 && f != 0)
return 1;
for(i=0; i<DIMORDERARRAY; i++)
{ if(orderarray[i] == f)
return 1;
if(orderarray[i] == g)
return 0;
}
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists