Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/getprob/
Upload File :
Current File : /usr/home/beeson/MathXpert/getprob/inqindep.c

/*  M. Beeson, for Mathpert
    inquire_independent_variable; this file is interface-free, calling
    on get_var_from_user (in interact.c) for the actual interaction

11.8.92 extracted from getprob.c
10.24.99 last modified
12.29.99 added integral_subterm and code that calls it
1.2.00  added if(problemtype == GRAPH_PARAMETRIC) pflag = 1;  at line 182
3.8.00  corrected inquire_independent_variable for limits
3.28.00 added HIGH_ORDER_ODE to the list of problemtypes at line 225
5.3.00 modified inquire_independent_variable on SOLVE_TWO_ODES 
so it doesn't swap t out of varlist[0] just because it doesn't occur in the problem,
and so it doesn't reset the eigenvariable at the end.
8.1.00 modified inquire_independent_variable for SOLVE_TWO_ODES
12.2.00 modified inquire_independent_variable for SOLVE_ODE adding
      if(FUNCTOR(ARG(0,t)) == PR) at line 556
10.4.07  Added code at line 625 in inq_independent_variable to prefer THETA, then t for parametric graphs.   
10.21.10  modified at dated line for IMPLICIT_DIFF 
8.26.11  modified inquire_independent_variable at the dated line to get 't' introduced in graphing ode's when using PR.  
8.28.11 modified last lines of inquire_independent_variable
9.2.11  modified inquire_independent_variable for ODE types.
9.3.11  And again.
9.6.11  and again, at line 470
5.20.13  removed includes that are now included in mpdoc.h
5.10.24 made default_independent_variable implement its spec properly
9.4.24  modified inquire_independent_variable on PARAMETRIC
9.30.24  removed get_parameter_values (which was used only for MINMAX)
         removed confirm_independent_variable and modified inquire_independent_variable
12.10.24 added the dated line with set_dependency_info
1.15.25  removed 'else' at beginning of of line 490.
1.28.25 modified default_independent_variable on IMPLICIT_DIFF
*/

#include <assert.h>
#include <string.h>

#include "globals.h"  /* which includes setjmp.h and terms.h */
#include "graphstr.h"
#include "mpdoc.h"
#include "probtype.h"  /* possible values of problemtype */
#include "prover.h"
#include "algaux.h"   /* for getnewvar */
#include "chkinput.h" /* graph_interval */
#include "dispfunc.h" /* atom_string    */
#include "getprob.h"  /* eqns_adjust_varlist */
 

#define ODE_TYPE(x) (x==SOLVE_ODE || x==SOLVE_TWO_ODES || x == HIGH_ORDER_ODE)

static void set_halfbound(void);

/*___________________________________________________________________*/
static void inq_aux(term dependent)
/* dependent has been identified as the dependent variable
in a problem with only two non-INTEGER variables.  Locate
the other non-INTEGER variable (the independent variable)
and put it in varlist[0], and the dependent one in varlist[1] */

{ int i,k=-1,j=-1;
  int nvariables = get_nvariables();
  term *varlist = get_varlist();
  for(i=0;i<nvariables;i++)
     { if(equals(varlist[i],dependent))
          { j = i;
            continue;
          }
       if(TYPE(varlist[i])==INTEGER) /* it's a parameter */
          continue;
       if(k < 0)
          k = i;    /* found the independent variable */
       if(j >= 0)
          break;    /* no need to go on, have identified both
                       the dependent and independent variables. */
     }
  assert(j >= 0 && k >=0);  /* dependent = varlist[j],
                               independent = varlist[k]  */
  if(k!=0)
     { swapvars(0,k);
       if(j==0)
          j=k;
     }
  if(j!=1)
     swapvars(1,j);
  return;
}

/*___________________________________________________________________*/
static int integral_subterm(term t, term *ans)
/* Return 0 if t has an INTEGRAL subterm, with the
leftmost such term in *ans;  return 1 if it has no
such subterm.
*/
{ int i,err;
  unsigned short n;
  if(ATOMIC(t))
     return 1;
  if(FUNCTOR(t) == INTEGRAL)
     { *ans = t;
       return 0;
     }
  n = ARITY(t);
  for(i=0;i<n;i++)
     { err = integral_subterm(ARG(i,t),ans);
       if(!err)
          return 0;
     }
  return 1;
}
/*___________________________________________________________________*/
static int limit_subterm(term t, term *ans)
/* Return 0 if t has an LIMIT subterm, with the
leftmost such term in *ans;  return 1 if it has no
such subterm.
*/
{ int i,err;
  unsigned short n;
  if(ATOMIC(t))
     return 1;
  if(FUNCTOR(t) == LIMIT)
     { *ans = t;
       return 0;
     }
  n = ARITY(t);
  for(i=0;i<n;i++)
     { err = limit_subterm(ARG(i,t),ans);
       if(!err)
          return 0;
     }
  return 1;
}
/*___________________________________________________________________*/
void default_independent_variable(int nvariables, term *varlist, int flag)
// put the default independent variable at varlist[0]
// if flag is nonzero, then ignore the first two arguments and use the "real" nvariables and varlist;
// flag is passed as zero when setting up a listbox in a dialog before the "real" varlist is initialized.  Thus probably flag is always nonzero in Web MathXpert.
 { char *marker1, *marker2;
   char *preference = "xtyzwuvrs";
   unsigned f;
   int i,j = -1;
   if(flag)
      { varlist = get_varlist();
        nvariables = get_nvariables();
      }
   unsigned putative_eigenvariable = FUNCTOR(varlist[0]);
   marker1 = strchr(preference,putative_eigenvariable);
   for(i=0;i<nvariables;i++)
          { f = FUNCTOR(varlist[i]);
            marker2 = strchr(preference,f);
            // perhaps the following line would be good for all problemtypes ?
            if(marker2 < marker1 && get_problemtype() == IMPLICIT_DIFF)
               { putative_eigenvariable = f;
                 marker1 = marker2;
                 j = i;
               }
            if(f == THETA)
               { j = i;
                 putative_eigenvariable = f;
                 break;
               }
            if( /* given  sin(theta), select theta as the eigenvariable */
                ( (f == THETA  || f == PHI) && putative_eigenvariable < 't' ) ||
                (marker1 && marker2 && marker2 < marker1) ||
                (marker2 && !marker1)
              )
               { j = i;
                 putative_eigenvariable = FUNCTOR(varlist[j]);
               }
          }
    if(j>0)  /* then swap varlist[j] and varlist[0] */
       { if(flag) 
            swapvars(j,0);
         else
            { term temp = varlist[0];
              varlist[0] = varlist[j];
              varlist[j] = temp;
            }
       }
    else if(j < 0 && !marker1)  /* No variable >= 's' and no theta */
       { /* take the first Latin letter */
         /* example,  'ab' is entered, make 'a' the eigenvariable */
         j = 0;
         f = FUNCTOR(varlist[0]);
         for(i=0;i<nvariables;i++)
            { if(FUNCTOR(varlist[i]) < f)
                 { f = FUNCTOR(varlist[i]);
                   j = i;
                 }
            }
         if(j>0)
            { if(flag)
                 swapvars(j,0);
              else
                 { term temp = varlist[0];
                   varlist[0] = varlist[j];
                   varlist[j] = temp;
                 }
            }
       }
    if(get_problemtype() == IMPLICIT_DIFF)
       {  // there must be two variables and the second must depend on varlist[0];
          assert(nvariables >= 2);
          set_eigenvariable(0);
          f = FUNCTOR(varlist[1]);
          if(f >= 't' || nvariables == 2)
             set_dependency_info(varlist[1],varlist[0]);
          else
             { // look for the other variable
               for(j = 2; j < nvariables;j++)
                  { if(FUNCTOR(varlist[j]) >= 't')
                       { set_dependency_info(varlist[1], varlist[j]);
                         break;
                       }
                  }
             }
       }
    set_halfbound();
}
      
/*___________________________________________________________________*/
int inquire_independent_variable(PDOCDATA pDocData, term t)
/*  Assumes varlist is already set up, containing all atoms in the problem.
Must identify the independent variable for differentiation, indefinite integration,
solve-equation, and graphing problem types.  For differentiation and
integration problems, must decide which variables depend on the independent
variable, and set the rest up as parameters.  [Correction, this is done
by setup_parameters.]

For graphing problems,
assume all variables but the dependent and independent ones are parameters.
The problem has not yet been 'enhanced' by enhance_problem.
   'where' is SOURCE_MATHPERT or  SOURCE_USER.
The following assumptions will be made in order not to interrogate the user about the independent
variable:

   the first  variable after 't' (inclusive) in the alphabet in the
   expression typed by the user is the independent variable;  except
   that 'theta' or 'phi' in
   f(t theta) is the independent variable.  If there is no variable
   after t, then the independent variable is the first of theta, phi,
   if they occur, or the first Latin variable.  However, none of this
   applies to contour or relation graphs or implicit diff problems, or ode 
   problems.  In one-variable ode problems,  if t or x occurs (and not t' or x'),
   then it is the independent variable (whichever is typed first).

   Nonzero return value means user refused to give independent variable but
instead pressed Cancel, or the Esc key, to "start over".
   Swaps the order of terms in varlist so that the independent variable
comes first; hence the default 'eigenvariable = 0 ' is correct.  But in
limit or definite integration problems, eigenvariable should be set to the
index of the limit or definite integration variable in varlist.
   Also it must arrange that the dependent variable is in varlist[1].
   When this is called, varinfo hasn't yet been set to BOUND or HALFBOUND,
since we haven't yet identified the variables of differentiation or
integration, so this function must do that, too.
     It must correctly handle cases in which the independent variable
does not occur in the term t, as in graphing y = 5, or even
x=a where a is meant to be a parameter; or the differential
equation y' = y.
    It must also handle cases in which t is an OR, and the second disjunct
specifies a graph range, e.g.  or(x^3, -2 <= y <= 2).
     For 3d graphs, it has to make varlist[0] the first parameter
and varlist[1] the second parameter, that is, (x,y) or (u,v).
*/
{  const char *prompt = NULL;
   int i,j,err;
   int problemtype = pDocData->problemtype;
   int nvariables = pDocData->DocVarData.nvariables;
   term *varlist = pDocData->DocVarData.varlist;
   varinf *varinfo = pDocData->DocVarData.varinfo;
   term u,y;
   unsigned putative_eigenvariable;
   int pflag = 0;  /* set when dealing with a definite integral; at this point
                      we actually have an AND of three terms */
   int ngraphvars = 0;   /* don't count integer variables when attempting to
                            find the independent variable */
   if(problemtype == INTEGRATION && FUNCTOR(t) != INTEGRAL && contains(t,INTEGRAL))
      { /* locate the first integral and use it instead */
        integral_subterm(t,&u);
        t = u;
      }
   if((problemtype == LIMITS || problemtype == LHOPITAL) && FUNCTOR(t) != LIMIT && contains(t,LIMIT))
      { /* locate the first limit term and use it instead */
        limit_subterm(t,&u);
        t = u;
      }
   if(problemtype == INTEGRATION && FUNCTOR(t) == INTEGRAL)
      { if(!ISATOM(ARG(1,t)))
           return 0;    /* incorrect input; input_check will catch it, but
                           this gets called first. */
        for(j=0;j<nvariables;j++)
           { if(equals(ARG(1,t),varlist[j]))
                break;
           }
        assert(j < nvariables);
        if(j != 0)
           { swapvars(j,0);
           }
        return 0;
      }
   if(problemtype == LIMITS && FUNCTOR(t) == LIMIT)
      { u = ARG(0,t);
        if(FUNCTOR(u) != ARROW)
           return 0;  /* incorrect input */
        u = ARG(0,u);
        if(!ISATOM(u))
           return 0;  /* incorrect input */
        for(j=0;j<nvariables;j++)
           { if(equals(u,varlist[j]))
                break;
           }
        assert(j < nvariables);
        if(j != 0)
           { swapvars(j,0);
           }
        return 0;
      }
   if(problemtype == RELATED_RATES)
      /* make all variables depend on varlist[0] */
      { for(i=1;i<nvariables;i++)
           { SETDEPENDENT(varlist[i]);
             varinfo[i].dp = 1L;
           }
        return 0;
      }
   if(FUNCTOR(t) == AND && problemtype == INTEGRATION)
      pflag = 1;
   if(FUNCTOR(t) == OR &&
      GRAPHTYPE(problemtype) &&
      problemtype != RELATED_RATES &&
      problemtype != SIMPSONS_RULE &&
      problemtype != TRAPEZOID_RULE &&
      problemtype != RIEMANN_SUMS && 
      problemtype != HIGH_ORDER_ODE
     )
       pflag = 1;
   if(problemtype == PARAMETRIC_GRAPH || problemtype == POLAR_GRAPH )
      { pflag = 1;
        term u = zero;  // will be the parameter interval if there is one
        if(problemtype == PARAMETRIC_GRAPH && ARITY(t) == 2)
           {  // it's from the Problem Library, as users must enter the parameter interval
              // all the stored problems have variable t or theta, but they do have parameters
              ;  // do nothing
           }
        else if(problemtype ==PARAMETRIC_GRAPH && ARITY(t) == 3)
           u = ARG(2,t);
        else if (problemtype == POLAR_GRAPH && ARITY(t) == 2 && FUNCTOR(t) == AND)
           u = ARG(1,t);
        else
           {  // we have to set the independent variable from t, as the parameter interval
              // isn't set yet.
              // user-entered problems have to include the parameter interval.
              // but Problem Library problems should have independent variable theta,
              // which may not be in varlist[0] if there is a parameter
              if(problemtype == POLAR_GRAPH && contains(t, THETA))
                 { for(int k = 0;k<nvariables;k++)
                     { if(FUNCTOR(varlist[k])== THETA)
                           { swapvars(k,0);
                             return 0;
                           }
                      }
                 }
            }
        
        if (interval_as_and(u))
            {
              term x = ARG(1,ARG(0,u));
              for(int k = 0;k<nvariables;k++)
                 { if(equals(x,varlist[k]))
                      { swapvars(k,0);  // put x in 0-th place, it's the independent variable
                        return 0;   // done!
                      }
                  // assert(0);  // OK provided interface properly validates input
                 }
            }
            // assert(0);
      }
   for(i=0;i<nvariables;i++)
      { if(varinfo[i].type != INTEGER && 
           (!pflag || contains(ARG(0,t),FUNCTOR(varlist[i]))) 
          )
           { if(ngraphvars == 0 && i > 0 &&
                problemtype != SOLVE_TWO_ODES 
               )
                swapvars(i,0); /* put the first graph variable that occurs in the problem
                                  in the 0-th position. */
             ++ngraphvars;    /* also don't count variables that only occur in the
                                limits of a definite integral */
           }
      }
   if(ngraphvars == 0)  // a constant was entered
      { invent_new_independent_variable(t, problemtype);
        ++ngraphvars;
      }
   if(ngraphvars == 1 &&  !ODE_TYPE(problemtype))
      { /* you might think there's nothing to do, but if user has entered
           y=5 for a graphing problem, we don't want to make y the independent
           variable! */
        if(!GRAPHTYPE(problemtype))
			return 0;
		// so now we're making a graph
             /* 'contains' because t might be an AND of equations */
        if(FUNCTOR(t) == '=' && equals(ARG(0,t), varlist[0]) &&
                !contains(ARG(1,t),FUNCTOR(varlist[0]))
               )
                invent_new_independent_variable(t,problemtype);
             else if(FUNCTOR(t) == AND)
                { for(i=0;i<ARITY(t);i++)
                     { if(FUNCTOR(ARG(i,t)) == '=' &&
                          equals(ARG(0,ARG(i,t)),varlist[0]) &&
                          !contains(ARG(1,ARG(i,t)),FUNCTOR(varlist[0]))
                         )
                          break;
                     }
                  if(i<ARITY(t))
                     invent_new_independent_variable(t,problemtype);
                }
          
    
      /* just make sure that varlist[0] is the first one which doesn't have
         type INTEGER; even in case of definite integrals this is ok since
         any variables occurring only in the limits come AFTER the integrand.
         If the integrand is constant (seminumerical that is) ngraphvars will
         be zero so we won't be here.
      */
      for(i=0;i<nvariables;i++)
          { if(varinfo[i].type != INTEGER)
               break;
          }
        if(i > 0)
           swapvars(i,0);
        if(GRAPHTYPE(problemtype) && contains(t,'='))
             /* 'contains' because t might be an AND of equations */
           { if(ISATOM(ARG(0,t)))
                invent_new_independent_variable(t,problemtype);
           }
        return 0;
      }
   if(ngraphvars >= 2 &&
       (problemtype ==  SOLVE_ODE ||
        problemtype == HIGH_ORDER_ODE
       )
     )
      { /* make sure the dependent variable is in varlist[1] */
        if(FUNCTOR(t) == '=' &&
           (FUNCTOR(ARG(0,t)) == PR || FUNCTOR(ARG(0,t)) == DIFF) &&
           ISATOM(ARG(0,ARG(0,t)))
          )
           { if(!equals(ARG(0,ARG(0,t)), varlist[1]))
                { /* then locate it and set it */
                  y = ARG(0,ARG(0,t));
                  for(i=0;i<nvariables;i++)
                     { if(equals(varlist[i],y))
                          { swapvars(i,1);
                            break;
                          }
                     }
                }
           }
        /* else assert(0) */
      }
   if(ngraphvars >= 3 && problemtype ==  SOLVE_TWO_ODES &&
      FUNCTOR(t) == AND && ARITY(t) == 2  /* as must be true */
     )
      { /* make sure the dependent variables are in varlist[1] and varlist[2] */
        for(i=0;i<ARITY(t);i++)
           { u = ARG(i,t);
             if(FUNCTOR(u) == '=')
                u = ARG(0,u);
             if(FUNCTOR(u) == PR || FUNCTOR(u) == DIFF)
                { y = ARG(0,u);
                  if(ISATOM(y))
                     { for(j=i+1; j<nvariables;j++)
                          { if(equals(varlist[j],y))
                               { swapvars(i+1,j);
                                 break;
                               }
                          }
                     }
                }
           }
      }
   if(problemtype == LINEAR_EQUATIONS)
      { if(FUNCTOR(t) != AND)
           return 0;  /* apparent success, but input_check will stop it */
        err = eqns_adjustvarlist(t);
        if(err)
           return err;
      }
   if( ngraphvars == 2 &&   /* t has form  Y= f(X) */
       FUNCTOR(t) == '=' &&
       ISATOM(ARG(0,t))  &&
       !(equals(ARG(0,t),pi_term) || equals(ARG(0,t),eulere) || equals(ARG(0,t),complexi) ||
         equals(ARG(0,t),trueterm) || equals(ARG(0,t),falseterm) || equals(ARG(0,t),infinity)
        ) &&
       problemtype != IMPLICIT_DIFF &&   
       problemtype != GRAPH_RELATION &&
       problemtype != GRAPH_INEQUALITY
     )  /* then don't prompt the user, we can figure it out */
      { inq_aux(ARG(0,t));
        set_dependency_info(ARG(0,t),varlist[0]);  // 12.10.24
        SETDEPENDENT(ARG(0,t));
        putative_eigenvariable = FUNCTOR(varlist[0]);
        /* The case y=a with a intended as parameter comes here.  Don't
           assume that 'a' is the independent variable, unless the source
           is SOURCE_MATHPERT */
        if(pDocData->problemsource == SOURCE_MATHPERT || !('a' <= putative_eigenvariable && putative_eigenvariable <= 'p'))
           return 0;
# if 0
// in Web MathXpert, we are not going to bother the user.
        err = confirm_independent_variable(varlist[0]);
        if(err)
           { invent_new_independent_variable(t,problemtype);
             setup_parameters(pDocData,t);
           }
#endif
        return 0;
      }
   if(ngraphvars == 2 && FUNCTOR(t) == AND && problemtype != GRAPH_INEQUALITY)
     /* maybe it's an AND of expressions Y = f(X) */
     /* only ONE of the conjuncts has to have that form,
        e.g.  y = x^2, sin x  is acceptable */
      { for(i=0;i<ARITY(t);i++)
           { u = ARG(i,t);
             if(FUNCTOR(u) == '=' && ISATOM(ARG(0,u)))
                { inq_aux(ARG(0,u));
                  return 0;
                }
           }
      }
   if( // pDocData->problemsource == SOURCE_MATHPERT &&
           problemtype != GRAPH_RELATION &&
           problemtype != GRAPH_INEQUALITY &&
           problemtype != CONTOUR_PLOT && 
           problemtype != SOLVE_TWO_ODES && 
           problemtype != SOLVE_ODE &&
           problemtype != HIGH_ORDER_ODE && 
           !(ngraphvars == 1 && GRAPHTYPE(problemtype))
          )
           /* Don't bother the user */
           /* except on IMPLICIT_DIFF, where textbook problems sometimes
              ask for dx/dy -- in Web MathXpert, you have to enter with the problem
              what derivative you want to solve for.
           */
      { default_independent_variable(get_nvariables(), get_varlist(),1);
        return 0;
      }
   if(solvetype(problemtype))
       prompt = english(639); /*  Solve for which variable?  */
   else if
     (problemtype == DIFFERENTIATE ||
      problemtype == DIFFERENTIATE_FROM_DEFN 
     )
       prompt = english(640); /* Differentiate with respect to which variable?  */
   else if (problemtype == INTEGRATION )
       prompt = english(641); /* Integrate with respect to which variable?  */
   else if (problemtype == MINMAX)
       prompt = english(644); /* Which is the independent variable?  */
   else if (problemtype == COMPLEX_CONTOUR_PLOT)
      { if(nvariables == 1)
           { varinfo[0].type = DCOMPLEX;
             return 0;
           }
        prompt =  english(642); /* Which is the independent complex variable?  */
      }
   else if (problemtype == GRAPH_RELATION ||
            problemtype == CONTOUR_PLOT ||
            problemtype == GRAPH_INEQUALITY
           )
      { if(nvariables == 1)  /* somebody might graph the relation x = 3 */
           { term y = getnewvar(t,"yxt");
             vaux(y);  /* add it to varlist */
             ++nvariables;
           }
        if(nvariables == 2 &&
           FUNCTOR(varlist[0]) == 'x' &&
           FUNCTOR(varlist[1]) == 'y'
          )
           return 0;   /* don't bother the user */
        if(nvariables == 2 &&
           FUNCTOR(varlist[0]) == 'y' &&
           FUNCTOR(varlist[1]) == 'x'
          )  /* swap x and y so x is varlist[0] */
            { swapvars(0,1);
              return 0;
            }
        if(nvariables == 2)  /* but they aren't x and y */
           prompt = english(643); /* Which variable do you want on the horizontal axis? */
        if(nvariables > 2)  /* if x and y are there, assume rest are params */
           { for(i=0;i<nvariables;i++)
               { if(FUNCTOR(varlist[i])== 'x')
                    { for(j=0;j<nvariables;j++)
                          { if(FUNCTOR(varlist[j]) == 'y')
                               { if(j==0 && i==1)
                                    { swapvars(0,1);
                                      break;
                                    }
                                 if(i!=0 && j!=0)
                                    swapvars(0,i);  /* swap x into position 0 unless blocked by y */
                                 if(j!=1)
                                    swapvars(1,j);  /* swap y into position 1 */
                                 if(i!=0 && j==0)   /* x was blocked by y, but no more */
                                    swapvars(0,i);  /* now that y is out of the way */
                                 break;  /* don't continue looking for 'y' */
                               }
                          }
                      if(j<nvariables)
                          break;  /* found both x and y */
                    }
               }
             if( i== nvariables || j == nvariables) /* 'x' or 'y' not found */
                prompt =  english(643);  /* Which variable do you want on the horizontal axis?  */
             else
                return 0;   /* finished */
           }
      }
   else if (   /* example:  y' = y,  we need to invent independent variable t; 
			      example:  y' = ay,  assume a is a parameter and invent t;
				  example:  y' = ty,  ask whether t is the independent variable or a parameter
				  example:  y' = ay + t,  assume a is a parameter and ask about t.
               In these last two cases, Web MathXpert will assume t is the independent variable
			    */
            (problemtype == SOLVE_ODE  ||
             problemtype == HIGH_ORDER_ODE
            ) &&
            (contains(t,PR) && !contains(t,DIFF))    
           )
      { int i,k=-1, depvarindex = -1;
        int notparameters = 0;  //count the variables that are not assumed to be parameters           
        for(i=0;i<nvariables;i++)
           { term y = ARG(0,ARG(0,t));  // the dependent variable
             if(!ISATOM(y)) 
                 assert(0);
             if(nvariables == 1)  // y' = y for example
                 { notparameters = 1;
                   break;
                 }         
             if( !equals(varlist[i],y) && ('a' <= FUNCTOR(varlist[i]) && FUNCTOR(varlist[i]) <= 'd'))  // treat this variable as a parameter by default
                 continue;
             ++notparameters;
             if(equals(varlist[i],y))
                depvarindex = i;
             if(k == -1 && !equals(varlist[i],y))
                k = i;  // mark the place of the first variable that is not the dependent variable and not alphabetically a parameter.
           }
        if(notparameters == 1)
		   { invent_new_independent_variable(t,problemtype);
             swapvars(nvariables,1);  // the dependent variable is left in the last position by invent_new_independent_variable
           }
        else if(depvarindex != 1)
           { swapvars(depvarindex,1);   // put the dependent variable in index 1
             if(k==1) 
                k = depvarindex;  // keep k the index of the same variable it was the index of
           }
        if(notparameters == 2) // deal with cases illustrated in the last two examples above
           { if(k != 0)
               swapvars(k,0);
             putative_eigenvariable = FUNCTOR(varlist[0]);
             err = 1;
             if(GREEK(putative_eigenvariable))
                 err = 0;  // assume it is the independent variable
             if( 'm' <= putative_eigenvariable &&  putative_eigenvariable <= 'z')
                err = 0;
             if( 'M' <= putative_eigenvariable &&  putative_eigenvariable <= 'Z')
                err = 0;
             
                 { // assume it is the independent variable
                   err = 0;
                 }
             if(err)
                 { invent_new_independent_variable(t,problemtype);
                   swapvars(nvariables,1);  // the dependent variable is left in the last position by invent_new_independent_variable
                 }
           }
         if(notparameters > 2) //  Then, if t is mentioned, assume it is the independent variable, and otherwise, invent a new one.
                               //  example:   y' = y + t + w,   we assume t is the independent variable;  y' = y + z + w,  we invent t.
                               //  Such equations will rarely be entered and if the user doesn't like the result he can try again with diff(y,t).
           { for(i=0;i<nvariables;i++)
                { if(i == 1) continue;  // ignore the dependent variables
                  if(FUNCTOR(varlist[i]) == 't')
                      { swapvars(i,0);
                        break;
                      }
                }
            if(i == nvariables)
               { invent_new_independent_variable(t,problemtype);
                 swapvars(nvariables,1); 
               }

          }
        return 0;
      }
   else if ( problemtype == SOLVE_TWO_ODES  && ngraphvars == 2)
      { if( FUNCTOR(t)== OR && interval_as_and(ARG(1,t))) /* example:  y'=x,x'=-y | 2 <= t <= 5 */
           { u = ARG(0,ARG(1,ARG(1,t)));  /* the independent variable */
             for(i=0;i<nvariables; i++)
                { if(equals(varlist[i],u))
                     { swapvars(0,i);
                       return 0;
                     }
                }
           }
        if(
            (FUNCTOR(t) == OR && contains(ARG(0,t),FUNCTOR(varlist[0]))) ||
            (FUNCTOR(t) == AND && contains(t,FUNCTOR(varlist[0])))
              /* example:  y' = x, x' = -y,  with t not mentioned.  We need to invent t */
          )
        /* If the user presses "Domain and Range" in the GetProblem dialog,
           and then presses OK, OK,  then this gets called twice. Don't 
           invent a second new variable the second time it's called.
        */
           invent_new_independent_variable(t,problemtype);
        return 0;
      }
 
   else if (problemtype == SOLVE_TWO_ODES && ngraphvars > 2)
      /* example:  y' = x, x' = -yt  possibly followed by 2 <= t <= 5  */
      { term left1,left2,u,v;
        if(FUNCTOR(t) == OR && interval_as_and(ARG(1,t)))
           { /* user has entered a problem followed by an interval of values for the
                independent variable. */
             u = ARG(0,ARG(1,ARG(1,t)));  /* the independent variable */
             /* it should have already been checked that this variable 
                does not occur on the left of either of the differential equations,
                unless in the form dy/du */
             for(i=0;i<nvariables;++i)
                { if(equals(u,varlist[i]))
                     { swapvars(i,0);
                       return 0;
                     }
                }
             assert(0);   /* you must find that variable in the varlist */
           }
        assert(FUNCTOR(t)== AND);
        assert(FUNCTOR(ARG(0,t))=='=');
        assert(FUNCTOR(ARG(1,t))=='=');
        left1= ARG(0,ARG(0,t));
        left2= ARG(0,ARG(1,t));
        u = ARG(0,left1);
        v = ARG(0,left2);
        assert(ISATOM(u));
        assert(ISATOM(v));
        assert(equals(varlist[0],u));
        for(i=0;i<nvariables;i++)
           { if(equals(varlist[i],v) && i != 1)
                { swapvars(i,1);
                  break;
                }
           }
        // Now the two dependent variables are in positions 0 and 1 in varlist
        for(i=0;i<nvariables;i++)
           { if(FUNCTOR(varlist[i]) == 't')
                 { if(i==0|| i==1)
                      { invent_new_independent_variable(t,problemtype);  // since 't' is a dependent variable we can't use that.
                        swapvars(2,nvariables);   // get the second dependent variable into position 2
                      }
                   else
                      {  //  't' is the independent variable
                         // now we have x,y,...t,...  in varlist and we want t,x,y,...
                          swapvars(0,i);  //   t,y,...,x,...
                          swapvars(1,i);  //   t,x,...,y,...
                          if(i != 2)
                             swapvars(2,i);  //   t,x,y,...
                      }
                   break;
                  }
            }
        if(i == nvariables) 
           { // 't' did not occur 
             invent_new_independent_variable(t,problemtype);
              swapvars(2,nvariables);   // get the second dependent variable into position 2
           }
        return 0;
      }
   else if (problemtype == PARAMETRIC_GRAPH && ngraphvars == 3
            && FUNCTOR(t)==AND && ARITY(t)==2  /* these must hold--but compiler won't take an assert inside if */
            && FUNCTOR(ARG(0,t)) == '=' && FUNCTOR(ARG(1,t))== '='
              /* this last can fail, e.g. if (sin at, cos bt) was entered */
              /* but note that (sin nt, cos mt) won't fail it, since
                 n and m are integer parameters and not counted in ngraphvars */
           )
      { for(i=0;i<nvariables;i++)
          { if(!equals(ARG(0,ARG(0,t)),varlist[i]) &&
               !equals(ARG(0,ARG(1,t)),varlist[i]) &&
               varinfo[i].type != INTEGER
              )
               break;   /* independent variable is varlist[i] */
          }
        if(i==0)
           return 0;   /* nothing to do */
        swapvars(0,i);       /* put the independent variable in 0-th position */
      }
   else if (problemtype == PARAMETRIC_GRAPH && ngraphvars >1)
      { /* prefer theta or t as independent variable if present */
        for(i=0;i<nvariables;i++)
           { if(FUNCTOR(varlist[i]) == THETA)
                 { swapvars(0,i); 
                   break;
                 }
           }
        for(i=0;i<nvariables;i++)
           { if(FUNCTOR(varlist[i]) == 't')
                { swapvars(0,i);
                  break;
                }
           }
      }
   else if GRAPHTYPE(problemtype)
      prompt = english(644);  /* Which is the independent variable? */
   if(prompt == NULL)
      return 0;  /* no action necessary for some problemtypes */
   else if(pDocData->problemsource == SOURCE_MATHPERT)
      err = 0;  /* e.g., if this came from the Graph Button, don't bother the user */
   else
      { 
        assert(nvariables >= 1);
         /* otherwise invent_new_independent_variable has been called by now */
         /* Web MathXpert will not interrogate the user.
            If they don't like the choice of variables, they can go back and pick
            letters in the first half of the alphabet for constants.
         */
      }
   if(err)
      return 1;  /* user refused, pressing ESC */
   set_halfbound();   /* near end of this file */
   if((problemtype == GRAPH_RELATION  || problemtype == GRAPH_INEQUALITY) &&
      nvariables > 2
     )
       /* Haven't got the independent variable and also
          must still get vertical variable.
          We arrive here with input "fish" for example
       */
      { int i;
        term *varlist = get_varlist();
        int nvars = get_nvariables();
        // does 'x' or 'y' occur? if so swap it to position 0 or 1, resp.
        for(i=0;i<nvars;i++)
           { if(FUNCTOR(varlist[i]) == 'x')
                { swapvars(i,0);
                }
             if(FUNCTOR(varlist[i]) == 'y')
                { swapvars(i,1);
                }
           }
        if(FUNCTOR(varlist[0])!= 'x' && FUNCTOR(varlist[1]) != 'y')
           { // neither x nor y is there, sort the varlist in reverse alphabetical order
             int i,j;
             for(i=0;i<nvars;i++)
             for(j=i;j<nvars;j++)
                { if(FUNCTOR(varlist[j]) < FUNCTOR(varlist[i]))
                     swapvars(j,i);
                }
             return 0;
           }
        if(FUNCTOR(varlist[0]) == 'x')
           { // take the alphabetically last one for the vertical axis
             int i;
             int j = 0;
             for(i=0;i<nvars;i++)
                { if(FUNCTOR(varlist[i]) > FUNCTOR(varlist[j]))
                     { j = i;
                     }
                }
             if(j > 1)
               swapvars(j,1);
             return 0;
           }
        if(FUNCTOR(varlist[1]) == 'y')
           { // take the alphabetically last one for the horizontal axis
             int i;
             int j = 0;
             for(i=0;i<nvars;i++)
                { if(i==1)
                     continue;
                  if(FUNCTOR(varlist[i]) > FUNCTOR(varlist[j]))
                     { j = i;
                     }
                }
             if(j > 1)
               swapvars(j,0);
             return 0;
           } 
             
      
        
        
      }
return 0;
}

/*___________________________________________________________*/
#if 0
 //  old finish of prevous function
   if(problemtype  == MINMAX)
      return get_parameter_values(pDocData,t);

   return 0;  /* success at last */
}
/*_________________________________________________________*/
static int get_parameter_values(PDOCDATA pDocData,term t)
/* assumes varlist[0] is the independent variable.  If t
contains any parameters (other variables except possibly the
dependent variable, which would appear on the left of = in t,
prompt the user for numerical values for them.  Enter those parameter
values using SETVALUE and also in the assumption list.
Return 1 if user refuses, pressing Esc.  Return 0 for success. */
{ term y;
  int err,i,yflag=-1;
  double ans;
  int nvariables = pDocData->DocVarData.nvariables;
  term *varlist = pDocData->DocVarData.varlist;
  char prompt[64];
  if(FUNCTOR(t) == '=')
     { y = ARG(0,t);
       assert(ISATOM(y));
       /* where is y in varlist? */
       if(nvariables ==2)
          return 0;
       for(i=0;i<nvariables;i++)
          { if(equals(varlist[i],y))
               break;
          }
       assert(i<nvariables);
       yflag = i;
     }
  for(i=1;i<nvariables;i++)
     { if(i==yflag)
          continue;
       strcpy(prompt, english(1120));
         /* Enter a numerical value for */
       strcat(prompt, atom_string(varlist[i]));
       strcat(prompt,": ");
       err = get_double(prompt,  &ans);
       if(err)
          return 1;
       SETVALUE(varlist[i],ans);

       assume(equation(varlist[i],make_double(VALUE(varlist[i]))));

     }
  return 0;
}
#endif
/*_________________________________________________________*/
static void set_halfbound(void)
/* Set varinfo[0].scope to HALFBOUND when appropriate.  This is
called by inquire_independent_variable except when the problem came
from the problem-generator, and then it is called from get_problem. */

{  varinf *varinfo= get_varinfo();
   int problemtype;
   if(varinfo[0].scope == BOUND)
      return;  /* do nothing */
   problemtype = get_problemtype();
   if(problemtype == DIFFERENTIATE ||
      problemtype == DIFFERENTIATE_FROM_DEFN ||
      problemtype == IMPLICIT_DIFF ||
      problemtype == INTEGRATION ||
      problemtype == RELATED_RATES ||
      problemtype == MINMAX
     )
      varinfo[0].scope = HALFBOUND;
}
 
#if 0
/*____________________________________________________*/
static int inquire_independent_vars(int problemtype, int nvariables, term t, unsigned long long hwnd)
/* used to identify x,y  in 3d graphing types.
   t is the (not-yet-enhanced) term entered as the problem.
*/
{ int i,j;
  int a,b;
  term tlist,y,u,v;
  term *varlist = get_varlist();
  term intervals;
  if(FUNCTOR(t) == OR)
     { intervals = ARG(1,t);
       t = ARG(0,t);
       if(FUNCTOR(intervals) == AND && ARITY(intervals) <= 3)
          { /* then assume that it is the independent variables which
               have been mentioned in the first two intervals */
            assert(graph_interval(ARG(0,intervals)));
            assert(graph_interval(ARG(1,intervals)));
            u = ARG(1,ARG(0,ARG(0,intervals)));
            v = ARG(1,ARG(0,ARG(1,intervals)));
            for(i=0;i<nvariables;i++)
               { if(equals(varlist[i],u))
                    { for(j=0;j<nvariables;j++)
                         { if(equals(varlist[j],v))
                              { if(i!=0 && j!=0)
                                   swapvars(0,i);  /* swap u into position 0 unless v is alreayd there */
                                if(j!=1)
                                   swapvars(1,j);  /* swap v into position 1 */
                                if(i!=0 && j==0)   /* u was blocked by v, but no more */
                                   swapvars(0,i);  /* now that v is out of the way */
                                return 0;
                              }
                         }
                    }
               }
            assert(0);  /* u and v must have been in the varlist somewhere. */
          }
     }
  else
     SETFUNCTOR(intervals,ILLEGAL,0);
  switch(problemtype)
     { case NONPARAMETRIC_SURFACE:
          a = 'x';
          b = 'y';
          break;
       case POLAR_NONPARAMETRIC_SURFACE:
          a = 'r';
          b = THETA;
          break;
       case PARAMETRIC_SURFACE:
          if(contains(t,THETA))
             { a = 'r';
               b = THETA;
             }
          else
             { a = 'u';
               b = 'v';
             }
          break;
       default:
          assert(0);
     }
  if(nvariables == 1)  /* somebody might graph the function z = 5*/
     { if(problemtype == NONPARAMETRIC_SURFACE)
          y = getnewvar(t,"yxt");
       else if(problemtype == POLAR_NONPARAMETRIC_SURFACE)
          { varlist = get_varlist();
            if(FUNCTOR(varlist[0]) == THETA)
               y = getnewvar(t,"r");
            else
               y = make_atom_from_string("theta");
          }
       else   /* if(problemtype == PARAMETRIC_SURFACE) */
          y = getnewvar(t,"uv");
       vaux(y);  /* add it to varlist */
       ++nvariables;
       varlist = get_varlist();
      }
  if(nvariables == 2 &&
     FUNCTOR(varlist[0]) == a &&
     FUNCTOR(varlist[1]) == b
    )
     return 0;
  if(nvariables == 2 &&
     FUNCTOR(varlist[0]) == b &&
     FUNCTOR(varlist[1]) == a
    )  /* swap x and y so x is varlist[0] */
     { swapvars(0,1);
       return 0;
     }
  if(nvariables > 2)  /* if a and b as determined above are there,
                         use them as independent vars */
     { for(i=0;i<nvariables;i++)
          { if(FUNCTOR(varlist[i])== a)
               { for(j=0;j<nvariables;j++)
                    { if(FUNCTOR(varlist[j]) == b)
                         { if(i!=0 && j!=0)
                              swapvars(0,i);  /* swap x into position 0 unless blocked by y */
                           if(j!=1)
                              swapvars(1,j);  /* swap y into position 1 */
                           if(i!=0 && j==0)   /* x was blocked by y, but no more */
                              swapvars(0,i);  /* now that y is out of the way */
                           break;  /* don't continue looking for 'y' */
                         }
                    }
                 if(j<nvariables)
                    return 0;  /* found both x and y */
               }
          }
        while(1)
           { get_vars_from_user(english(1282),0,hwnd,&tlist);
                              /* Select the two independent variables */
                              /* the 0 means to show all variables
                                 as possible choices    */
             if(ARITY(tlist) == 2)
                break;
             report_message(english(1532),english(1291)); /* Error */
             /* Select TWO independent variables.  Press and hold the Shift... */
           }
        /* Put the variables selected into varlist[0] and varlist[1] */
        nvariables = get_nvariables();
        for(i=0;i<nvariables;i++)
           { if(FUNCTOR(varlist[i]) == FUNCTOR(ARG(0,tlist)))
                 { swapvars(0,i);
                   break;
                 }
           }
        assert(i<nvariables);
        for(i=0;i<nvariables;i++)
           { if(FUNCTOR(varlist[i]) == FUNCTOR(ARG(1,tlist)))
                 { swapvars(1,i);
                   break;
                 }
           }
        assert(i<nvariables);
        return 0;
     }
  return 0;
}
#endif

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists