
\section {Bergman proceedings extending\\  Standard  Lisp}

\subsection  {Introduction}

{\bf  Bergman} is written in Standard Lisp, as defined by the Standard
Lisp report \cite{StLisp}.  This contains (on purpose) a rather restricted
number of procedures.  It was necessary sometimes to
go outside the scope of Standard Lisp.  The "general Lispic" type 
procedures were defined  and collected in the source file {\bf slext.sl.}

 Many of these procedures actually exist in PSL (but often under
other names).  For such reasons the alternative  
definitions to most of them was privided, copying definitions from or calling
existing procedures when available, and else defining them by
means of "pure" Standard Lisp.

 In this section we list (hopefully) all the (general Lisp)
extensions of Standard Lisp alphabetically, with short
explanations of their actions; we discuss deviations from the
Standard in the {\bf bergman} sources; and we briefly discuss some
(potential) problems in the Standard itself, and in the way it
does or does not provide a good basis for e.g. Reduce
implementations.

 All descriptions are in Standard Lisp
syntax, but they have {\bf Rlisp} (i.e., symbolic mode) correspondences
in Reduce.  In order to have maximal benefit from them, a reader
who wishes to do some deeper level  {\bf bergman} programming should be
acquainted with Standard Lisp (or symbolic mode).



\subsection {Fast variant Standard Lisp extensions}

\begin{verbatim}

BMI!+ <--> PLUS2
BMI!- <--> DIFFERENCE
BMI!* <--> TIMES2
BMI!/ <--> QUOTIENT
BMI!< <--> LESSP
BMI!= <--> EQ
BMI!> <--> GREATERP
FASTGETV <--> GETV

\end{verbatim}

 The EXPRs or MACROs to the left operate as those to the right, with
the following two exceptions: input need not be typechecked, and input
and (for the first six ones) resulting numbers should be "INUMs", i.e.,
fairly small integers. Thus, the compiled code may use fast integer
arithmetics on them. (You may note that in the sources, these macros
are used on coefficients who are known to be of limited size and on
degree numbers and variable indices, while the right ones are used
on integer coefficients of indefinite size and e.g. on coefficients
in series calculations, where BIGNUMs may appear.)


\subsection {General Standard Lisp extensions}

 \begin{description}

 \index{addintolist} \item [(ADDINTTOLIST {\it i lint})] \ 

{\it i} should be a number, and {\it lint} a list $(i_1\  i_2\  i_3 \ldots)$ of numbers.
The list $(i_1+i\  i_2+i\  i_3+i\cdots)$ is returned.

 \index{appendchartoid} \item [(APPENDLCHARTOID {\it lch id})]: EXPR

{\it  lch} should be a list of characters, {\it id} an identifier. Returns an
interned identifier, whose print name consists of the characters on
{\it lch} followed by the print name of {\it id}. 

 \index{appendnumbertostring} \item [(APPENDNUMBERTOSTRING {\it numb strng})]: EXPR

 A new string is formed, consisting of the characters in the string
strng followed by the characters (sign if negative, digits, et cetera)
in the print form of the number {\it numb}.

 \index{applyifdef0} \item [(APPLYIFDEF0 {\it lexprid})]: EXPR

{\it lexprid} should be a list of identifiers. Each of these (in order)
is tested for a function definition, and if one is found, the function
is applied on an empty list. (Thus any one of the identifiers being
defined should be an EXPR with no arguments.)

\index{assignstring} \item [(ASSIGNSTRING {\it id string})]: EXPR

 Checks if {\it string} is a string, and then assignis it as the value of
{\it id}, returning the old value.  Else, prints a warning message, and
returns NIL. id is neither checked for being an identifier, nor for 
having a value.

\index{atsoc} \item [(ATSOC {\it any alist})]: EXPR
 As ASSOC, but tests if {\it any} equals the car of a dotted pair on {\it alist}
with EQ instead of EQUAL.


\index{bmdating} \item [(BMDATING)]: EXPR

 If available returns a string informing on the present date and time.
(If not available, the returned string informs on this fact.)

\index{callshell} \item [(CALLSHELL {\it filstr lst})]: EXPR

 Makes a system call with the calling command name given by the string
{\it filstr} and the arguments by the items of the list {\it lst}. 
(These items are represented by their print forms.)

\index{circlength} \item [(CIRCLENGTH {\it any})]: EXPR 

 Sets  !*CSTRUCTURE!*.
 Extends length measurement from ordinary lists to arbitrary
s-expressions, including circular lists. Returns the number of
CDR's possible until an atom is achieved (in which case
 !*CSTRUCTURE!* is set to NIL), or a former CDR is repeated
(in which case !*CSTRUCTURE!*  is set to T). Thus, (1 2 3 4)
has circlength 4; (1 2 . 3) has circlength 2; and if we have \\
A= (1 2 3 4 3 4 3 4 ...) (with (CDDR A) EQ to (CDDDDR A),
then A has circlength 2.


\index{cdradd1} \item [(CDRADD1 {\it alist})]: EXPR

{\it alist} should be an association list with numeric CDRs of items. Each
such CDR c is replaced by (ADD1 c). (Unspecified return value.)

\index{constantlist2string} \item [(CONSTANTLIST2STRING {\it lst})]: EXPR

 Returns a string consisting of the print forms of the items on the list
lst, separated by spaces.

\index{copy} \item [(COPY {\it any})]: EXPR

 Returns a recursively constructed copy of the S-expression any. Dotted
pairs are copied to new ones, until atoms are encountered. In other
words, COPY behaves as if defined by

\begin{verbatim}
(DE COPY (any)
 (COND  ((PAIRP any) (CONS (COPY (CAR any)) 
                           (COPY (CDR any))))
        (T any))) 
\end{verbatim}


\index{copy} \item [(COPYD {\it imgid srcid})]: EXPR

 Both arguments should be identifiers; the second one should be a
function name. COPYD copies the function definition from {\it srcid} to
{\it imgid}. (Unspecified return value.)

\index{defp} \item [(DEFP {\it id})]: MACRO

 Returns non-NIL iff has a function definition.

\index{delq} \item [(DELQ {\it lst any})]: EXPR

 As DELETE, but tests if {\it any} equals an item on {\it lst}
 with EQ instead of EQUAL.



\index{deglist2list} \item [(DEGLIST2LIST {\it dlist})]: EXPR

 Returns the items of a degree list (but not the degree numbers) in
one list, ordered in the way they come in the degree list. 

\index{dplistcopy} \item [(DPLISTCOPY {\it alist})]: EXPR

 Returns a copy of the association list {\it alist}; but copying is done on
the top list level and on the{\it alist} dotted pair items top level. (In
other words, in (DPLISTCOPY '(((1 2) 3 4))), 
the old and new ((1 2) 3 4)
parts won't be EQ, but both the (1 2) and the (3 4) parts will be.)

\index{dplistp} \item [(DPLISTP {\it any})]: EXPR

 Returns non-NIL iff any is an association list (i.e., a list of
dotted pairs).
 
\index{dskin} \item [(DSKIN {\it filen})]: EXPR

 Open the file with name  {\it filen}; reads, evals, and prints successively
each s-expression therein (if not redirected as some evaluation side
effect) until end-of-file is reached, and closes the file.
(Unspecified return value.)

\index{evenp} \item [(EVENP {\it no})]: EXPR or MACRO

 Returns non-NIL iff the integer no is even.

\index{fastgetenv} \item [(FASTGETV {\it vect no})]: MACRO

 Returns (GETV vect no) if the input is correct, but may be faster due
to the elimination of some error checks. 

\index{filep} \item [(FILEP {\it filstr})]: EXPR or MACRO

 Returns non-NIL if {\it filstr} is a legal file name of an existing file.
(In some versions, where this is not so easily done, it may always
returns non-NIL.)

\index{flipswitch} \item [(FLIPSWITCH {\it id boole})]: EXPR

{\it Id} must be an identifier, and be assigned a value. {\it Id} is
assigned NIL if {\it boole} is NIL, T else; and the old value of {\it id}
is returned.

\index{flushchannel} \item [(FLUSHCHANNEL {\it chn})]: MACRO

 Flush the output to the output channel (stream) {\it chn}.

\index{ibidnoopfcn} \item [(IBIDNOOPFCN {\it any})]: EXPR

 Just returns {\it any.} (Useful with COPYD in case some no-operator
variants are wanted in some modes.)

\index{lapin} \item [(LAPIN {\it filen})]: EXPR

 Open the file with name {\it  filen}; reads and evals successively
each s-expression therein (if not redirected as some evaluation side
effect) until end-of-file is reached, and closes the file.
(Unspecified return value.)

\index{lastcar} \item [(LASTCAR {\it lst})]: EXPR

 Returns the last item of the list {\it lst.}

\index{lastpair} \item [(LASTPAIR ({\it list}) (COND ((NULL (CDR {\it list})) {\it list})] \ 

 Returns the last top level pair (consisting of the last item and NIL)
of the list {\it lst}.

\index{lconc} \item [(LCONC {\it ptr lst})]: EXPR

{\it ptr} should be a dotted pair consisting of a list and of its
LASTPAIR. This list is concatenated with the list {\it  lst}, and the CDR of
{\it ptr} is changed to the LASTPAIR of the prolonged list. ({\it lst} may be NIL.)
(Unspecified return value.)

\index{listcopy} \item [(LISTCOPY {\it lst})]: EXPR

 Returns a copy of the list {\it lst}; but copying is done only on the top
list level.

\index{listonenoopfcn0} \item [(LISTONENOOPFCN0)]: EXPR

\index{listonenoopfcn1} \item [(LISTONENOOPFCN1 {\it any})]: EXPR

\index{listonenoopfcn2} \item [(LISTONENOOPFCN2 {\it any1 any2})]: EXPR

 Just returns a freshly constructed list. (Useful with COPYD in case
some no-operator variants are wanted in some modes.)

\index{loadifmacros} \item [(LOADIFMACROS {\it lid})]: FEXPR

 For each identifier (member of {\it lid}), checks whether this is function
bound to a macro, defined as a lambda expression. If so, eval this
expression (with NIL bound as argument).
 This is only intended for 'self loading MACROs', where it efficiently
forces the intended loading (and replacement of the MACRO definition
by an EXPR or FEXPR one), without or before calling the function.
(Useful in case self loading MACROs are called in compiled code as
EXPRs or FEXPRs. Since the 'self loading MACRO' trick is principally
intended for use with top level procedures, this should rarely happen.)

\index{mergestrings} \item [(MERGESTRINGS {\it string string})]: EXPR

Returns the concatenation of the two strings.

\index{minusp} \item [(MINUSP {\it no})]: EXPR or MACRO

 Returns non-NIL iff the number no is negative.
 
\index{ncons} \item [(NCONS {\it any})]: EXPR or MACRO

 Returns (CONS any NIL).

\index{nilnoopcfn0} \item [(NILNOOPFCN0)]: EXPR
\index{nilnoopcfn1} \item [(NILNOOPFCN1 {\it any})]: EXPR
\index{nilnoopcfn2} \item [(NILNOOPFCN2 {\it any1 any2})]: EXPR
\index{nilnoopcfn3} \item [(NILNOOPFCN3 {\it any1 any2 any3})]: EXPR
\index{nilnoopcfn4} \item [(NILNOOPFCN4 {\it any1 any2 any3 any4})]: EXPR

 Just returns NIL. (Useful with COPYD in case some no-operator
variants are wanted in some modes.)

\index{nones} \item [(NONES n)]: EXPR 

Creates a list consisting of $n$ ones: $(1 1\ldots 1)$.
\index{off} \item [(OFF {\it id})]: FEXPR

 Sets the identifier whose name is the name of the identifier {\it id}
preceeded by an asterisk $( * )$ to NIL. (Unspecified return value.)
 
\index{on} \item [(ON {\it id})]: FEXPR

 Sets the identifier whose name is the name of the identifier {\it id}
preceeded by an asterisk $( * )$ to T. (Unspecified return value.)


\index{onenoopfcn1} \item [(ONENOOPFCN1 {\it any})]: EXPR

\index{onenoopfcn2} \item [(ONENOOPFCN2 {\it any1 any2})]: EXPR

 Just returns 1. (Useful with COPYD in case some no-operator
variants are wanted in some modes.)

\index{paircopyd} \item [(PAIRCOPYD {\it alist})]: EXPR

{\it alist} should be an association list of identifiers; the second one in
each pair should be a function name. PAIRCOPYD copies the function
definition from the second identifier to the first one in each of the
pairs. (Unspecified return value.)

\index{pnth} \item [(PNTH {\it lst no})]: EXPR

{\it lst} should be a list of LENGTH greater than or equal to the positive
integer {\it no}. Returns the {\it no}'th top level pair of the list (so that
(PNTH lst 1) is EQ to {\it lst}, (PNTH lst 2) is EQ to (CDR lst), et cetera).

\index{printx} \item [(PRINTX {\it any})]: EXPR

 Sometimes succeeds in printing an ''unprintable object''.

\index{promptread} \item [(PROMPTREAD {\it string})]: EXPR

 A READ is performed, and the result returned. If reading is connected
with prompting, the string should be used for prompt.

\index{prunefirstdegreeitem} \item [(PRUNEFIRSTDEGREEITEM {\it dlany int})]: EXPR

 {\it dlany} must be a non-empty degree list. If the first
degree appearing on {\it dlany} is {\it int}, then (CDR dlany) is returned; else,
{\it dlany} is returned.

\index{reclaim} \item [(RECLAIM)]: EXPR or MACRO

 Performs a garbage collection. (May be a no-operator in some versions.)
(Unspecified return value.)

\index{setvectprog} \item [(SETVECTPROG {\it id no})]: EXPR

 Creates a new vector of length $no + 1$ and name {\it id}, and successively
reads the next $no + 1$ s-expressions (without evaluation), assigning
the vector entries to these. (Unspecified return value.) (Useful for
reading in very large vectors without overtaxing the recursive depth
of the lisp reader.)

\index{setprompt} \item [(SETPROMPT {\it string})]: EXPR

 Set the prompt string to prompt.

\index{stripexplode} \item [(STRIPEXPLODE {\it atm})]: EXPR

 Returns the same as EXPLODE on the atom atm, except that if {\it atm} is
a string its enclosing double quotes are removed.

\index{tconc} \item [(TCONC {\it ptr any})]: EXPR

 ptr should be either a dotted pair consisting of a list and of its
LASTPAIR, or NIL. This list is concatenated with a new dotted pair
formed by {\it any} and NIL, and the CDR of {\it ptr} is changed to this dotted
pair. If {\it ptr} is NIL, then a list of the one element {\it any} is formed,
and the dotted pair of this list and its LASTPAIR (i.e., itself)
is returned; else (the modified) {\it ptr} is returned.

\index{tconcptrclear} \item [(TCONCPTRCLEAR {\it ptr})]: EXPR

{\it ptr} should be a dotted pair consisting of a list and of its
LASTPAIR, as returned by successive applications of TCONC. This is
modified by removing all after the first element of the list. The
modified {\it ptr} (which now is EQUAL to the result of (TCONC NIL (CAAR ptr)))
is returned.

\index{time} \item [(TIME)]: EXPR or MACRO

 Returns an integer more or less measuring the "cpu time" of the
{\bf berg\-man} session until now. (Not necessarily available in all
versions.)

\index{tnoopfcn1} \item [(TNOOPFCN1 {\it any})]: EXPR

 Just returns T. (Useful with COPYD in case some no-operator
variants are wanted in some modes.)

\index{union} \item [(UNION {\it lst1 lst2})]: EXPR

 Returns a list containing the elements in the list {\it lst1} and {\it lst2},
avoiding repetitions of EQUAL members of both lists. (If several
members in one of the lists are equal, then however this `'redundancy''
may be carried over to the new list.)

\index{zerop} \item [(ZEROP {\it any})]: EXPR

 Returns non-NIL iff any is EQN to the number 0.
 

\end{description}


  \section{Formal description of  bergman}



\subsection{Organisation of the programme source files}

 There is a certain amout of modularisation of  {\bf bergman}.
 The programme is
divided into 'units', each of which corresponds to one or several
separate files. In these it is noted which procedures and special
variables are ''imported'' from other units, and which ''exported'', i. e.,
used in other units. This does NOT constitute ''modules'' in the C sense,
since almost all procedures are defined and equally available everywhere
in the final programme. In order to disencourage the use of lower level
procedures or variables in ordinary applications, these use mixed upper
and lower case letters (which makes them harder to access directly when
the flag RAISE is on, as it generally is). There are some exceptions in
upper cases; these are listed as ''available'' (if not exported),
documented, and intended for general use.

 As a matter of fact, the code to a high extent is written AS IF it
were truly modularised. Thus there are in general only some specified
procedures from one module used in the others, and these and their
action are documented in the file protocol.txt, which one can find into 
the {\bf bergman} documentation area. Very often such
procedures are defined in different versions. In fact, ''to change mode''
in bergman mainly means ''to replace one set of function definitions
with another''.

 Each unit is referred to in comments by its ''bare name'' 'foo'. The
corresponding source file has the bare name suffixed by .sl; compiled
versions, et cetera, will of course have other extensions. Thus, the
source files of the monomial manipulation unit 'monom' and 'ncmonom'
are named monom.sl and ncmonom.sl, respectively; in both, versions of
the ''exported'' monomial manipulation procedures are defined, in
commutative and non-commutative variants, respectively.

 There are also some ''header'' files, with macros and with some general
lisp procedures; and ''file handler'' files, used to compile the source
files and to add some top level interface procedures. These files
probably are more sensitive to changes of system than the 'ordinary'
source files; you may wish to or have to rewrite some of them.



\subsection{Overview of the (main) units and source files}
%as per 2004-09:

\begin{center}

        "FILE HANDLER" FILES:
\end{center}

\begin{tabular}{ll}
compan.sl  &  Performs the compiling of sourse files for Anick reslolution \\
           & and Betti numbers computation\\
compile.sl &  Compiling all main units \\
bmtop.sl   &  Loads main compiled units and creats {\bf bergman} \\
topproc.sl &  Contains the  top-of-the-top level functions \\

\end{tabular}

\begin{center}

        "HEADER" MACRO FILES:
\end{center}

\begin{tabular}{ll}
macros           &General macro file (used in all compilation)\\
accmacr          &Macro files used when compiling SAWS unit(s)\\
subsmacr &\\
midmacr &\\
anmacros & Macros for Anick procedures \\
\end{tabular}

\begin{center}
        STANDARD LISP EXTENSIONS:
\end{center}

\begin{tabular}{ll}
slext            &Defining procedures not in the Standard Lisp document.\\
                 &(Uses macros.sl. May be used in the compilation of all\\
                 &other files)\\
\end{tabular}

\begin{center}
CENTRAL UNITS:
\end{center}

\begin{tabular}{ll}
main   &Main functions; S-pair constructions\\
 strategy        &Graph component algorithm for eliminating redundant\\
                 &S-polynomial caculations\\
modes & Mode changes\\
\end{tabular}


\begin{center}
INTERFACE:
\end{center}

\begin{tabular}{ll}
 inout       & Input and output routines\\
 modinout    & Input and output routines for modules\\
 alg2lsp     & PSL, Maple- and Reduce-like input parcer procedures.\\
aninterf     & Interface for Anick modules\\
bnminout    & Input and output routines for Anick modules\\
t\_inout      &\\
\end{tabular}

\begin{center}
MONOMIALS AND POLYNOMIALS:
\end{center}

\begin{tabular}{ll}
monom           &Monomial handling (including puremon manipulations)\\
 ncmonom        &Non-commutative monomials handling (including\\ & puremon
                manipulations)\\
reclaim         &Garbage collection routines. (Could be dependent on\\
                &everything else, including on the machine)\\
 normwd  &Normal form calculations, and other polynomial handling\\
 reduct               &Contains some general routines, and some specific for\\ 
                &the char 0 case\\
polynom         &General polynomial routines\\
\end{tabular}


\begin{center}
COEFFICIENTS:
\end{center}

\begin{tabular}{ll}
coeff            &Coefficient arithmetic handling. Contains mainly means\\
                 &to use for changing or modifying the coefficient\\
                 &arithmetics; e. g., by calling on a modulus changer\\
                 &auxiliary\\
 char0           &Default ( = characteristic 0) coefficient manipulation\\
                 &procedures\\
\end{tabular}
\begin{center}
        ANICK UNITS\\
        (loaded automathically
        when needed):
\end{center}

\begin{tabular}{ll}
anbetti         & Calculating Betti numbers\\
bnmbetti        &\\
 chrecord       & Working with chains\\
  diffint       & Calculating resolution\\
  tenspol.      & Tensor polynomials\\
   gauss        & Some linear algebra   


\end{tabular}

\begin{center}
        SPECIAL PURPOSE AUXILIARY UNITS\\
        (hopefully loaded automathically
        when needed):
\end{center}

\begin{tabular}{ll}
odd             &Modulus changer auxiliary, compiled and (re)loaded when a\\
                &characteristic $> 2$ (without 'look-up logarithms') is set\\

logodd          &Modulus changer auxiliary, compiled and (re)loaded when a\\
                &characteristic $> 2$ is set, while the 'look-up logarithms'\\
                &is active\\
char2           &Modulus changer auxiliary, loaded when the characteristic\\
                &is set to $2$\\

pbseries        &Loaded when the double Poincare-Betti series or the Hilbert\\
                &series of the associated non-commutative monomially related\\
                &algebra is demanded\\
hseries         &Hilbert series handling\\
hscom           &Commutative Hilbert series calculation\\
sermul          &Series multiplications\\

checkstg,       &These files are compiled into the file stg.b, which should\\
accproc,        &be loaded automatically (from stagsubstance.sl) when any\\
subsproc,       &SAWS (Staggering Algorithm With Substance) procedure\\
stg,            &is called\\
monomstg,&\\
bind,&\\
write,&\\
ideal&\\
\end{tabular}

\begin{center}
SOME OTHER THINGS:
\end{center}

\begin{tabular}{ll}
auxil           &Extras, not necessary for ordinary usage.\\

debug           &Debugging facilities (only for development usage). Not\\
                &compiled (as standard).\\

homog           &Procedures enabling non-homogeneous input and output; under\\
                &development. Not compiled (as standard).\\
\end{tabular}

These units do not include any user interface (or e.g. Reduce interface)
worthy of mention. 


\subsection{Basic structures and naming conventions}\label{monomials}

 Here we give an informal description of the "types" communicated
between the "modules" of bergman.  The actual 'recursive definitions'
are only suggestions, since the 'parts' of an object
should not be accessed directly, but only by means of the procedures
described in the protocol file and by the macros in macro.sl.


 We are not concerned about differences between 'objects' being
represented by pointers or not, here; however, in Lisp we mostly
automatically have indirection.


 Several objects will be composed of others by recognised Lisp
operations, forming lists or (other) dotted pairs. A special
such construct is the degree list. (This was introduced, since
bergman is handling quite a number of homogeneous objects, and
often has use of accessing them sorted by degree.)

 In ``Lispish'' terms, a degree list DL (of type dlXXX) is an
association list, where the antecedents form an increasing
sequence of integers (the "degrees"). More precisely, the degree
list is a list of lists, say DL = (list\_1 list\_2 list\_3 \ldots),
where for each i the car of list\_i is an integer int\_i, and
the rest of the elements on list\_i are objects of type XXX;
i.e., list\_i = (int\_i . tail\_i), where tail\_i is of type lXXX.
The integers must fulfil int\_1 $ <$ int\_2 $ <$  int\_3 $ <$  \ldots . The
XXX objects in Cdr(list\_i) normally are said to have "degree
int\_i". (In many cases, DL always will fulfil the extra property
that (as soon as any active change of the list is concluded)
each tail\_i is non-NIL. Such a degree list is called pruned.)


 The prefix gen- always denotes: also NIL is a legal object.
dp- , l- , dl- denotes dotted pairs lists, and degree lists,
repectively. (gen- should only be used together with a type
definition NOT allowing NIL as a legal object.) Thus we have
the following "type macros" (or "templates"):
\begin{tabular}{lcl}
        genXXX &::=& $\langle$NIL  $|$  XXX$\rangle$\\
        dpXXX  &::= & $\langle$XXX$\rangle$$\langle$XXX$\rangle$\\
        lXXX  &::= & $\langle$NIL$\rangle$ $|$ $\langle$XXX$\rangle$$\langle$lXXX$\rangle$\\
        dlXXX  &::= & A special kind of l(intlXXX)\\
\end{tabular}

   \vspace{0.3cm}
\begin{center} 
{\bf \large 
        General Lisp types (abbreviated):}
\end{center}
\begin{tabular}{lcl}
 atom &::=& $\langle$id(ent(ifier))  $|$  number  $|$  string  $|$ ...$\rangle$\\
 any &::=& $\langle$atom  $|$  dpany$\rangle$\\
 bool &::=&  $\langle$ any $\rangle$\\
\end{tabular}

 For a complete description of Standard Lisp types, see
the Standard Lisp report \cite{StLisp}. The type "any" above includes
all bergman types below, although the programmer should
treat all of these not prefixed by dp-, l-, or dl- as
undivisible units from the general Lisp procedures point
of view.
{\it Bool} denotes (quasi) boolean variables. The reserved
Lisp identifier NIL is considered as standing for "false".
Any other Lisp item stands for "true". (This follows
ordinary Lisp conventions; which means that bool output
behaves as one might expect with logical Standard Lisp
procedures such as AND, COND, OR, and NOT. Likewise, it
is permitted to treat an object of type genXXX as a bool,
employing the fact that it is "false" if and only if it
is NIL, and hence is "true" if and only if it is of type
XXX.)


   \vspace{0.3cm}
\begin{center} {\bf \large Coefficient types:}\end{center}

        
 Primitive: redandcoeff, redorcoeff, in\_form\_coefficient,
            out\_form\_coefficient.

 \begin{tabular}{lcl}
 coeff &::= &$\langle$redandcoeff  $|$  redorcoeff  $|$  ratcoeff$\rangle$\\
 ratcoeff &::=& $\langle$redandcoeff$\rangle$ $\langle$redandcoeff$\rangle$\\
 genredandcoeff &::=& $\langle$redandcoeff  $|$  NIL$\rangle$\\
 genredorcoeff &::=& $\langle$redorcoeff  $|$  NIL$\rangle$\\
\end{tabular}

   \vspace{0.3cm}
\begin{center} 
{\bf \large 
        Implementations of internal coefficients (at present):}
\end{center}
 \begin{tabular}{lcl}
 redandcoeff &::=& $\langle$inum  $|$  bignum  $|$  unsigned inum  $|$\\
& & unsigned bignum
                   $|$  Standard\_Form$\rangle$\\
 redorcoeff &::=& $\langle$inum  $|$  bignum  $|$  unsigned inum  $|$\\
& & unsigned bignum
                   $|$  Standard\_Form$\rangle$\\
 in\_form\_coefficient &::=& $\langle$fixnum  $|$  Standard\_Form$\rangle$\\
 out\_form\_coefficient &::=& $\langle$fixnum  $|$  Standard\_Form$\rangle$\\
\end{tabular}

   \vspace{0.3cm}
\begin{center} 
{\bf \large 
        Monomial types:}
\end{center}


 Primitive: revlexpuremon, lexpuremon, ncpuremon, revlexmonquot,
            lexmonquot, ncmonquot, \ldots .

 \begin{tabular}{lcl}
 puremon &::=& $\langle$revlexpuremon  $|$  lexpuremon  $|$  ncpuremon  $|$  \ldots$\rangle$\\
 monquot &::=& $\langle$revlexmonquot  $|$  lexmonquot  $|$  ncmonquot  $|$  \ldots$\rangle$\\
 augmon &::=& $\langle$monptr$\rangle$ $\langle$monaugplist$\rangle$ $\langle$puremon$\rangle$\\ 
 monptr &::=& $\langle$any$\rangle$\\
 monaugplist &::=& $\langle$any$\rangle$\\
 mon\_factor\_data &::=& $\langle$bool$\rangle$\\
 exptno &::=& $\langle$unsigned int$\rangle$\\
 varno &::=& $\langle$unsigned int$\rangle$\\
 degree &::=& $\langle$int$\rangle$\\
\end{tabular}

 The puremon and quotmon types might be radically different
for different ring setups. When the ring setup modes are
changed, no conversion of existing monomial structures is
performed; but the access procedures for such structures are.
Thus, e.g. performing MONLESSP on a pair of monomials formed
when in another monomial mode yields unpredicted and
potentially damaging results.

 Similarly, mon\_factor\_data depends on monomial modes. However,
it also is of boolean type, whence tests for being NIL or
not are safe.

   \vspace{0.3cm}
\begin{center} 
{\bf \large 
    Types used internally in hseries:}
\end{center}
\begin{tabular}{lcl}
 hsflag &::=& $\langle$bool$\rangle$\\
 hsmon &::=& $\langle$exptno$\rangle$ $\langle$lexptno$\rangle$\\
 hsflagmon &::=& $\langle$hsflag$\rangle$ $\langle$hsmon$\rangle$\\
 hsmonid &::=& $\langle$lhsflagmon$\rangle$\\
 hsredmonid &::=& $\langle$hsmonid$\rangle$\\
 hsmoniddata &::=& $\langle$varno$\rangle$ $\langle$lhsredmonid$\rangle$\\
 hsmask &::=& $\langle$hsmon$\rangle$\\
 hscoeff &::=& $\langle$bignum$\rangle$\\
 hsterm &::=& $\langle$hscoeff$\rangle$ $\langle$degno$\rangle$\\
 hsnum &::=& $\langle$lhsterm$\rangle$\\
 hsdendeg &::=& $\langle$degno$\rangle$\\
 (gen)hsnumdendeg &::=& $\langle$hsnum$\rangle$ $\langle$hsdendeg$\rangle$\\
 hssplitnum &::=& $\langle$hsnum$\rangle$ $\langle$hsdendeg$\rangle$\\
\end{tabular}

 The monomial (augmented) property list procedures should be hand-set.
We only access them by means of \index{lget} LGET,\index{lput} LPUT, and 
\index{lput!-lget} LPUT!-LGET.

  \vspace{0.3cm}
\begin{center} 
{\bf \large 
        Term ( = Coefficient-Monomial) types:}
\end{center}
\begin{tabular}{lcl}
 redandterm &::=& $\langle$redandcoeff$\rangle$ $\langle$augmon$\rangle$\\
 redorterm &::=& $\langle$redorcoeff$\rangle$ $\langle$augmon$\rangle$\\
 ratterm &::=& $\langle$ratcoeff$\rangle$ $\langle$augmon$\rangle$\\
 term &::=& $\langle$coeff$\rangle$ $\langle$augmon$\rangle$, = $\langle$redandterm  $|$  redorterm  $|$  ratterm$\rangle$\\
\end{tabular}

   \vspace{0.3cm}
\begin{center} 
{\bf \large 
        Polynomial types:}
\end{center}
\begin{tabular}{lcl}
 pureredand &::=& $\langle$NIL$\rangle$ $|$ $\langle$redandterm$\rangle$$\langle$pureredand$\rangle$\\
 pureredor &::=& $\langle$NIL$\rangle$ $|$ $\langle$redorterm$\rangle$$\langle$pureredor$\rangle$\\
 purepol &::=& $\langle$pureredand  $|$  pureredor$\rangle$\\
 (gen)augredand &::=& $\langle$polhead$\rangle$ $\langle$pureredand$\rangle$\\
 (gen)augredor &::=& $\langle$polhead$\rangle$ $\langle$pureredor$\rangle$\\
 (gen)qpol &::=& $\langle$polhead$\rangle$ $\langle$pureredand$\rangle$\\
 (gen)augpol &::=& $\langle$polhead$\rangle$ $\langle$purepol$\rangle$ , = $\langle$augredand  $|$  augredor  $|$  qpol$\rangle$\\
 redandposition &::=& $\langle$augredand$\rangle$ $|$ $\langle$qpol$\rangle$ $|$ $\langle$pureredand$\rangle$\\
 redorposition &::=& $\langle$augredor$\rangle$ $|$ $\langle$pureredor$\rangle$\\
 polposition &::=& $\langle$redandposition  $|$  redorposition$\rangle$\\
 polheads &::=& $\langle$NIL  $|$  ratcoeff  $|$  polpriorities$\rangle$\\
 polpriorities &::=& $\langle$unsigned long$\rangle$\\
\end{tabular}

 The redandpositions (redorpositions) are intended to be the
(non-NIL) results of zero or more successive PolTails on an
augredand or a qpol (an augredor, respectively). A term "at"
a polposition is the Lt of the PPol part of the polposition.

 An augpol is incomplete if its purepol part is NIL.
 In most cases, the zero polynomial should be represented by NIL.
Thus, if some (destructive) algebraic operations on a polynomial
might yield a zero result, one should check whether or not the
purepol part is NIL; and if so, return NIL rather than the
corresponding incomplete augpol. The test preferrably should be
done by means of the macro PPol0!?.

Polheads may be implemented in some smarter way in C. We use it for
polpriorities in augredors and for ratcoeffs in qpols. We do not
access these with the same macros, so there should be no trouble.
 The polpriorities type suggested below has the weakness that it is
supposed to be user implementable. In the present implementation, it
is set to the number of terms in the polynomial (whence it is
unsigned and does not exceed the length of the longest polynomial;
this length however often is greater than 256 and probably might
exceed 65536 as well).
 The user might wish to use negative integers, too!



   \vspace{0.3cm}
\begin{center} 
{\bf \large 
        Strategic types:}
\end{center}
\begin{tabular}{lcl}
 critpairs &::=& $\langle$any$\rangle$\\
 binno &::=& $\langle$unsigned char$\rangle$\\
 (gen)degno &::=& $\langle$unsigned int$\rangle$\\
 bgsize &::=& $\langle$unsigned int$\rangle$\\
\end{tabular}



\subsection{Global structures and programme outline}\label{globals}

The most important global structures are:
\begin{itemize}
\item  \index{InPols}InPols, the input polynomials (the original ideal basis);
\item  \index{cInPols}cInPols, ditto of current degree;
\item  \index{SPairs}SPairs, the pairs of LeadMons to investigate;
\item  \index{cSPairs}cSPairs, ditto of current degree;
\item \index{GBasis} GBasis, the Gr\"{o}bner basis; and
\item  \index{cGBasis}cGBasis, the new Gr\"{o}bner  basis elements (of current degree).
\end{itemize}

They are described below. "Current degree" here stands for "The value
of the global variable cDeg".

InPols is organised as a list of (zero or more) degree-lists, where
each degree-list has a degree NUMBER as its car, and a positive
number of AUGMENTED POLYNOMIALs (ordered increasingly w.r.t their
LeadMons) as the rest of its elements. (Of course the polynomials in
one degree--list all have that total--degree.) The degree--lists are
ordered by increasing degree.

In the beginning of an ordinary application of the main procedure 
(which is GROEBNERKERNEL) InPols contains all input polynomials.
As the work progresses, more and more of these are removed
from InPols and processed; thus, in the end InPols is empty. At a
given time, InPols contains the input polynomials of higher total-degree 
than the current degree, while the unprocessed ones of the
current degree are listed on cInPols.

SPairs is a list of degree--lists, each of which has a degree as its
car and MONOMIALs (of that total--degree) as the rest of its elements.
Each such MONOMIAL is the lcm of at least one pair of LeadMons, which
has not (yet) been discarded as yielding a non-trivial S--polynomial,
a critical pair. Critical pairs are represented by dotted pairs of
LeadMons (represented as MONOMIALs). The POINTER of the monomial
is a list of critical pairs. The monomials in a degree--list are
ordered increasingly; and SPairs is ordered by increasing degree.

In the beginning of an ordinary GROEBNERKERNEL application, SPairs
is empty. In the run of the procedure, newly found critical pairs
are inserted in it (as elements of POINTERs of MONOMIALs in adequate
positions), while the SPair elements of the current degree are moved
to cSPairs and (in due time) processed and removed. Thus, in the end
SPair once more is empty.

GBasis and cGBasis are lists. Their cars are NIL; the rest of the
elements are LeadMons (represented as MONOMIALs) of Gr\"{o}bner basis
elements, ordered increasingly by the appropriate ordering. GBasis
contains the gbe's of lower than current total--degree; these are
in their final form (if the flag IMMEDIATEFULLREDUCTION is on).
cGBasis contains the new--found gbe's of the current degree. They
may very well change, due to reduction modulo gbe's found later
but with lower ordered LeadMons. However, their LeadMons cannot
change!

(The fact that the main structures are GLOBAL variables makes it
possible to use the main functions for slightly different purposes.
E. g., in order only to perform a reduction of a polynomial P modulo
a known Groebner basis B, just do\\
   (RPLACD GBasis B')\\
   (ReducePol P)\\
where B' is B represented in the above described way. Such variants
may be found in 'auxiliaries'.)

The main procedure GROEBNERKERNEL roughly works as follows:

\begin{verbatim}
While InPols or SPairs is non-empty do
 begin
  cDeg:= the lowest existing degree in InPols and/or SPairs
         ( = min(caar(InPols),caar(SPairs)), if both exist);
  Move the cDeg component(s) of InPols and/or SPairs to cInPols
  and/or cSPairs, discarding their cars (i.e., degrees);
  While cInPols or cSPairs is non-empty do
   begin
    If cSPairs is empty, or if car(cInPols) exists, and its
        LeadMon   is strictly of lower order than car(cSPairs),
     then process car(cInPols), and remove it from cInPols,
     else
      begin
       SP2r:=SPolInputs(car(cSPairs));
       For (a.b) in SP2r do
           process the S-polynomial POINTER(a)-POINTER(b);
      end;
   end;
  For mon in cdr(cGBasis) do 
         PRIORITY(POINTER(mon)):=length(POINTER(mon));
  If CUSTDISPLAY is ON then call DEGREENDDISPLAY,
   else if SAVEDEGREE is ON then call DEGREEOUTPUT;
  Consider new LeadMon-pairs among the new gbe's;
  Call MonReclaim;
 end;
\end{verbatim}

Here to process the augmented polynomial pol signifies:

\begin{verbatim}

begin
 NGroeb := ReducePol(pol) (i. e., the normal form of pol);
 If NGroeb $\ne $ 0 then (we indeed have a new gbe, whence:)
   begin
    POINTER(LeadMon(NGroeb)) := NGroeb;
    NGroeb := LeadMon(NGroeb);
    Consider new LeadMon-pairs formed by
             NGroeb and the old gbe's;
    Insert NGroeb on its proper place in cdr(cGBasis);
    If IMMEDIATEFULLREDUCTION is ON,
      then reduce other new gbe's w. r. t. NGroeb;
   end;
end;
\end{verbatim}

The process SPolInputs (defined in 'compalg' or in 'noncomm') takes
a MONOMIAL mon as its argument, which must have a list of critical
pairs as its POINTER. It produces (more or less smartly) a final list
of pairs of LeadMons of gbe's, from which S--polynomials will be
calculated. (As a side effect, POINTER(mon) is changed.)

At the end of the main loop of GROEBNERKERNEL, some more or less
optional procedures may be called. DEGREEOUTPUT 
prints the current degree gbe's, in a form decided by various global
or fluid variables, e. g. OutVars, GBasOutChan, and ALGOUTMODE.
In order to get its output on the file foo, perform
(DEGREEOUTPREPARE "foo")
before the GROEBNERKERNEL. (No argument = type on the standard output.)
Also perform (ENDDEGREEOUTPUT) or (GROEBNERFINISH) after
GROEBNERKERNEL.
The form of the output may be governed by assigning ALGOUTMODE
different values. (Right now, allowed values are LISP, MACAULAY, PBOUT,
and ALG. The latter stands for a "general" (Maple or Reduce type)
algebraic form.)

On the other hand, DEGREENDDISPLAY is not defined. Our
experience seems to indicate that users often want to customise
output.
You may do this by defining DEGREENDDISPLAY as any EXPR with
no argument, and by turning ON the flag CUSTDISPLAY. In this way you
may also e. g. interrupt the calculations at a certain degree.

Finally, MonReclaim is defined in the 'reclaim' unit. Since Gr\"{o}bner
basis calculation often tend to be very space-consuming, effective
reclaims may be of considerable value.
    
\section{Mathematical background}\label{sec:Math-app}

This appendix contains a brief introduction into the Gr\"{o}bner bases theory 
for graded algebras and does not pretend to more than a little help to the reader.

Let $K$ be a field and $\mathcal{A}$ be a  free commutative or non-commutative $K$-algebra 
generated by the finite alphabet: the set of variables 
$X.$ So  $\mathcal{A}$ is $K[X]$ or $K\langle X \rangle$ and it has a natural $K-$base, 
consisting of monomial (including the 
unity $1$). Note that we often use in this book the 
notions ``algebra'' and ``ring'' as synonyms. 

We would like to compare any two   monomials and there are only two essential 
restrictions
 on the ordering $>$
between the monomials. First we demand that no infinite descending chain of 
monomials $f_1>f_2>\ldots$ exists 
(for the commutative case it can be replaced by the demand that no one 
monomial is less than the unity). Second
we would like to have some kind of respect to the multiplication, namely:

$$f>g \Rightarrow fh>gh, hf>hg$$ for any monomial $h.$ 

Any ordering with those conditions is called admissible and   a few of them are 
used in this book - we refer 
to the section \ref{ord} to more complete list. For the simplicity in this section 
we restrict ourselves 
by the most typical one, namely
DEGLEX, where the monomials first are compared by their length and  
then (if the lengths are equal) lexicographically.
 For example, if $x>y>z$ is
 our ordered alphabet, then  we have
 $$1 <z<y<x< zz<yz<yy<xz<xy<xx<\,.\,.\,.$$
 in the commutative DEGLEX   and
$$1 <z<y<x< zz<zy<zx<yz<yy<yx<xz<xy<xx<zzz\,.\,.\,.$$ in the non-commutative.

Having an ordering we always can choose a leading monomial $lm(u)$ for a given nonzero 
element $u\in\mathcal{A}$, i.e. the
highest monomial $f$ which has nonzero coefficient $\alpha_f$ in the 
expansion $u=\sum \alpha_g g$ in our 
monomial basis. The coefficient itself we will call the leading coefficient and 
denote it as  $lc(u).$
For example if $u= xy+3y^2+4z^2$ in one of the orderings above then  $lm(u)=xy, lc(u)=1.$

Let $I$ be an ideal generated in $\mathcal{A}$ by some set $R, I=(R).$ If $R$ consists of 
the homogeneous elements
 (and this is the main case in {\bf bergman}) then  the factor-algebra  $A=\mathcal{A} /I$ 
is a graded algebra,
$$A=\oplus_{n=0}^{\infty}A_n,\ A_n\cdot A_m\subseteq A_{n+m}$$
and its Hilbert series $H_A$ is defined as
$$H_A(t)=\sum_{i=0}^{\infty} \dim A_nt^n.$$
The Hilbert series is a rational function for the commutative case, but not necessarily 
in non-commutative (even when $R$ is a finite set).

The idea of the Gr\"{o}bner basis approach is to use the monomials and ordering 
in $\mathcal{A}$ for representing the base,
multiplication table and calculating the Hilbert series of the factor-algebra $A.$ 

It is quite natural to identify elements of $A$ with the linear combination of monomials, 
but the main trouble is
that different linear combinations can represent the same element. To avoid this problem 
let us introduce the notion of the
normal monomial.  A monomial $f$ is normal (relative ideal $I$ and admissible ordering) 
if it cannot be rewritten
in a factor-algebra as a linear combination of the lower monomials. It is easy to show 
that the normal monomials
form a $K-$base for the factor-algebra $A.$

 For example, if $R$ consists of the monomials only (in this case we speak about the 
monomial algebra $A$) then
a monomial $f$ is normal if and only if it is not divisible by any of monomials in $R.$ 
The situation is more complicated
in the general case, especially if the algebra is non-commutative and relations are not 
homogeneous - in this case
the problem to decide if the given monomial is normal is algorithmically undecidable! 

Fortunately in the cases where {\bf bergman}  mainly works such an algorithm exists and it 
is the algorithm based on
Gr\"{o}bner basis calculations that is implemented here.

The shortest way to  define  a Gr\"{o}bner basis  $G$ for an algebra $A$ (more exactly for 
an ideal $I$)
 is to say that it is a subset of $I$ with the property
that any monomial that  is not divisible by  any leading monomial $lm(g)$ for $g\in G$ is 
normal. From this definition
we see that for monomial algebra $A=\mathcal{A}/(R)$ the set $R$ of the monomials is a 
Gr\"{o}bner basis.  This leads to the main idea: to replace
an arbitrary algebra $A$ by a monomial algebra $B=\mathcal{A}/(S)$ which has the same set 
of normal monomials (and, as result,
the same Hilbert series) but  is much easier to work with. The set of monomials $S$ is 
nothing else than the set
of leading terms $\{ lm(g), g\in G\}. $

The multiplication tables for $A$ and $B$ are, of course, different, but knowing the 
Gr\"{o}bner basis it is easy to find a multiplication in
$A$ too. First we explain the notion of normal form. If a monomial $f$ is not normal it 
is divisible by some $lm(g)$.
Because $g=0$ in $A$ we can replace the factor $lm(g)$ by the linear combination of lower 
monomials getting the same element 
in  $A.$ The same procedure can be applied to those new monomials which are still not normal. 
Because the ordering is admissible
this process should stop and we will obtain a linear combination of normal monomials, which by 
the definition is a normal form
 of the original  monomial. Normal form of the normal monomial $f$ is naturally $f$ itself 
and we can extend the notion of normal
form to any element $u\in \mathcal{A}.$ The process, described above is called the reduction 
(to normal form). The important property of the reduction
is that the result is independent of way in which the reduction is performed. For example if 
there are two different factors
$lm(g),lm(h)$ dividing $f$ it does not matter which of this factor we start with, the final 
result will be the same.

This property gives the alternative definition of the notion Gr\"{o}bner basis. The process 
of reduction, described as above can be applied to any
subset $G\subseteq I$ (when the monomial is called normal in case it is not divisible by 
any $lm(g)$). If the result of the
reduction is uniquely defined for any element $u\in\mathcal{A}$ the set $G$ is a Gr\"{o}bner 
basis.

This also leads to the algorithm of the constructing the Gr\"{o}bner basis starting from the 
arbitrary set $R,$ generating $I.$  We put $G=R$ and
check possible monomials.
If we get
two different reduction result from the same monomial we simply add the difference between 
them to the set $G$ and repeat the check again
until all the reductions will be the same. Exactly this (but in a smarter way) degree by 
the degree
 does   {\bf bergman} during the calculations.

Note that the normal form of a given element $u\in \mathcal{A}$ is zero if and only 
if $u\in I,$ so we decide  if two elements are equal in $A,$
if we know a Gr\"{o}bner basis -- their normal forms should be equal. We know how to 
construct the multiplication table in $A:$ normal monomials form
a $K-$base and the reduction to the normal form calculates the product of two normal 
monomials.

We refer to  Chapters {1, 2} for examples, but note that Gr\"{o}bner bases theory has in 
reality much more applications: the art is to translate
the mathematical problem to the corresponding factor-algebra problem and to see how 
Gr\"{o}bner basis can be used here. The user can find some
examples here, but much more advanced applications are 
in  \cite{Adams, Becker, Frob, Green, Kreuzer, Mora, Pfister, Sturm }.



