%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Copyright (C) 1995,1996,1998 Joergen Backelin
%%
%% Bergman is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY.  No author or distributor
%% accepts responsibility to anyone for the consequences of using it
%% or for whether it serves any particular purpose or works at all,
%% unless (s)he says so in writing.  Refer to the Bergman General
%% Public License for full details.

%% Everyone is granted permission to copy, modify and redistribute
%% bergman, but only under the conditions described in the
%% Bergman General Public License.   A copy of this license is
%% supposed to have been given to you along with bergman so you
%% can know your rights and responsibilities.  It should be in a
%% file named copyright.  Among other things, the copyright notice
%% and this notice must be preserved on all copies.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


	Module specifications for bergman0.9.

 Recall that the mode-changing mechanisms of bergman mainly work
by exchanging certain procedure definitions.

 The "modules" communicate by means of certain "imported" and
"exported" routines.  (They are not truly different from the other
procedures in actual programming, but the programmer should
respect this "modularisation" or else risk chaos.)  To this is
added a number of macros, which only to a very limited extent are
treated here.  Whenever variants of the same "communicating"
procedures for different modes are implemented (in different files
or not), it is the responsibility of this part of the source to
guarantee that the procedures perform according to the subsequent
protocol, and that the appropriate mode-changing procedures will
substitute the appropriate procedure definitions.

	......


 The files mentioned here should be found on the src subdirectory of
the bergman top directory, if not otherwise stated.

 The procedures whose names do not contain lower case letters
are (also) intended for interactive use of any bergman user, and
thus should be specified in the manual or document files.

 The macros are only available if the appropriate macro files are
loaded.  The macros described here (and some others) are found in
macros.sl, unless otherwise stated.



	THE COEFFICIENT MODULE

    Files: coeff.sl, char0.sl, char2.sl, odd.sl, logodd.sl, sfcf.sl.

    Information about coefficient handling:

 The actual changes of coefficient domain are handled by coeff.sl
routines.  The different coefficient domain procedures are written
in separate files for separate set-ups:

	File		Contains

	char0.sl	Characteristic 0 (field: Q)
	char2.sl	Characteristic 2 (field: Z/2Z)
	odd.sl		Odd prime characteristic (field: Z/pZ)
	logodd.sl	As odd.sl, but using `modular logarithms'
	sfcf.sl		The most general Reduce context coefficients:
			standard formns. Only available in Reduce
			variants of bergman.

 (Other procedures may be modified in some positive characteristic.
In these cases, the Char0 version is regarded as default (and thus
is used in case of no separate definition).)

 The files closely correspond to the corresponding coefficient domain
modes. In the odd characteristic modes, there is a run time compilation
of the appropriate procedures, governed by instructions in coeff.sl.
If the MODLOGARITHMS switch is ON, some `logarithm look-up tables' are
used.  These may be created dynamically by separate scripts and saved
on the domains subdirectory of the bergman root directory, or on some
other directory, as determined by the values of the global variables
MAKEPRIMEFILE!* and PrimeFilePreAmble.

 Each of the domain mode files is responsible for maintaining/exporting
the following structures/procedures:


    Structures:

 There are two fundamental mathematical concepts for the polynomials,
the coefficient field and the coefficient domain. We always assume
that the polynomial base ring is a (commutative) field. The
coefficient domain may consist of the entire field, or of a proper
subring such that the coefficient field is its field of fractions.
In either case, the normal forms of S-polynomials are only assumed
to be used for testing whether or not they are zero, and as reductor
polynomials; thus they may be replaced with associated polynomials;
and indeed, ordinarily they are. Therefore it is sufficient to use
coefficient domain elements in the calculation of such normal forms. 

 On the other hand, if you really need the normal form of a
polynomial, then there may appear denominators. Therefore we added
'ratio' (or rate) coefficients and polynomials with a ratio
coefficient factor as structures, but use them only in connection
with such 'absolute' normal forms.

 A principal example is the default case, where the coefficient field
(Q) consists of the rational numbers, and the coefficient domain (Z)
of the integers. The 'ratio coefficients' are just the (non-zero)
rational numbers. (Recall that here 'rational' refers to the 'ratio'
or proportion of two integers; which we consider as their quotient.)

 Input, LispForm, Output coefficients are either integers or
Reduce standard forms (as yet).


 There are two internal representations of (non-zero) domain elements:
redandcoeffs (reductand coefficients) and redorcoeffs (reductor
coefficients). (See the 'polynomials' section for an explanation of
the difference.)

 Redandcoeffs represent non-zero coefficients in reductand polynomials.

 Redorcoeffs represent non-zero coefficients in reductor polynomials.

 (There are never zero coefficients in reductand or reductor
polynomials.  If a coefficient operation 'mathematically' should
return a zero redandcoeff or redorcoeff, it returns NIL.  On the
other hand, it is guaranteed that redandcoeffs and redorcoeffs
are non-NIL.
 Tests whether or not a coefficient is NIL should only be done by
the specified macros.)

 Ratcoeffs ('ratio' coefficients) represent non-zero quotients of
coefficient domain elements. A ratcoeff has a numerator and a
denominator part; they are redandcoeffs. It is extremely important
that the ratcoeff parts be not accessed by other means than the
appropriate (coefficient domain dependent) procedures, since they
may be represented in radically different manners for different
coefficient domains. (E.g., if the coefficient domain coincides with
the coefficient field, we might or might not represent ratcoeffs
internally as (single) redandcoeffs, returning 1 (the unit) for
all their denominators.)

    Procedures:

    Coefficient domain independent or changing:

 DomainInit ( ) : - 
    Called after all mode setting and after reading in input,
    this procedure performs whatever further initiation
    necessary from the coefficient domain module point of view.

 AddTo!&Char0Lists (List1:lprocedure, List2:lprocedure) : - ;
    List1/List2 are added to lists of procedures which are to be
    redefined/undefined when the coefficients are set to Q.
    (The procedure foo will be redefined by replacing its definition
    by the definition of Char0foo.)

 SETMODULUS (name:field-descriptor) : field-descriptor ; !! HAS CHANGED; DOCUMENT THIS !!
    name should be some way to denote what to use for the new
    coefficient field. Legal values right now are: NIl or
    0 (denoting the field Q of rational numbers); and a
    prime p (denoting the Galois field with p elements).
    If bergman is running under Reduce, the identifier SF
    also is a legal value; denoting that Reduce "Standard
    Forms" be considered as representing the coefficient
    domain elements. (The correctness of the input need not be
    checked. Likewise, if the SF alternative is used, there need
    not be a check of the Reduce set-up.) The coefficient field
    is set to name. If name is an odd prime, then the field may
    or may not be of `logarithmic' type, depending on whether
    the switch MODLOGARITHMS was on or off.

 SETMODULUS2 : - ;
    The same effects as with (SETMODULUS 2).

 RESTORECHAR0 : - ;
    The same effects as with (SETMODULUS 0).

 SETREDUCESFCOEFFS ( ) : - ;
    The same effects as with (SETMODULUS SF).
    (Only active for bergman under Reduce.)

 GETMODULUS ( ) : field-descriptor ;
    Returns the characteristic of the coefficient field, or SF
    if the coefficients are standard forms. (Characteristic 0
    may be represented by NIL.)

 DENSECONTENTS ( ) : - ;
    In coefficient modes where the coefficient domain differs
    from the coefficient field, search for the content of a
    polynomial (and factor out this content if it is non unit)
    rather often.
    Not only may affect the current coefficient mode, but
    also any coefficient mode with domain different from field
    which is set later in this bergman session.

 SPARSECONTENTS ( ) : - ;
    In coefficient modes where the coefficient domain differs
    from the coefficient field, search for the content of a
    polynomial (and factor out this content if it is non unit)
    rather seldom.
    Not only may affect the current coefficient mode, but
    also any coefficient mode with domain different from field
    which is set later in this bergman session.


    Coefficient domain dependent (all of whom may be RESET):

 REDANDCF!+ (Cf1:redandcoeff, Cf2:redandcoeff) : redandcoeff ;
 REDANDCF!- (Cf1:redandcoeff) : redandcoeff ;
 REDANDCF!-!- (Cf1:redandcoeff, Cf2:redandcoeff) : redandcoeff ;
 REDANDCF!* (Cf1:redandcoeff, Cf2:redandcoeff) : redandcoeff ;
 REDANDCF!/ (Cf1:redandcoeff, Cf2:redandcoeff) : redandcoeff ;
 REDANDCFREMAINDER (Cf1:redandcoeff, Cf2:redandcoeff) : redandcoeff ;
 REDANDCFDIVISION (Cf1:redandcoeff, Cf2:redandcoeff) : dpredandcoeff ;
    Perform the operations addition, negation ( = "unary minus"),
    subtraction, multiplication, truncated division, taking of
    remainder with respect to truncated division, and lastly
    performing both these operations at once, yielding an output
    (Cf3 . Cf4) (where Cf3 is the resulting truncated quotient and
    Cf4 the remainder). As always, NIL represents zero in the output.
    Zero input is not permitted.
    The 'truncated division' and 'taking remainder' operations should
    be compatible in the sense that
	Cf1 = Cf2 * Cf3 + Cf4,
    and the division should be exact (whence the remainder should
    be zero) whenever possible.

 REDANDCFNEGATIVE (Cf:redandcoeff) : boolean ;
    Returns T if there is a meaningful concept of "negativity" in the
    coefficient domain and Cf is negative; NIL else.

 RATCF2NUMERATOR (Cf:ratcoeff) : redandcoeff ;
 RATCF2DENOMINATOR (Cf:ratcoeff) : redandcoeff ;
 REDANDCF2RATCF (Cf:redandcoeff) : ratcoeff ;
 REDANDCFS2RATCF (Cf1:redandcoeff, Cf2:redandcoeff) : ratcoeff ;
    Converters between ratcoeffs and redandcoeffs. The first two
    return the numerator and denominator parts of their argument.
    REDANDCFS2RATCF constructs and returns a ratcoeff corresponding
    to the quotient of the coefficient domain elements represented
    by the arguments. REDANDCF2RATCF constructs and returns a
    ratcoeff representing the same element as does its argument.
     The procedures in general are NOT reversible: e.g.,
    RATCF2NUMERATOR (REDANDS2RATCF (Cf1,Cf2)) need not represent the
    same element as Cf1 does.

 RATCF!- (Cf:ratcoeff) : ratcoeff ;
    Perform negation ( = unary minus).

  NOTE: Using these explicit REDANDCF and RATCF calling procedures
	in most cases would be very slow compared to ordinary
	operations; thus they should be avoided.

 InCoeff2RedandCoeff (InCf:in_form_coefficient) : genredandcoeff ;
    Returns the internal (redand) form of InCf, if it does not
    represent zero; NIL else.

 RedandCoeff2OutCoeff (Cf:redandccoeff) : out_form_coefficient ;
 RedorCoeff2OutCoeff (Cf:redorccoeff) : out_form_coefficient ;
    Returns the out form of Cf, if Cf is non-NIL.
     (Modifying the output might modify Cf and should thus be
    made ONLY if Cf never will be re-used.)
     The value is undefined if Cf is NIL. This might or might
    not be signalled by an error.

 RedorCoeff2RedandCoeff (Cf:redorcoeff) : redandcoeff ;
    Returns the redand form of Cf.
     (Modifying the output might modify Cf and should thus be
    made ONLY if Cf never will be re-used.)

 RedandCoeff1!? (Cf:redandcoeff) : bool ;
 RedorCoeff1!? (Cf:redorcoeff) : bool ;
    Returns T if its arguments represents 1; NIL else.

 ((OBSOLETE:
 RedandCoeffPlus (redandcoeff, redandcoeff) : redandcoeff/NIL ;
    Returns the redandcoeff representation of the sum of the
    two coefficients, if this is non-zero; NIL if the sum is 0.))

 SHORTENRATCF (Cf:ratcoeff) : ratcoeff ; DESTRUCTIVE
    Changes Cf to a "simple" representative for the same coefficient
    field element, and returns this changed input. (Thus destructive.)
    If the coefficient domain comprises an algorithm for calculating greatest
    common divisors, the "simple" representative may be achieved by factoring
    out the GCD of the numerator and the denominator parts from both.


 Matrix line, i.e., list, operations: The objects are lists of
generalised (reductand or reductor or ratio) coefficients, i.e., of such
coefficients (representing non-zero domain field elements) and of NIL
(representing 0).

 INTEGERISE (Line:lgenratcoeff) : ratcoeff ; DESTRUCTIVE
    Each (non-NIL) ratcoeff in Line is replaced by a redandcoeff,
    representing some c times the element which the ratcoeff
    represents, using the same c for the whole list. Returns c.
    (Should not be called if Line does not contain some non-NIL
    entry.?)

 RedandLine2RedorLine (Line:lgenredandcoeff) : redorcoeff ;
    Changes each non-zero (i.e., non-NIL) entry in Line to a
    redorcoeff representing (the same element as before) / (a constant c).
    The first entry of the argument must be non-zero. This need not
    be checked.
    Returns the redorcoeff representation of c.
    Destructive.

 ReduceLineStep (L1:lgenredandcoeff, Tl:lgenredandcoeff, Tl2:lgenredorcoeff) :
		red??coeff ; DESTRUCTIVE (1,2)
    L1 should be a (reductand) line; Tl1,
    a tail part of L1; and the Tl2, the non-trivial tail part
    of a (reductor) line L2. The tail parts should have the same
    lengths, so that the CAR's of the second and of the third
    argument correspond to elements in the same column (the i'th,
    say). Both of these elements should be non-zero.
    (Correct input forms need not be checked.)
    The procedure changes the entries of L1 to represent a linear
    combination  a * L1 + b * L2 , with zero i'th entry but with
    a and b non-zero.
    Returns the red??coeff representation of a.
    Destructive.



 Polynomial (characteristic dependent) operations:

 PolNum (Pol:qpol) : redandcf ;
    Extract the numerator of the ratcoeff factor of Pol.

 PolDen (Pol:qpol) : redandcf ;
    Extract the denominator of the ratcoeff factor of Pol.

 (( THE FOLLOWING TWO SEEM UNNECESSARY AND INCONSISTENT WITH GOOD
    MODULARISATION:
   -- PutPolNum (qpol, redandcoeff) : - ;
   --    Replace the numerator of the ratcoeff factor of qpol by
   --    redandcoeff. Destructive.

   -- PutPolDen (qpol, redandcoeff) : - ;
   --    Replace the denominator of the ratcoeff factor of qpol by
   --    redandcoeff. Destructive. ))

 mkQPol () : qpol ;
    Create and return a new (but incomplete) quotpol, with null
    pure polynomial part. The ratcoeff factor of the result
    represents the unit of the coefficient field.

 Num!&Den2QPol (Cf1:redandcoeff, Cf2:redandcoeff) : qpol ;
    Create and return a new (but incomplete) quotpol, with null
    pure polynomial part. The ratcoeff factor of the result
    represents  Cf1 / Cf2 ; (or rather, more precisely, represents
    the quotient in the coefficient field of the coefficient domain
    elements represented by Cf1 and Cf2).
     Note that PolNum and PolDen on qpol not necessarily return
    these arguments; some kind of "factoring out" may or may not
    occur!

 Num!&Den!&Tm2QPol (Cf1:redandcoeff, Cf2:redandcoeff, Tm:cfmon) : qpol ;
    Create and return a new (complete) quotpol, whose pure
    polynomial part represents Tm. The ratcoeff factor of the
    result represents  Cf1 / Cf2 .
     Note that PolNum and PolDen on qpol not necessarily return
    Cf1 and Cf2; some kind of "factoring out" may or may not occur!

 Tm2QPol (Tm:cfmon) : qpol ;
    Create and return a new (complete) quotpol, whose pure
    polynomial part represents Tm. The ratcoeff factor of the
    result represents the unit of the coefficient field.

 QPol2LRatTm (Pol:qpol) : ratterm ;
    "A combined converter procedure. Should yield a (RatCf . AugMon)
    term pair, with parts accessible by the ordinary macros for terms."
	IMPROVE THE DEFINITION.

 ILLOGICAL: BOTH following procedures are destructive !!??
 Redand2Redor (Pol:pureredand) : pureredor ; DESTRUCTIVE7
    Changes Pol to a reductor, and returns this. Pol must not
    represent the 0 polynomial; this need not be checked.

 DestructRedor2Redand (Pol:pureredor) : - ; DESTRUCTIVE
    Changes Pol to redand. (Might not be feasible if specific
    memory block for redors??)

 PreenRedand (Pol:pureredand) : - ; DESTRUCTIVE
    Changes Pol, fixing whatever the characteristic and other
    mode settings or switches may demand.

 PreenRedor (Pol:pureredor) : - ; DESTRUCTIVE
    Changes Pol, fixing whatever the characteristic and other
    mode settings or switches may demand.

 PreenQPol (Pol:qpol) : qpol ; DESTRUCTIVE
    Changes Pol, fixing whatever the characteristic and other
    mode settings or switches may demand.
     Returns the changed input. (Destructive.)

 ReducePolStep (Pol1:augredand, Place:redandposition, Pol2:pureredor,
		MonQ:monquot) : - ; DESTRUCTIVE (1 2)
    Changes Pol1. Subtracts (a multiple of) MonQ times Pol2
    from Pol1, cancelling the next monomial AFTER the
    position Place (within Pol, thought of as a list of terms),
    which SHOULD be MonQ times the leading monomial of Pol2.
    The latter need not be checked.
    May also multiply Pol1 by a non-zero constant.

 NormalFormStep (Pol1:qpol, Place:redandposition, Pol2:pureredor,
		 Mon:monquot) : - ; DESTRUCTIVE (1 2)
    Changes Pol1. Subtracts (a multiple of) MonQ times Pol2
    from Pol1, cancelling the next monomial AFTER the
    position Place, which SHOULD be MonQ times the leading
    monomial of Pol2. The latter need not be checked.

 SubtractRedand1 (Pol:augredand, Place:redandposition,
		  Pol2:pureredor) : - ; DESTRUCTIVE (1 2)
    Changes Pol1. Subtracts (a multiple of) Pol2 from Pol1,
    cancelling the next monomial AFTER the position Place,
    which SHOULD equal the leading monomial of Pol2. The latter
    need not be checked.
    May also multiply Pol1 by a non-zero constant.

 SubtractRedor1 (Pol1:augredor, Place:redorposition,
		 Pol2:pureredor) : - ; DESTRUCTIVE (1 2)
    Changes Pol1. Subtracts (a multiple of) Pol2 from Pol1,
    cancelling the next monomial AFTER the position Place,
    which SHOULD equal the leading monomial of Pol2. The latter
    need not be checked.
    May also multiply Pol1 by a non-zero constant.

 SubtractQPol1 (Pol1:qpol, Place:redandposition,
		Pol2:pureredor) : - ; DESTRUCTIVE (1 2)
    Changes Pol1. Subtracts (a multiple of) Pol2 from Pol1,
    cancelling the next monomial AFTER the position Place,
    which SHOULD equal the leading monomial of Pol2. The latter
    need not be checked.

 RedorMonMult (Pol:augredor, MonQ:monquot) : augredand ;
    Returns MonQ times Pol.

 CFMONREDANDMULT (Cf:redandcoeff, Mon:puremon, Pol:augredand) : augredand ;
    augredand := Cf*Mon*Pol (non-destructively and in this order).

 (( DestructRedandSimpSemiLinComb (Pol1:augredand, Pol2:augredand,
				Cf:redandcoeff) : genaugredand ; DESTRUCTIVE (1 2)
    Returns Pol1 + Pol2 * Cf, destroying both input augredands.
    [Might be removed from the protocol?] ))

 DestructQPolSimpSemiLinComb (Pol1:qpol, Pol2:qpol,
			      Cf:ratcoeff) : quotpol/NIL ; DESTRUCTIVE (1 2)
    Returns Pol1 + Pol2 * Cf, destroying both input qpols.

 DestructRedandCoeffTimes (Pol:augredand,
			   Cf:redandcoeff) : - DESTRUCTIVE (1)
    Destructively multiplies each coefficient in Pol with Cf.

 DestructQPolCoeffTimes (Pol:qpol , Cf:ratcoeff) : - ; DESTRUCTIVE (1)
    Destructively multiplies each coefficient in Pol with Cf.

 DestructChangeRedandSign (augredand) : augredand ;
    Destructively replaces each coefficient in Pol with its
    negation. Returns its (changed) input.

 SHOULD THE cfmon BELOW BE A ratcfmon???:
 DestructQPolTermPlus (Pol:qpol, Tm:cfmon) : augqpol ; DESTRUCTIVE (1)
    Destructively adds Tm to Pol; returns the changed Pol
    (or NIL, if this represents 0).

   Global variables:

 REDANDCOEFFONE = the reductand representation of the unit in the
		coefficient domain.


	THE MONOMIAL MODULE

    Files: monom.sl, ncmonom.sl.

    Structures:

 LispForm monomials are lists of exponents / of variable indices
in the commutative / non-commutative case.

 Puremonomials and augmonomials both represent the (monic, i.e.,
coefficient free) monomials.  The augmonomials are used in the
terms (summands) of the reductand and reductor polynomials.  It is
possible to get the augmonomial form from the pure one, and vice
versa; but information about the monomial pointer or associated
monomial flags or properties are directly accessible only from
the augmonomials.  "Aug" stands for "augmented", referring to the
extra information connected with the monomial.
 An "interned" augmonomial is guaranteed unique representation in
the sense that if the (mathematically) identical monomial is
"interned" to an augmonomial twice, without an intervening
"un-interning" of the result of the first one, then the two results
test as equal by Mon!=, and have the same monomial pointer, flags,
and properties.  (In this implementation, this is achieved
uniformly in such a way that Mon!= objects are EQ (in the Lisp
sense); hence Mon!= is defined as a macro, expanding to EQ.  The
programmer should of course use Mon!=, not EQ.)  Only the RECLAIM
module procedures may "un-intern" a monomial.
 (It should be noted that the interning private structures at
present are shared by the MONOMIAL and the RECLAIM modules; this is
a deficit in the modularisation and should be amended.)

 Monomial pointers may be any valid objects.  There is one pointer
associated to each augmonomial; it is initiated to NIL.

 Monomial flags may be any valid objects.  There may be any number
of flags associated to an augmonomial; initially, there is none.

 Monomial properties have 'names' and 'values'; both may be any
valid objects.  There may be any number of properties associated to
an augmonomial; initially, there is none.  Each property has a
value.  Whenever a test by name for a given property is done, the
test name must be EQ (in the Lisp sense) to the property name in
order for the property to be recognised.

 Non-interned monomial quotients are ephemeral.  They result from
certain monomial divisions and may be used in certain subsequent
multiplications.  They are NOT assumed to be comparable with
anything else in any way.  (In fact, in the non-commutative case
they might consist of pairs of monomials, one left and one right
'factor'.)

 (There may be another non-interned monomial structure, niMon,
of ephemeral type and possible for direct access to internal
representations. This is an example of bad modularisation, and
should either be removed or defined exactly.)

 Algform output monomials may be ephemeral.  They consist of
association lists, where each association pair is of the form
(id . exp), where id is an identifier or string whose PRIN2 name
is the relevant variable name, and exp is the relevant exponent.
The exponents must be non-zero.  The association list is ordered in
the order the monomial should be printed.

 Monomial factor data encode the ways in which one monomial may be
 a factor of another.  It is NIL iff there is no such way.


    Procedures.

   Initiations and mode changers:

 MonomialInit ( );
    Called after all mode setting and after reading in input,
    this procedure performs whatever further initiation
    necessary from the monomial module point of view.


 MonCommify ( );
    Mode changer to commutative monomials (major) mode
    auxiliary.

 MonNonCommify ( );
    Mode changer to noncommutative monomials (major) mode
    auxiliary.

 MonDegLexify ( ); !!! NEW !!!
    Mode changer to TDEG-LEX monoid order (minor) mode auxiliary.
    (In case NON-COMMUTATIVE mode is active, its effects may be
    notable first at switch back to COMMUTATIVE mode.)

 MonPureLexify ( ); !!! NEW !!!
    Mode changer to LEX monoid order (minor) mode auxiliary.
    (In case NON-COMMUTATIVE mode is active, its effects may be
    notable first at switch back to COMMUTATIVE mode.)

 MonRevLexify ( ); !!! NEW !!!
    Mode changer to TDEG-REVLEX monoid order (minor) mode auxiliary.
    (In case NON-COMMUTATIVE mode is active, its effects may be
    notable first at switch back to COMMUTATIVE mode.)


   Input and output support:

 MONINTERN (lispform_monomial) : augmon ;
 MONLISPOUT (puremon) : lispform_monomial ;
 MonAlgOutprep (puremon) : algform_output_monomial ;
    Converters.

   Other procedures:

 MONLESSP (Mon1:puremon, Mon2:puremon) : bool ;
    Undefined (possibly erroneous) if Mon1 and Mon2 represent the
    same monomial or are of different total-degrees. Else, non-NIL
    iff Mon1 is less than Mon2 with respect to the active monoid order.

 MONTIMES2 (Mon1:puremon, Mon2:puremon) : augmon ;
    The output represents the product Mon1 * Mon2 (in the given order).
    NOTE: In the non-commutative case, this is mostly NOT what we need.

 MonTimes (Mon:puremon, MonQ:monquot) : augmon ;
    Return the "product" of its argument in the appropriate manner.
    In other words: MonQ should be the result of "quoting out"
    a monomial, m1, from another, m2. MonTimes should be inverse of
    this operation, so that if Mon represents m1 then the
    output represents m2.

 niMonQuotient (Mon1:puremon, Mon2:puremon) : monquot ;
    Mon1 must be (or formally: represent) a factor of Mon2. The
    return data should be sufficient for restoring Mon2 from Mon1.

 MONFACTORP (Mon1:puremon, Mon2:puremon) : mon_factor_data ;
 PreciseniMonQuotient (Mon1:puremon, Mon2:puremon,
		       Pos:mon_factor_data) : monquot ;
 TOTALDEGREE (Mon:puremon) : degree ;
    These do what you expect. The extra data Pos given to
    PreciseniMonQuotient may be used in order to specify IN WHAT
    POSITION Mon1 is to be considered as a factor of Mon2, in the
    non-commutative case.


   New procedures (to write):

 MonSignifVar (Mon:augmon) : varno ;
    Return the "index" of the "most significant" variable present in
    Mon. The "index" and the concept "most significant" would be module
    and perhaps implementation dependent. It is however guaranteed that
    indices for the same variable are EQ. Mon mustn't represent 1.

 MonLeastSignifVar (Mon:augmon) : varno ;
    Return the "index" of the "least significant" variable present in
    Mon. The "index" and the concept "least significant" would be module
    and perhaps implementation dependent. It is however guaranteed that
    indices for the same variable are EQ. Mon mustn't represent 1.

 RestOfMon (Mon:augmon) : augmon ;
    The output represents a quotient of Mon and its
    "most significant variable".


   New structure (to write): MONONE = the augmented monomial representing
 the unit in the coefficient domain. WRITTEN IN nc CASE.

  (Not so well modularised procedures:

 niMonIntern ( ) : augmon ;
    Convert the ephemeral niMon puremon to an augmon.
 
 LCorOUT (puremon1 puremon2), et cetera: Badly modularised?
Strategy seems to depend fairly strongly on commutative/non-dito
mode.
)


   Macros:

 PMon (Mon:augmon) : puremon ;
 Mpt(Mon:augmon) : monomial_pointer ;
    Converters.

 Mon!= (Mon1:augmon, Mon2:augmon) : bool ;
    Do Mon1 and Mon2 represent the same monomial?

 Mon!? (Input:any) : bool ;
    Is Input an augmented monomial? NOT guaranteed correct result
    in general. However, it is guaranteed that the return value
    NIL means "no", and that the answer is correct for atoms.

 PutMpt (Mon:augmon , Input:any) : -
    Set the monomial pointer of Mon to Input.

 Mpt!? (Mon:augmon) : bool ;
    Is the monomial pointer of Mon non-NIL?


	THE POLYNOMIAL MODULE

    File: polynom.sl


   Structures:

 (Recall that two polynomials are associated if one of them is
a unit times the other; and that the units in our polynomial
ring are the non-zero elements in the field of coefficients.)

 Most polynomials encountered in Groebner reductions are
defined 'up to association' and thus may be represented as
"domain polynomials", polynomials all whose coefficients
belong to the coefficient domain. 

 General polynomials (where the coefficients are any field
elements) must be considered e.g. in some resolution
calculations.

 Internally, domain polynomials are represented in two ways,
as reductand polynomials (redands) or as reductor polynomials
(redors). Redands may be reduced in normal form processings,
by means of redors. (Mathematically, the result of a
reduction step need not be a domain polynomial; however,
there are always associated domain polynomials to the
result.) In general, the redands are more ephemeral.
(In a good memory handling, the redors might be stored in
blocks which not so often were garbage collected. In the
present implementation, they are not.) The coefficients may
be represented in quite different manners. They should
be non-zero; any procedure which logically could yield a
zero polynomial should yield NIL instead of this, and NIL
should not be used as valid input to any procedures
expecting redand or redor arguments.

 A general polynomial may always be factorised into a
product of a domain polynomial and one general field element.
The internal representation of the polynomial corresponds to
this, being a "quotient polynomial" (qpol) with one pure
polynomial part and one "quotient" part. The quotient is
of the ratio coefficient type (with reductand coefficients
for the numerator and the denominator parts).


 A pure (reductand or reductor) polynomial consists of terms,
which consists of (reductand or reductor) coefficients, and
(augmented) monomials. A pure quotient polynomial consists of
reductand terms, as for the reductand polynomial, and actually
is of the same type.

 An augmented (reductand or reductor) polynomial consists of a
pure polynomial and a polynomial `priority'. An 'augmented'
quotient polynomial consists of a pure polynomial and a
quotient (as described above); it is the same as a quotient
polynomial.

 A lisp form polynomial consists of a (lisp) list of lisp
form terms, each of which is a dotted pair whose CAR is a lisp
form coefficient and whose CDR is a lisp form monomial. This
may be used for any input/output handling; but shortcuts are
also permissible. (E. g., printing an augmented polynomial in
algebraic form may be done by first creating a lisp form
polynomial, or directly; but the result should not depend on
this.)

 A (redand or redor) term should always be non-zero. Different
terms in the same redand or redor should never contain the same
monomial.

   Procedures:

 OrdinaryConcPolMonMult (Place:polposition, Pol:purepol,
			 MonQ:monquot) : - ; DESTRUCTIVE (1 2)
    Changes returnstart by concatenating MonQ*Pol (which may mean
    MonQ1*Pol*MonQ2). Pol may be a pure reductand or reductor
    polynomial; Place should be the position of the last pair in a
    polynomial of the same kind.

 SubtractRedor (Pol:augredor, Mon:augmon) : - ; DESTRUCTIVE (1)
    Checks Pol for occurrences of Mon; if found, subtracts
    (a coefficient times) the reductor polynomial pointed to from
    Mon, retaining the reductor status of the changed input.
    May also multiply Pol by a non-zero constant.

 TermInsert (Tm:redandterm, Pol:augredand) :
	    redandposition ; DESTRUCTIVE (2)
    Insert a term Tm (i.e., a monomial with a coefficient) into
    Pol. This changes Pol to represent (the old Pol) + Tm; or
    to be an incomplete augredand (if the zum is zero).
    Returns the position at the term with the same monomial
    in the resulting Pol; or the position immediately after
    this one, if the occurrence of this monomial was cancelled
    by adding the term.


 REDANDMONMULT (Pol:augredand, Mon:puremon) : augredand ;
    Returns the product of Pol and Mon (in this order).
    Non-destructive.

 QPOLMONMULT (Pol:qpol, puremon) : qpol ;
    Returns the product of Pol and Mon (in this order).
    Non-destructive.


   Macros or procedures:

 mkAPol () : augpol ;
    Returns a new incomplete augpol representing the polynomial 0.
    (Thus augpol is NOT a valid argument to other operations, EXCEPT
    for inserting or concatenating terms. Since it contains no terms,
    it has neither reductand or reductor coefficients; but if
    reductands and reductors differ e.g. in memory treatment, then
    the augpol should be considered as a reductand.)


 QPol2Lm (qpol) : augmon ; ET CETERA
    Converters. [List them all; explain the mnemonics.]

 . . .



	THE INTERFACE MODULE

    Files: inout.sl, alg2lsp.sl; see also HOMOGENISATION and PAD.

	.
	.
	.

	NEW:


 PRINTRATCF (Cf:ratcoeff) : boole ;
    If Cf is a/b (with a and b relatively prime as they should),
    the procedure does one of the following
	Prints a/b and returns T if b <> 0;
	Prints a and returns T if b = 1 but a <> 1;
	Doesn't print and returns NIL if a = b = 1.
    The procedure may or may not surround the print form of a
    (and b) with parentheses, depending on the domain and
    other mode settings.

 PRINTQPOLRATFACTOR (Pol:qpol) : bool ;
    If the rational factor or "quotient" of Pol is a/b (with
    a and b relatively prime as they should), the procedure does
    one of the following
	Prints a/b and returns T if b <> 0;
	Prints a and returns T if b = 1 but a <> 1;
	Doesn't print and returns NIL if a = b = 1.
    The procedure may or may not surround the print form of a
    (and b) with parentheses, depending on the domain and
    other mode settings.



	THE 'MAIN' MODULE (main.sl)
	THE 'REDUCTION' MODULE (reduction.sl)
	THE 'STRATEGY' MODULE (strategy.sl)
	THE RECLAIM MODULE (reclaim.sl)

 These parts are not as logically and practically separated as the
other modules.  The RECLAIM module handles the conditional
'un-interning' of monomials, and also demands an ordinary reclaim
at the end-of-degree cleanup.  The un-interning of monomials should
be done differently, in the same module as the interning.  The
strategy source file handles a way of implementing the Buchberger
algorithm chriteria, and the (minor) similar work to be done in the
non-commutative case.  Some of the corresponding routines are found
in the main source file, however.  The REDUCTION module is more
pure, taking care of the reduction of a given reductand polynomial
and of the formings of S-polynomials.  The main file contains the
central (top level) procedures, but also an assorted number of
'auxiliaries' which might be better to distribute elsewhere; and
some detailed mode-changers, the details of which should properly
be left to the relevant modules.
 The latter three 'modules' coincide largely with the procedures
which are supplemented (or redefined) in the SAWS mode files.

		. . . . . . . .

  ReducePol (Pol:augredand) : genaugredand ; DESTRUCTIVE
    Changes Pol to a non-zero constant times the normal form
    of its input (with respect to GBasis). Returns NIL if the normal
    form is zero, its changed argument else.

 NORMALFORM (Pol:qpol) : genqpol ; DESTRUCTIVE
    Changes Pol to the normal form of its input (with respect
    to GBasis). Returns NIL if the normal form is zero, its changed
    argument else.

 FormSPol (Mon1:augmon, Mon2:augmon, Mon3:augmon, ?) : genaugredand ;

		. . . . . . . .


  PutLeadMonPtr
  PutLeadMonPtrsinPolList
  PutLeadMonPtrsinPolDegList
  LeadMonList2PolList
  LeadMonDegList2PolDegList
  PolList2LeadMonList
  PolDegList2LeadMonDegList
  LeadMonList2LeadMonDegList
  PolList2PolDegList

	THE HOMOGENISATION MODULE

    File: homog.sl.

 Experimental.  Contains procedures for homogenising a
(commutative) input, and for dehomogenising the output.



	THE GROWTH SERIES MODULE

    File. pbseries.sl.

 Only non-commutative mode. Contains procedures for calculating
(arbitrarily many terms in) the Hilbert series of the quotient
algebra, as well as the inverse Hilbert series, and furthemore the
double Poincare-Betti series of the associated monomial ring.

	(THE PAD

 Under development. Should contain:

 READLISPINPUT (FileIndex/NIL/T);

 SETINVARS, SETOUTVARS, SETVARS; PRINTINVARS, PRINTOUTVARS,
PRINTVARS. Intended to improve the user and window system
interfaces. Similarly, there are Reduce interface procedures
planned, which should benefit from the above.)

