Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/prover/
Upload File :
Current File : /usr/home/beeson/MathXpert/prover/binders.c

/*   M. Beeson, for Mathpert  */
/* binders etc.-- keeping a record of bound variables while traversing a term */
/* You call fillbinders when passing a binding functor and releasebinders
   when coming out again.  */
/* 6.11.92 original date
   1.6.99 last modified
   9.5.04  corrected i+i to i+1 at line 115 and added set_nvariables a few lines below.
   9.16.11  added the line commented "used by release_binders". 
   9.18.11  at line 108 changed assert(i>0) to assert(i>=0).
   5.5.13 added include binders.h 
   5.6.13 changed definition of isbinder--it is not exported! (Why wasn't this causing problems, or was it?) 
*/

#include <assert.h>
#include <stdlib.h>
#include "globals.h"
#include "prover.h"
#include "binders.h"


static termlist *binders;
static termlist *lastbinder = NULL;   /* to begin with there is no node */
/* binders is kept as a doubly linked list in permspace,
and lastbinder points to the last node.  */
/*________________________________________________________________*/
termlist * get_binders(void)
{ return binders;
}
/*________________________________________________________________*/
void init_binders(void)
/* used to initialize the binders list from outside prover.dll */
{ binders = lastbinder = NULL;
}
/*________________________________________________________________*/
void setlocus(term x,term *savelocus,int *savej,term p)
/* x must be a BOUND variable.  Find it in varlist as varlist[i],
save the current locus in *savelocus and save i in *savej,
and set the locus to p  */
  { int i;
    int nvariables = get_nvariables();
    term *varlist = get_varlist();
    varinf *varinfo = get_varinfo();
    for(i=0;i<nvariables;i++)
        { if(equals(x,varlist[i]))
             break;
        }
    if(i >= nvariables)
       assert(0);  /* you must find the variable in varlist */
    *savelocus = varinfo[i].locus;
    *savej = i;
    varinfo[i].locus = p;
  }
/*________________________________________________________________*/

void addbinder(term p)
/* store one more 'binder' */
/* lastbinder always points to the last node, or to NULL if there is no node */
{ termlist *oldlast = lastbinder;
  lastbinder = mallocate(sizeof(termlist));  /* create a new last node */
  if(lastbinder == NULL)
     nospace();
  lastbinder->prev = oldlast;        /* set the back-pointer */
  lastbinder->data = p;              /* fill it */
  lastbinder->next = NULL;
  if(oldlast == NULL)
     binders = lastbinder;
  else
     oldlast->next = lastbinder;    /* set the previous forward pointer */
}
/*______________________________________________________________________*/
void releasebinders(void)
/* get rid of the last two nodes on the binders list */
{  term h,p,q;
   if(lastbinder->prev == NULL)
      assert(0);
   q = lastbinder->data;
   p = lastbinder->prev->data;
   /* p and q are the two binder propositions.  What is the bound
   variable?  */
   if(FUNCTOR(p) == LE && FUNCTOR(q) == LE)
      { /* This was a definite integral or indexed sum or product*/
        h = ARG(1,p);
        if(!equals(ARG(0,q),h))
           assert(0);
      }
   else
      { h = ARG(1,q);
        if(!ISATOM(h))
           h = ARG(0,lastbinder->data);
        if(!ISATOM(h))
           assert(0);
        /* h is the limit variable, or in case of limits at infinity, a
           new variable treated as the reciprocal of the limit variable */
        if(DEPENDENT(h))      /* so marked if it came from a limit at infinity,
                            in which case we have to get rid of that variable
                            from varlist.  But it can also be so marked if
                            introduced by defnofderivative, in which case
                            we DON'T get rid of it.  */
           { int i;
             int nvariables = get_nvariables();
             term *varlist = get_varlist();
             varinf *varinfo = get_varinfo();
             for(i=nvariables-1;i>=0;i--)
                { if(equals(varlist[i],h))
                    break;
                }
             assert(i>=0);    /* you must find that variable */
             if(varinfo[i].multorder == 0)
                /* if it was introduced by defnofderivative, this will not hold.
                   If it does hold, the variable came from a limit at infinity. */
                { if(i==nvariables-1)
                     { --nvariables;   /* the most common and simple case */
                       set_nvariables(nvariables);
                     }
                  else  /* a new variable was introduced while traversing the limit
                           term, for example  cos(x) was in the denominator so we get
                           a new variable n and x != n pi is checked  */
                     {  /* move all the variables beyond that point down one */
                       int j;
                       for(j=i+1;j<nvariables;j++)
                          { unsigned long a,b;
                            varlist[j-1] = varlist[j];
                            varinfo[j-1] = varinfo[j];
                            /* Adjust the dependency information in varinfo */
                            /* Move bit i and bits left of it one place to the right
                               in varinfo[j-1].dp  */
                            a = varinfo[j-1].dp & (0xffffffffUL >> (32-i));
                                /* rightmost i bits -- don't touch these */
                            b = varinfo[j-1].dp & (0xffffffffUL << i);
                                /* bits to the left of the ones not to be touched */
                            varinfo[j-1].dp = a & (b >> 1);  /* the deed is done */
                          }
                        --nvariables;
                        set_nvariables(nvariables);  /* Now there's one fewer. */
                     }
                }
           }
      }
   lastbinder = lastbinder->prev;  /* back up */
   free2(lastbinder->next);
   if(lastbinder->prev == NULL) /* this is the head of the list */
      { free2(lastbinder);
        binders = NULL;
        lastbinder = NULL;
        return;
      }
   lastbinder = lastbinder->prev;     /* back up again */
   free2(lastbinder->next);
   lastbinder->next = NULL;           /* put a proper end to the list */
}
/*________________________________________________________________*/
int isbinder(term p)
/* does p occur in the binders list? if so return 1, else return 0 */
/* Also, if p has functor NE or LE and a term with functor < but the
same args appears in the binders list, also return 1. */
/* Also, if p has the form  a < h where h != infinity is in the binders list,
return 1 */
{ termlist *marker = binders;
  term u;
  unsigned f = FUNCTOR(p);
  unsigned g;
  if(ATOMIC(p))
     return 0;  /* should never happen, but be careful */
  assert(f==LE || f =='<' || f == '=' || f == NE);
  while(marker != NULL)
     { u = marker->data;
       g = FUNCTOR(u);
       if(equals(p,u))
           return 1;
       if(g=='<' && (f == LE || f==NE) && equals(ARG(0,u),ARG(0,p)) && equals(ARG(1,u),ARG(1,p)))
           return 1;
       if(g==NE && equals(ARG(1,u),infinity) && equals(ARG(1,p),ARG(0,u)))
      /* u has the form  h != infinity, put there when a limit at infinity is encountered */
          return (f== '=' ? 0 : 1);     /* example, 5 < h or 5 != h */
       if(g==NE && equals(ARG(1,u),infinity) && equals(ARG(0,p),ARG(0,u)))
          return f==NE ? 1 : 0;  /* example, h < 5  or h = 5 */
       if(g==NE && equals(ARG(1,u),minusinfinity) && equals(ARG(0,p),ARG(0,u)))
          return (f== '=' ? 0 : 1);   /* example,  h < 5 or h != 5 */
       if(g==NE && equals(ARG(1,u),minusinfinity) && equals(ARG(1,p),ARG(0,u)))
          return (f== NE ? 1 : 0);   /* example, 5 < h or 5 = h */
       marker = marker->next;
     }
  return 0;
}
/*________________________________________________________________*/
int get_infinitesimal(term *h, term *z, term *p)
/* lim(h->z,...) was entered */
/* Or, lim(x->infinity) was entered, and h comes out 1/x, z comes out zero */
/* and similarly for lim(x->-infinity)                                     */
/* search the binder list for an infinitesimal term, and
   extract h and z.  Assign *p to the following binder.
   Return 0 for success, 1 for failure */

{ termlist *marker = binders;
  while(marker != NULL && FUNCTOR(marker->data) != INFINITESIMAL)
     marker = marker->next;
  if(marker==NULL)
      return 1;
  *h = ARG(0,marker->data);
  *z = ARG(1,marker->data);
  *p = marker->next->data;
  return 0;
}

/*________________________________________________________________*/
void fillbinders(term t)
/* t is a term binding a variable; enter appropriate assumptions
restricting the range of the bound variable that are valid in its
scope  */

{  unsigned f = FUNCTOR(t);
   term x,a;
   int nvariables = get_nvariables();
   term *varlist = get_varlist();
   varinf *varinfo = get_varinfo();
   switch(f)
     { case INTEGRAL:
          assert(ARITY(t)==4);
            /* definite integrals only, not indefinite ones */
            /* fall through */
       case SUM:  
       case PRODUCT:
       case EVAL:
          x = ARG(1,t);
          addbinder(le(ARG(2,t),x));
          addbinder(le(x,ARG(3,t)));
          return;
       case LIMIT:
          x = ARG(0,ARG(0,t));
          a = ARG(1,ARG(0,t));
          if(NOTDEFINED(a))
             { char mu[7] = {MU,'t','u','s','v','w','x'};
               int i;
               term w = getnewvar(t,mu);
               assert(FUNCTOR(w) != ILLEGAL);  /* crash if we run out of variable space */
               ++nvariables;  /* getnewvar has added one */
               SETDEPENDENT(w);  /* so it will be marked DEPENDENT in the
                                    binders list, for benefit of 'nonstandard' */
               /* 'nonstandard' has to be able to recover the variable x
                   from w.  It does this by looking in the varinfo entry for
                   w to find out what variable w depends on.  Therefore we must
                   enter that information here.  Which entry in varlist is x? */

               for(i=0;i<nvariables;i++)
                  { if(FUNCTOR(varlist[i]) == FUNCTOR(x))
                       break;
                  }
               assert(i<nvariables);  /* x must be in varlist somewhere */
               assert(equals(varlist[nvariables-1],w));
                 /* w was just placed in varlist by getnewvar */
               varinfo[nvariables-1].dp = 1<<i;
               /* that takes care of entering the dependency info in varinfo */
               varinfo[nvariables-1].multorder= 0;  // used by release_binders
               addbinder(infinitesimal(w,zero));
               addbinder(equals(a,infinity) ? lessthan(zero,w): lessthan(w,zero));
               return;
             }
          addbinder(infinitesimal(x,a));
          if(ARITY(t)==3)  /* one-sided limit */
             { if(equals(ARG(1,t),right))
                  addbinder(lessthan(a,x));
               else
                  addbinder(lessthan(x,a));
             }
          else
             addbinder(ne(x,a));
          return;
      }
}

/*___________________________________________________________________*/
int get_limit_info(term *x, term *a, term *dir)
/* return indirectly the x and a such that the binders list
came from lim(x->a,...).  Return 0 for success.  Return 1 if
the binders list does not contain information from a limit.
If it's a one-sided limit, put 'left' or 'right' in *dir,
else put 'zero' there.  Limits at infinity are not considered
one-sided.
*/
{ termlist *marker;
  term z,b;
  if(binders == NULL)
    return 1;
  for(marker = binders; marker; marker = marker->next)
     { if(FUNCTOR(marker->data) == INFINITESIMAL)
          break;
     }
  if(!marker)
     return 1;  /* binders list doesn't refer to a limit */
  z = ARG(0,marker->data);
  b = ARG(1,marker->data);
  marker = marker->next;
  assert(marker);  /* the domain inequality must be there */
  if(VARNAME(FUNCTOR(z)) != MU)
     { /* it's not a limit at infinity */
       *x = z;
       *a = b;
       if(FUNCTOR(marker->data) == NE)
          { /* it's a two-sided limit */
            *dir = zero;
            return 0;
          }
       assert(FUNCTOR(marker->data) == '<');
       if(ZERO(ARG(0,marker->data)))
          { *dir = right;
            return 0;
          }
       *dir = left;
       return 0;
     }
  /* Now we have a limit at infinity. z is a new variable
     introduced as the reciprocal of the original variable.
     We have to recover x by seeing what variable z depends on.
  */
  *x = firstdepends(z);
  /* Now is it a limit at plus infinity or minus infinity? */
  assert(FUNCTOR(marker->data) == '<');
  if(ZERO(ARG(0,marker->data)))
     *a = infinity;
  else
     *a = minusinfinity;
  *dir = zero;
  return 0;
}

/*______________________________________________________________________*/
int binders_interval(term *left, term *x, term *right)
/* if the first two terms in the binders list are
0 <= x and x <= right, as they will be when they arose
from a definite integral or indexed sum, then instantiate
the variables  *left, *x, and *right, and return 0.
Otherwise return 1.
*/
{ term first, second;
  if(binders == NULL)
     return 1;
  first = binders->data;
  if(FUNCTOR(first) != LE)
     return 1;
  if(binders->next == NULL)
     return 1;
  second = binders->next->data;
  if(FUNCTOR(second) != LE)
     return 1;
  if(!equals(ARG(1,first),ARG(0,second)))
     return 1;
  *x = ARG(1,first);
  *left = ARG(0,first);
  *right = ARG(1,second);
  return 0;
}

/*________________________________________________________________________*/

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