From 865a78a7026917d5a6fcdbfe1b98d32df6ac1983 Mon Sep 17 00:00:00 2001
From: Tim Daly
Date: Thu, 14 Jul 2016 02:54:00 -0400
Subject: [PATCH] books/bookvol2 Add Davenport chapters
Goal: Axiom Literate Programming
---
books/bookvol2.pamphlet | 2930 ++++++++++++++++++++++++++++++++++++++++
changelog | 2 +
patch | 2 +-
src/axiom-website/patches.html | 2 +
4 files changed, 2935 insertions(+), 1 deletions(-)
diff --git a/books/bookvol2.pamphlet b/books/bookvol2.pamphlet
index 6cfea26..4f3bd3d 100644
--- a/books/bookvol2.pamphlet
+++ b/books/bookvol2.pamphlet
@@ -3,6 +3,2328 @@
\input{bookheader.tex}
\mainmatter
\setcounter{chapter}{0} % Chapter 1
+\chapter{The Axiom System by James H. Davenport}
+This is (mostly) quoted verbatim, with permission,
+from Davenport\cite{Dave92a}.
+
+\section{A little history}
+
+In 1978 the present author spent two months at IBM Yorktown Heights,
+as part of the Computer Algebra Group, which had developed the
+Scratchpad-1 computer algebra system. Though this system never saw
+the light of day outside IBM, it was at the time a competitor for
+Macsyma and Reduce. All systems had struggled with the problems of
+writing ever more complicated algebraic algorithms, and handling the
+growth of the systems. Zippel has estimated that Macsyma, at its
+heyday, contained six different Gaussian elimination algorithms,
+whether because they were handling different data types, or because
+the authors were unaware of the other ones, or for more subtle
+reasons. Davenport\cite{Dave81} had been having similar problems with Reduce,
+and a feeling of discontent among algorithm implementors was common.
+
+The reactions of the computer algebra system-builders to the
+complexity are interesting to tabulate.
+
+\begin{tabular}{rp{11cm}}
+Macsyma & embarked on the, ultimately futile, ``new rational function''
+project, which was to have re-written much of the algebraic kernel in
+a more mathematically structured way, but which was unable to maintain
+backwards compatibility.\\
+Reduce & developed into Reduce 3, with its concept of domains , which
+meant that new constant domains could be added relatively simply
+See Bradford et al.\cite{Brad86}\\
+Waterloo's & emerging team decided that none of the existing solutions
+was right, and opted for a new design based round a very small kernel,
+typically not knowing any algebra, and loadable modules, which would
+contain the algebraic knowledge of the system. This became the Maple
+system. Over the years, the definition of the kernel has changed, as it
+became obvious that certain algorithms, e.g. modular ones, could not
+be implemented efficiently in the interpreted modules.\\
+MuMath & and its successor Derive based themselves on the philosophy
+that ``whatever fitted on a PC'' was much closer to most users'
+requirements than ``the best possible mathematics'', and, in terms of
+the number of users, they are certainly correct.\\
+IBM &embarked on a lengthy period of algebraic reflection, prototyping
+and experimentation, sporadically reported in the literature
+Davenport \& Jenks\cite{Dave81a} and Jenks \& Trager\cite{Jenk81}
+first product of this process). Axiom is the end product of this
+process of reflection.
+\end{tabular}
+
+\section{Axiom's philosophy}
+
+Axiom shares with Maple the desire to build a system consisting of a
+kernel and loadable modules, written in an appropriately high-level
+language: the kernel knows very little algebra (in the classical sense
+of the term) and the modules define what algebraic facilities are
+present. The resemblance ends here, though. Maple's modules are
+interpreted, sacrificing the ultimate in performance for small size and
+rapid loading, whereas Axiom's modules are compiled into machine code
+for speed, much as in Reduce or Macsyma, but also for type analysis
+and constructing the database for the information system. There are
+certainly arguments in favour of Maple's approach, though it does
+assume that the designers know {\sl a priori} which primitives to build into
+the kernel to make a fast algebra system. Hence Maple is relatively
+fast at those operations for which it was designed, but attempts to
+make it into, say, a computational group theory package, have not been
+particularly successful, since the inner loops have been taking place
+in interpreted code. Another difference is, regrettably, that Axiom's
+kernel is currently far larger than Maple's, largely due to the
+genericity of the type system it implements.
+
+Axiom's kernel designers took the view that they did not know what
+algebraic facilities would be wanted, nor how they would be
+programmed. The only real assumption made was that the computations
+would be largely symbolic, and hence big integers, lists, vectors and
+trees were emphasised over, say, the efficient compilation of
+fixed-precision floating-point, which is left to externally-compiled
+code. There are also assumptions in the user interface about the wish
+to convert symbols into polynomials where appropriate, but these are
+in fact not fixed. The graphics facilities provided are more oriented
+towards the production of graphs of functions than other kinds of
+illustrations, but new facilities could easily be added.
+
+{\bf Principle 1}. {\sl AXIOM has an interpreter for interactive use, much
+like any other system, and a compiler for creating new user-defined
+data types. The compiler emphasises strict type-checking, whilst the
+interpreter is more oriented towards ease of use.}
+
+The complexity of the algebraic facilities envisaged for Axiom
+required a data-typing mechanism over and above that provided by
+Lisp. To quote a very simple example, $1 + x + x^2$ could be either a
+polynomial or a truncated Taylor series, but the square of the
+polynomial is $1 +2x +3x^2 +2x^3 + x^4$ whereas the square of the
+series is $1+2x +3x^2$. Similarly, if 2 represents the integer 2,
+then $2+2 = 4$, whereas if 2 represents the congruence class ``integers
+congruent to 2 modulo 3'' then $2 + 2 = 1$ (and, of course, $4 = 1$ as
+well). Similarly, the list (1,2) is not the same as the list (2,1),
+but they should be regarded as the same if they represent (unordered)
+sets, and so on. In fact, the data typing requirements
+of computer algebra are so dynamic -- the authors cannot predict what
+types the users will call for, explicitly or implicitly -- and so rich
+that no existing language was suitable for expressing them. Hence the
+decision was taken that Axiom would have its own independent typing system.
+
+This typing system, which underpins much of the rest of Axiom, has to
+solve the problems that Macsyma and Reduce have. Macsyma's typing
+system suffers, essentially, from the $n^2$ problem -- every type has to
+know about every other type. This works when there are only a few
+types, and Macsyma has ``general expression'', ``rational function''
+(printed with /R/ ), and ``Taylor series'' (printed with /T/ ): adding
+more types would be difficult.
+
+Reduce's method of specifying domains is largely global: for example
+one specifies the modular domain by issuing the command {\tt on modular;}.
+One has then to be sure that all calculations are intended to be
+modular and that values being computed will not later be used as
+polynomial exponents, loop indices or whatever. There is much scope
+for hard-to-detect bugs in this area. The other drawback of Reduce's
+scheme is that it really only applies to {\sl constant} domains. This works
+well for floating point or complex coefficients, but has its weaknesses
+when it comes to handling Taylor series. For example
+\begin{verbatim}
+1: load tps; % truncated power series;
+
+\end{verbatim}
+\begin{verbatim}
+2: ps(cos x,x,0);
+
+ 1 2 1 4 1 6 7
+{1 - (---)*X + (----)*X - (-----)*X + O(X )}
+ 2 24 720
+
+\end{verbatim}
+\begin{verbatim}
+3: ws-1;
+
+ 1 2 1 4 1 6 7
+{ - (---)*X + (----)*X - (-----)*X + O(X )}
+ 2 24 720
+
+\end{verbatim}
+\begin{verbatim}
+4: ps(sin x,x,0);
+
+ 1 3 1 5 7
+{X - (---)*X + (-----)*X +O(X )}
+ 6 120
+
+\end{verbatim}
+\begin{verbatim}
+5:ws-x;
+
+ 1 3 1 5 7
+ - X + {X - (---)*X + (-----)*X +O(X )}
+ 6 120
+
+\end{verbatim}
+\begin{verbatim}
+6: ws 4 - ps(x,x,0);
+
+ 1 3 1 5 7
+ - (---)*X + (-----)*X +O(X )}
+ 6 120
+
+\end{verbatim}
+
+The spurious power series expansion at line 6: is necessary to avoid
+the confusion at line 5:, where the variable $x$ is separated from
+the power series in $x$.
+
+\section{Axiom's typing scheme}
+
+The typing scheme of Axiom can be described as a two-level typing
+scheme with single inheritance of types and multiple inheritance of
+meta-types. What does this mean, when stripped of the jargon? The first
+piece of jargon we wish to remove is the word ``type'', which is so
+heavily used in computer science that it has practically ceased to
+have any meaning at all. The word that most nearly corresponds in
+Axiom is the word domain, as we shall see.
+
+{\bf Definition 1}. {\sl A domain is a set of values (possibly
+infinite), and the operations which can be performed on them.}
+
+This corresponds rather closely to a ``data type'' in much modern
+programming language theory.
+
+{\bf Principle 2}. {\sl Every internal Axiom data object belongs to
+one and only one domain.}
+
+Thus the integer ``2'' belongs to the domain {\tt Integer}, whereas the
+congruence class modulo 3 ``2'' belongs to the domain {\tt IntegerMod(3)},
+which can also be written as {\tt IntegerMod 3}, thanks to the following.
+
+{\bf Convention 1}.
+{\sl Juxtaposition corresponds to (unary) function application.}
+
+This corresponds with the traditional mathematical convention that
+sin $x$ means the same as sin($x$). The user should be warned, however,
+that juxtaposition has a high precedence, and that {\bf sin x**2} parses as
+{\bf (sin x)**2} and not as {\bf sin(x**2)}. This just shows the richness of
+mathematical notation that formal grammars of any kind find hard to capture.
+
+Principle 2 can be seen in the following mini-session with Axiom:
+\begin{verbatim}
+->a:Integer
+->b:IntegerMod(3)
+\end{verbatim}
+\begin{verbatim}
+->a:=2
+
+ (3) 2
+\end{verbatim}
+\begin{verbatim}
+->a:=a+a
+
+ (4) 4
+\end{verbatim}
+\begin{verbatim}
+->b:=2
+
+ (5) 2
+\end{verbatim}
+\begin{verbatim}
+->b:=b+b
+
+ (6) 1
+\end{verbatim}
+
+The first two lines declare the domains to which the values of a and b
+may belong -- loosely speaking the types of the variables $a$ and $b$ --
+then they are given values, which are added. As we said earlier, $a + a = 4$,
+whereas $b + b = 1$. This may appear confusing, so let's run though
+the same session, but asking Axiom to print out the domains of the
+various values. This is done by means of the system command
+{\tt )set message type on}.
+
+{\bf Convention 2 (borrowed from APL)}. {\sl All system commands,
+i.e. those that do not perform, or affect the performance of, algebraic
+operations, begin with {\bf )}. In general, they may be contracted as far
+as is unambiguous, so that {\tt )set message type on} can be contracted as
+far as {\tt )se m ty on}}
+
+In addition to the Hyperdoc help system,
+information about system commands can be found using {\tt )help}.
+
+\begin{verbatim}
+->a:Integer
+ Type: Void
+->b:IntegerMod(3)
+ Type: Void
+\end{verbatim}
+\begin{verbatim}
+->a:=2
+
+ (3) 2
+ Type: Integer
+\end{verbatim}
+\begin{verbatim}
+->a:=a+a
+
+ (4) 4
+ Type: Integer
+\end{verbatim}
+\begin{verbatim}
+->b:=2
+
+ (5) 2
+ Type: IntegerMod 3
+\end{verbatim}
+\begin{verbatim}
+->b:=b+b
+
+ (6) 1
+ Type: IntegerMod 3
+\end{verbatim}
+
+Note that the declarations themselves are algebraic commands, and
+therefore their results must belong to a domain: in this case the {\tt Void}
+domain. The numbers before the values can be used to refer to these
+values later.
+
+{\bf Convention 3}. {\sl The symbol {\bf \pct} refers to the most recently
+computed proper value (i.e. not of the {\tt Void} domain). {\bf \pct\pct(n)},
+or {\bf \pct\pct n}, refers to the value numbered $n$, if $n$
+is a positive integer.
+If n is a negative integer, {\bf \pct\pct (n)} refers to the value of the
+$\vert{}n\vert$'th previous step. Also, {\bf \pct{}pi} refers to $\pi$,
+{\bf \pct{}e} to $e \approx 2.718281828$ and {\bf \pct{}i} to $\sqrt{-1}$}
+
+Note that {\bf \pct{}} is not a synonym for {\bf \pct{}\pct{}(-1)},
+since if the previous step were a declaration, then {\bf \pct{}\pct{}(-1)}
+would belong to the domain {\bf Void}, whereas {\bf \pct{}} would refer
+to the last non-void object.
+
+Principle 2 has an apparent exception, which we can see in the example
+above if, instead of writing {\bf a:=a+a}, we had just tried {\bf a+a},
+i.e. asked for the value to calculated, but not to replace the old {\bf a}.
+\begin{verbatim}
+->a+a
+ (4) 4
+ Type: PositiveInteger
+\end{verbatim}
+
+The {\bf 4} now belongs to {\tt PositiveInteger} whereas it used to belong
+to {\tt Integer}, yet we are performing the same calculation. The answer is
+that {\tt PositiveInteger} is not actually a separate domain from
+{\tt Integer}, rather it is a {\bf sub-domain} (a concept we shall
+define formally later). Whilst it is possible for users to add new
+sub-domains to Axiom, there are two built-in ones, with the inclusion
+relationships
+\[ PositiveInteger \subset NonNegativeInteger \subset Integer \]
+and a general rule about {\tt Union} domains that will be explained
+later. An element of a domain which is also an element of a sub-domain
+can move freely to a larger sub-domain, or to the whole domain, as
+required. The reason for the existence of these sub-domains is to
+allow more thorough type-checking: for example a square matrix has to
+have a dimension which is a {\tt NonNegativeInteger}, and it only makes
+sense to raise polynomials to {\tt NonNegativeInteger} powers. Similarly,
+the argument to {\tt IntegerMod} must be a {\tt PositiveInteger}. In order to
+make {\sl interactive} use easier, the interpreter will automatically
+convert elements of sub-domains into those sub-domains. This can be
+summarised as follows.
+
+{\bf Principle 3}. {\sl Values can freely move from sub-domains to
+larger ones, and, in the interpreter only, in the other direction,
+provided that this conversion is legitimate.}
+
+Compilers clearly can't move from a large domain to a smaller one,
+since they have no idea whether such a contraction will always be
+possible -- if the programmer knows that it will always be possible, they
+have to declare the fact.
+
+\subsection{Aren't all these types confusing?}
+
+The casual user need not concern themselves with the type system: those
+functions that most other systems provide, and which correspond to
+general algebra and calculus, work through the type system
+provided. For example, the following session could be taken from any
+algebra system.
+\begin{verbatim}
+->sin(x)
+
+ (1) sin(x)
+\end{verbatim}
+\begin{verbatim}
+->integrate(%,x)
+
+ (2) - cos(x)
+\end{verbatim}
+\begin{verbatim}
+->series (%,x=%pi/2)
+
+ (3)
+
+ %pi 1 %pi 3 1 %pi 5 1 %pi 7
+ (x - ---) - - (x - ---) + --- (x - ---) - ---- (x - ---)
+ 2 6 2 120 2 5040 2
+ +
+
+ 1 %pi 9 1 %pi 11 %pi 12
+ ------ (x - ---) - -------- (x - ---) + O((x - ---) )
+ 362880 2 39916800 2 2
+\end{verbatim}
+\begin{verbatim}
+->integrate %
+
+ (4)
+ 1 %pi 2 1 %pi 4 1 %pi 6 1 %pi 8
+ - ( - ---) - -- (x - ---) + --- (x - ---) - ----- (x - ---)
+ 2 2 24 2 720 2 40320 2
+ +
+
+ 1 %pi 10 1 %pi 12 %pi 13
+ ------- (x - ---) - --------- (x - ---) + O((x - ---) )
+ 3628800 2 479001600 2 2
+\end{verbatim}
+
+We note that the second use of integrate did not require, and indeed
+can not be given, a variable. Since the expression is a series in
+$x-\pi/2$, it can only be integrated with respect to $x$ , and the type system
+ensures this. In fact the domains of these results are, respectively,
+{\tt Expression Integer}, which is the workhorse for much of calculus,
+{\tt Union(Expression Integer,List Expression Integer)} and\\
+{\tt UnivariatePuiseuxSeries(Expression Integer,x,\pct{}pi/2)}
+for the last two.
+These last two require some explanation, which is given in the section
+\ref{Some AXIOM facilities} ``Some AXIOM facilities''
+on page \pageref{Some AXIOM facilities}.
+
+Axiom naturally manipulates various types of composite data structures:
+lists, vectors, sets and so on.
+
+{\bf Convention 4 (a convention of the library, rather than of the kernel)}.
+{\sl Parentheses -- {\bf ()} -- are used for grouping and function
+application, brackets -- {\bf []} -- are used for constructing lists,
+and braces -- {\bf \{\}} -- are used for constructing sets.}
+
+The difference between lists and sets is that lists can contain
+repetitions, and order matters, whereas sets, as in mathematics, are
+unordered and without repetition.
+\begin{verbatim}
+->[2,1,2,1]
+
+ (1) [2,1,2,1]
+ Type: List PositiveInteger
+\end{verbatim}
+\begin{verbatim}
+->{2,1,2,1}
+
+ (2) {1,2}
+ Type: Set PositiveInteger
+\end{verbatim}
+
+Suppose we had a list of objects, and wished to convert it into a set,
+e.g., in the situation above, we do not want to retype the 2,1,2,1.
+This is handled by a very general mechanism in Axiom.
+
+{\bf Convention 5}. {\sl The {\bf ::} in x operator, used as in}
+\[Axiom\thinspace{} object :: Axiom\thinspace{} domain\]
+{\sl can be used to convert the object to lie in the specified domain.}
+
+The {\bf ::} operator is partially built into the Axiom kernel. When new
+data types are defined, the definition includes some coerce functions
+between the new type and some existing types. However, the {\bf ::}
+operator is more than just one of these programmed conversions: it is
+at least what an algebraist would call the transitive closure of these
+operations, so that if there are {\tt coerce} functions from A to B , and
+from B to C , then {\bf ::} can convert from A to C . In fact, it is more
+than this: if a functor, such as {\tt List} possesses a {\tt map} operation
+of signature
+\[( A \rightarrow B , List\thinspace{} A ) \rightarrow List\thinspace{} B\]
+
+and it is possible to coerce objects from A to B , then the system
+will be able to coerce objects from {\tt List A} to {\tt List B}.
+More details are given in Sutor \& Jenks \cite{Jenk92}.
+
+{\bf Principle 4}. {\sl The interpreter is responsible for performing any
+chain of coercions necessary to understand the user's intentions, or
+when required to do so by an explicit use of {\bf ::} . The compiler will
+perform a chain of coercions when instructed to do so by the {\bf ::}
+operator in compiled code.}
+
+So we could replace command (2) above by
+\begin{verbatim}
+->%::Set PositiveInteger
+
+ (2) {1,2}
+ Type: Set PositiveInteger
+\end{verbatim}
+
+A large number of coercions are performed automatically. Even the
+simple computation $x+1$ causes three coercions:
+\begin{itemize}
+\item[(1)] the variable x from the domain {\tt Variable} to the domain
+{\tt Polynomial Integer};
+\item[(2)] the number 1 from the domain {\tt PositiveInteger} to the domain
+{\tt Polynomial Integer}, passing via {\tt Integer};
+\item[(3)] the result $x + 1$ from the domain {\tt Polynomial Integer}
+to the domain OutputForm, using sub-coercions of $x$ and 1 to
+{\tt OutputForm}.
+\end{itemize}
+
+All printing actually takes place from the domain {\tt OutputForm}, which
+is also the starting point for conversions to TeX format, Fortran etc.
+This means that a new domain which can be printed at all
+(i.e. which can be coerced to {\tt OutputForm}) can be printed in TeX,
+Fortran and indeed in any other ways that get added later, without
+having to modify the domain at all.
+
+\section{Some AXIOM facilities}
+\label{Some AXIOM facilities}
+
+Computer algebra is often also called ``symbolic manipulation'', and
+Axiom excels at manipulating symbols as such. A symbol can be as
+simple as $x$ or as complex as
+\begin{verbatim}
+
+ Omega (theta)
+ (1) x (a,b )
+ 7 1,2 1
+\end{verbatim}
+obtained via the following command:
+\begin{verbatim}
+ script(x,[[1,2],[paren theta],[Omega],[7], [a,script(b, [[1]])]])
+\end{verbatim}
+This symobl can be converted into TEX format by means of the
+{\tt outputAsTex} function: the result is shown below.
+\[{{} \sb {7} \sp {Omega}x \sb {{1, \: 2}} \sp {{\left( theta
+\right)}}}
+\left(
+{a, \: {b \sb {1}}}
+\right)
+\]
+It is still a single symbol, and the command
+\begin{verbatim}
+->integrate(sin %,%)
+
+ Omega (theta)
+ (4) - cos( x (a,b ))
+ 7 1,2 1
+ Type: Union(Expression(Integer),...)
+\end{verbatim}
+is no different from {\tt integrate(sin(x),x)}.
+
+Axiom has a rich integrator, based on the developments by
+Bronstein\cite{Bron90a}.
+As we saw earlier, and just above, it seems to give a rather
+complicated domain* for the result: why not just {\tt Expression Integer}?
+This expression certainly looks like an expression with integer
+entries, and seems to behave as one. First, we need to explain what
+{\bf Union} is.
+
+{\bf Principle 5}. {\sl Any set of Axiom domains $D_1,\ldots,D_n$ can be
+combined into a (disjoint) union domain, denoted
+{\tt Union}($D_1,\ldots,D_n$). The $D_i$ are called the {\bf branches} of the
+union. The operations available on this union domain are:}
+\begin{itemize}
+\item {\sl equality -- two elements are equal if they come from the same
+branch and are equal in that branch;}
+\item {\sl coercion to OutputForm;}
+\item {\sl coercion from each $D_i$ to the union domain;}
+\item {\sl coercion to each $D_i$ from the union domain, which may fail if
+the union object is not in the correct branch;}
+\item {\sl an in x predicate case , for testing if the union object
+actually is in a particular branch or not.}
+\end{itemize}
+{\sl These union domains correspond to what some other languages call
+``sum types''. A particularly useful case is exemplified by the
+``exact quotient'' operation on {\tt Integer}: its return type is
+{\tt Union(Integer,"failed")},
+where the special token {\tt failed} is returned if the division is not exact.}
+
+So we are saying that Axiom's integrator can return either an expression,
+or a list of expressions. A simple example of it doing the latter is the
+following.
+\begin{verbatim}
+-> integrate(1/(x**2-a),x)
+
+ 2 +-+
+ (x + a)\|a - 2a x +---+
+ log(-------------------) x\|- a
+ 2 atan(-------)
+ x - a a
+ (4) [------------------------,- -------------]
+ +-+ +---+
+ 2\|a \|- a
+\end{verbatim}
+
+Here, there are two possible answers, depending on the sign of $a$.
+Since Axiom has no way of knowing which is required, it returns
+both, and leaves it to the user, or the caller of the {\tt integrate}
+command, to supply the higher knowledge necessary to determine which
+element of the list to use (and it may not always be the same one). In
+some sense, they are equally correct, as we can check by differentiating
+them.
+\begin{verbatim}
+-> [differentiate(f,x) for f in %]
+
+ 1 1
+ (5) [------,------]
+ 2 2
+ x - a x - a
+\end{verbatim}
+
+Note the neat way of handling the list. There are many other such list
+handling techniques, and the user can also use {\tt map}, a function
+provided on most of the library's compound data types. This is how map
+could differentiate the elements of that list.
+\begin{verbatim}
+-> map(f+->differentiate(f,x),%% 4)
+
+ 1 1
+ (6) [------,------]
+ 2 2
+ x - a x - a
+\end{verbatim}
+
+{\bf Convention 6 (Of the library authors)}. {\sl The notation}
+\[list\thinspace{} of\thinspace{} variables +-> expression\]
+{\sl defines an anonymous function of those variables. It corresponds
+to the lambda-calculus expression ``$\lambda$variables.expression''.}
+
+As we have already seen, Axiom has a powerful series capability. As
+pioneered by Norman\cite{Norm75} in Scratchpad-1, these series are {\sl lazy}:
+terms are only evaluated as required for printing, and more terms can
+always be evaluated as required.
+\begin{verbatim}
+-> series(sin(x),x=0)
+
+ 1 3 1 5 1 7 1 9 1 11 12
+ (1) x - - x + --- x - ---- x + ------ x - -------- x + O(x )
+ 6 120 5040 362880 39916800
+\end{verbatim}
+\begin{verbatim}
+(2) -> %/x
+
+ 1 1 3 1 5 1 7 1 9 1 11 12
+ (2) - x - -- x + ---- x - ----- x + ------- x - --------- x + O(x )
+ x 6x 120x 5040x 362880x 39916800x
+\end{verbatim}
+\begin{verbatim}
+(3) -> %-1
+
+ 1 1 3 1 5 1 7 1 9 11
+ (3) - 1 + - x - -- x + ---- x - ----- x + ------- x + O(x )
+ x 6x 120x 5040x 362880x
+\end{verbatim}
+
+The number of terms initally calculated (and therefore displayed) is
+controlled by the system command {\tt )set streams calculate}. The type of
+this result is\\
+{\tt UnivariatePuiseuxSeries(Expression Integer,x,0)}.\\
+The last two parameters are clearly the variable and the point about
+which we are expanding, but what on earth is a Puiseux series? Why
+cannot Axiom give us the familiar Taylor series, which this certainly
+looks like being? A Taylor series represents a continuous function
+$a_0x^0+a_1x^1+\cdots$. One way of generalising this is to allow
+{\sl meromorphic} functions, i.e. those with a point singularity of the
+$1/x$ (more generally $1/x^n$) variety. In order to represent these,
+we have to allow (a finite number of) negative exponents in the series
+-- so-called Laurent series.
+\begin{verbatim}
+-> series(1/sin(x),x=0)
+
+ - 1 1 7 3 31 5 127 7 73 9 10
+ (4) x + - x + --- x + ----- x + ------ x + ------- x + O(x )
+ 6 360 15120 604800 3421440
+\end{verbatim}
+
+However, even these are not as general as one would like, since they are
+incapable of representing multi-valued functions like $\sqrt{x}$.
+To do this, we have to allow fractional exponents (of bounded
+denominator), which gives us Puiseux series.
+\begin{verbatim}
+-> sqrt %
+
+ 1 3 7
+ - - - -
+ 2 1 2 1 2 5
+ (5) x + -- x + --- x + O(x )
+ 12 160
+\end{verbatim}
+\begin{verbatim}
+-> %**2
+
+ 9
+ -
+ - 1 1 7 3 2
+ (6) x + - x + --- x + O(x )
+ 6 360
+\end{verbatim}
+\begin{verbatim}
+(7) -> %%(4)-%
+
+ 19
+ --
+ 2
+ (7) O(x )
+\end{verbatim}
+
+Note that Axiom, like any other algebra system, cannot prove that the
+difference of these two series is identically zero, merely that in
+going all the way up to the limit required by {\tt )set streams calculate},
+it can find no non-zero terms. Puiseux series have many uses in
+algebraic geometry. See Davenport\cite{Dave81}
+
+\subsection{How does one keep track of all this?}
+
+There seem to be so many different names and domains around in the
+Axiom system. How does one keep track of them all, and know what to
+use? There is an on-line help system Hyperdoc, with tutorial material
+and information arranged by subject, but the system itself provides
+some help.
+
+{\bf Convention 7}. {\sl The names of Axiom functions are either special
+symbols (such as $+$) or complete english words strung together. In this
+case, every word after the first is capitalised. Thus {\tt integrate}
+but {\tt complexIntegrate}. In addition:}
+\begin{itemize}
+\item {\sl all boolean predicates end in a {\bf ?} , as in {\tt odd?},
+which tests if a number is odd}
+\item {\sl all destructive functions which operate on data structures
+end in a {\bf !} , as in {\tt reverse!}, which reverses a list destructively.}
+\end{itemize}
+{\sl Conversely, the names of domains (and other constructors we will come
+to later) consist of english words strung together, all of which are
+capitalised, as in {\tt IntegerMod} or {\tt UnivariatePuiseuxSeries}.}
+
+One can search (case-insensitively) for all functions whose name contains
+a particular word by using the system command {\tt )what operations},
+contractible to {\tt )w o} , as in
+\begin{verbatim}
+->)what operations series
+
+Operations whose names satisfy the above pattern(s):
+
+series seriesSolve
+
+ To get more information about an operation, say series , issue the
+ command )display op series
+\end{verbatim}
+
+As it says, the command {\tt )display operations}, contractible to {\tt )d o},
+can be used to find out what the arguments of an operation should
+be. However, in order to explain this, we have to delve rather deeper
+into Axiom's type system. The user of the Nag Fortran library sees
+nothing strange in writing one subroutine to multiply real matrices,
+and a different one to multiply complex matrices. Indeed, one would be
+hard put to do anything else in Fortran 77. The user of the Nag Ada
+library, in contrast, would expect to find a generic matrix
+multiplication routine, which could be called for any built-in real or
+complex type, and possibly for additional user-defined types. Axiom's
+type system is much closer to the Ada one than the Fortran one, but in
+fact even more general than the Ada model.
+
+Just as one can make various different modular domains by applying the
+functor\footnote{Axiom terminology, borrowed from category theory,
+uses the word ``functor'' for those functions that yield domains as
+their result, whereas ``function'' is reserved for operations whose
+value is an Axiom object} {\tt IntegerMod} to different integers, so
+one can make different matrix domains by applying the functor {\tt
+Matrix} to different domains for the coefficients.
+\begin{verbatim}
+-> [[1,2],[3,4]]::Matrix IntegerMod 3
+
+ +1 2+
+ (1) | |
+ +0 1+
+ Type: Matrix(IntegerMod(3))
+\end{verbatim}
+\begin{verbatim}
+-> [[1,2],[3,4]]::Matrix IntegerMod 5
+
+ +1 2+
+ (2) | |
+ +3 4+
+ Type: Matrix(IntegerMod(5))
+\end{verbatim}
+\begin{verbatim}
+(3) -> [[1,2],[3,4]]::Matrix Float
+
+ +1.0 2.0+
+ (3) | |
+ +3.0 4.0+
+ Type: Matrix(Float)
+\end{verbatim}
+
+In each case, the coefficient arithmetic is done according to the correct
+rules of the coefficient domain.
+\begin{verbatim}
+(4) -> %%(1)**2
+
+ +1 1+
+ (4) | |
+ +0 1+
+ Type: Matrix(IntegerMod(3))
+\end{verbatim}
+\begin{verbatim}
+(5) -> %%(2)**2
+
+ +2 0+
+ (5) | |
+ +0 2+
+ Type: Matrix(IntegerMod(5))
+\end{verbatim}
+\begin{verbatim}
+(6) -> %%(3)**2
+
+ +7.0 10.0+
+ (6) | |
+ +15.0 22.0+
+ Type: Matrix(Float)
+\end{verbatim}
+
+But would it make sense, say, to have a matrix of hash tables? Clearly
+not: we require that the coefficients of the matrix be capable of being
+added, subtracted, multiplied etc. In fact, we have to place some
+requirements on the domain which is the parameter to {\tt Matrix}, just as
+we placed some requirements on the argument to {\tt IntegerMod}. The
+{\tt )show} command tells us what these requirements are
+(and a great deal more).
+\begin{verbatim}
+->)show IntegerMod
+ IntegerMod p: PositiveInteger is a domain constructor
+ Abbreviation for IntegerMod is ZMOD
+\end{verbatim}
+\begin{verbatim}
+->)show Matrix
+ Matrix R: Ring is a domain constructor
+ Abbreviation for Matrix is MATRIX
+\end{verbatim}
+We have stipulated that the Axiom object $p$ which is the parameter to
+{\tt IntegerMod} must belong to the (sub-)domain {\tt PositiveInteger},
+and similarly we stipulate that the domain $R$ which is the
+parameter to {\tt Matrix} must belong to the second-order type
+system {\tt Ring}.
+
+\section{Categories}
+
+{\bf Principle 6}. {\sl The Axiom library declares a family of second-order
+types, known as {\bf categories}. The categories are arranged in a directed
+acyclic graph, and each domain belong to a specific category, and to all
+the ancestors of that category. The specification of a category includes}
+\begin{itemize}
+\item {\sl all its direct ancestors,}
+\item {\sl any additional operations that this category supports, and}
+\item {\sl any additional axioms that the operations must satisfy.}
+\end{itemize}
+{\sl The operation {\tt Join} is used to construct new categories.}
+
+
+This may appear a bit abstract, so let's look at an example from the
+foundations of the Axiom library. The fundamental category in Axiom is
+{\tt SetCategory}.
+
+{\bf Convention 8}. {\sl Whenever a category, or domain, is being discussed
+in Axiom, the symbol \pct{} stands for the domain in question, or for any
+domain from the category in question.}
+
+With the help of that notation, we can ask Axiom what the definition
+of {\tt SetCategory} is.
+\begin{verbatim}
+->)show SetCategory
+ SetCategory is a category constructor.
+ Abbreviation for SetCategory is SETCAT
+ This constructor is exposed in this frame.
+ Issue )edit bookvol10.2.pamphlet to see algebra source code for SETCAT
+
+------------------------------- Operations --------------------------------
+
+ ?=? : (%,%) -> Boolean coerce : % -> OutputForm
+\end{verbatim}
+
+This output shows that there are two operations defined on any domain,
+denoted by \pct{} , which belongs to the category {\tt SetCategory}:
+an infix operation $=$ which takes two arguments from \pct{} and
+yields a {\tt Boolean} result, and an operation called {\tt coerce},
+which takes an element of \pct{}, and yields an {\tt OutputForm}.
+How does this grow into more useful categories?
+A graphic representaton of some of the first few extensions is given below.
+\[\begin{array}{ccc}
+SetCategory & &\\
+\downarrow & \searrow &\\
+AbelianSemiGroup & & OrderedSet\\
+\downarrow & \searrow & \downarrow\\
+AbelianMonoid & & OrderedAbelianMonoid\\
+\downarrow & \searrow & \downarrow\\
+CancellationAbelianMonoid & & OrderedAbelianMonoid\\
+\downarrow & \searrow & \downarrow\\
+AbelianGroup & & OrderedCancellationAbelianMonoid\\
+ & \searrow & \downarrow\\
+ & &OrderedAbelianGroup\\
+\end{array}\]
+where the arrows indicate a ``direct descendant'' relationship.
+
+{\tt AbelianSemiGroup} is defined to have one new operator:
+\[+ : \pct{} \times \pct{} \mapsto \pct\]
+satisfying the associative and commutative axioms:
+\[a+(b+c)=(a+b)+c\]
+\[a+b=b+a\]
+
+{\tt AbelianMonoid} introduces a new nullary
+operator\footnote{Technically speaking, it is a constant,
+rather than a nullary
+operator, which means that the value is computed once and for all when
+the type is created. The difference is essentially one of efficiency,
+and we will not discuss it further here.}
+\[0 :\thinspace{} \mapsto \pct{}\]
+satisfying the obvious axiom
+\[0 + a = a\]
+
+{\tt CancellationAbelianMonoid} is the category of abelian monoids with
+the cancallation axiom:
+\[a+b = a+c \Rightarrow b = c\]
+
+Constructively, this is represented by a partial subtraction operator,
+whose signature is defined as:
+\[- : \pct{} \times \pct{} \mapsto {\tt\ Union}(\pct{},{\rm "failed"})\]
+
+While such an operation could be defined for any {\tt AbelianMonoid}, or
+even any {\tt AbelianSemiGroup}, it is the cancellation axiom that ensures
+that {\bf $-$} has a unique value.
+This operator is subsumed in the {\bf $-$} operation
+defined on {\tt AbelianGroup}s.
+
+{\tt AbelianGroup} adds one further unary operator
+\footnote{In practice, it also adds a binary operator
+\[- : \pct{} \times \pct{} \mapsto \pct{}\]
+satisfying the axiom
+\[a-b = a+(-b)\]
+From a logical point of view, the binary operator is redundant. It is
+present in Axiom for two reasons. The first is legibility of programs:
+$a-b$ is easier to read than $a+(-b)$. The second is efficiency: while
+the binary operator {\sl can} always be implemented in terms of the
+unary operator, and indeed has a default definition implementing it
+this way, it is not necessarily very efficient to do so. For example,
+if \pct{} is a matrix type, implementing the binary operator in terms of
+the unary operator causes two new matrices to be allocated instead of
+one.}
+\[ - : \pct{} \mapsto \pct{}\]
+This operator satisfies the axiom
+\[a+(-a)=0\]
+
+The first $\searrow$ introduces an operator
+\[< : \pct{} \times \pct{} \mapsto Boolean\]
+satisfying the usual axioms:
+\[a < b \vee b < c \Rightarrow a < c\]
+\[\neg (a < b) \vee \neg (b < a) \Rightarrow a = b\]
+\[ a < b \Rightarrow \neg (b < a)\]
+
+Subsequent $\searrow$ in this diagram introduce no new operators, but
+one more axiom is introduced, when {\tt OrderedAbelianSemiGroup} is defined:
+\[a < b \Rightarrow a + c < b + c\]
+This is typical of what happens when two categories are merged to form
+a new named category: we keep the same operators, but are interested
+in the interaction between them, which requires the introduction of
+new axioms to define this interaction. Subsequent $\searrow$ in the
+chain represent the straight forward merging of ancestors.
+
+It should be noted that none of these definitions are hard-coded in the
+the Axiom kernel: merely the mechanism for understanding them is part
+of the kernel. The definitions are written in the Axiom category
+definition language, and could be modified or extended to suit
+different kinds of mathematics. See Lambe\cite{Lamb89}, Schwarz\cite{Schw88}
+The code reads, in essence, as given below.
+
+{\bf Convention 9}. {\sl Axiom comments can be introduced by {\bf $--$} or
+{\bf $++$}. Those beginning {\bf $++$} are intended for the user, and can
+be retrieved by the on-line help system.}
+
+For example, the comment following {\tt zero?} in {\tt AbelianMonoid} is
+retrieved when the operation name {\tt zero?} is searched for.
+
+\begin{verbatim}
+SetCategory(): Category == Join(Object, CoercibleTo OutputForm) with
+
+ "=": (%,%) -> Boolean
+
+\end{verbatim}
+\begin{verbatim}
+++ Axioms:
+++ associative("+":(%,%)->%) || \space{ (x+y)+z = x+(y+z) }
+++ commutative("+":(%,%)->%) || \spad{ x+y = y+x }
+AbelianSemiGroup(): Category == SetCategory with
+
+ "+": (%,%) -> %
+\end{verbatim}
+\begin{verbatim}
+++ Axioms:
+++ leftIdentity("+":(%,%)->%,0) || \spad{ 0+x=x }
+++ rightIdentity("+":(%,%)->%,0) || \spad{ x+x=x }
+AbelianMonoid(): Category == AbelianSemiGroup with
+
+ 0: constant -> % ++ 0 is the additive identity element
+
+ zero?: % -> Boolean ++zero?(x) tests if x is equal to 0
+
+ add
+
+ zero? x == x = 0
+\end{verbatim}
+
+The clause after add introduces a default definition of {\tt zero?}
+in terms of $=$ and 0.
+
+{\bf Principle 7}. {\sl Categories can introduce {\bf default definitions}
+of operations, which will take effect in any domain belonging to that
+category unless overridden by a definition in that domain, or in a
+more specific category.}
+
+Further details of the general mechanism are given in Jenks {et
+al.} \cite{Jenk92}, and the actual categories implemented in the
+Axiom library are described in Davenport \& Trager\cite{Dave90}
+and Davenport et al.\cite{Dave91}.
+However, we can see that it is possible to define such a system
+of categories which will act, in effect, as a type system for the
+domains themselves.
+
+{\bf Principle 8}.
+{\sl The functors of Axiom are strongly typed: each parameter which is
+an Axiom object is specified to come from a particular domain; each parameter
+which is an Axiom domain is specified to belong to a particular Axiom
+category. Similarly, the domain returned by a particular functor is
+specified to belong to a particular category. All construction of domains
+must satisfy these constraints on the functors.}
+
+To take the example of {\tt Matrix}, the definition of the functor could
+begin as follows:
+\begin{verbatim}
+ Matrix(R:Ring): MatrixCategory(R, Vector R, Vector R) ==
+\end{verbatim}
+
+where {\tt MatrixCategory} is a category, itself with three parameters,
+which defines the various operations that must be satisfied by all
+kinds of matrices, not just those defined by {\tt Matrix}, which defines
+dense matrices stored in a two-dimensional array with no special
+properties. We can discover what Axiom's current definition of the
+operations on a ring are.
+\begin{verbatim}
+-> )show Ring
+ Ring is a category constructor
+ Abbreviation for Ring is RING
+ This constructor is exposed in this frame.
+ Issue )edit bookvol10.2.pamphlet to see algebra source code for RING
+
+------------------------------- Operations --------------------------------
+ ?*? : (%,%) -> % ?*? : (Integer,%) -> %
+ ?*? : (NonNegativeInteger,%) -> % ?*? : (PositiveInteger,%) -> %
+ ?**? : (%,NonNegativeInteger) -> % ?**? : (%,PositiveInteger) -> %
+ ?+? : (%,%) -> % ?-? : (%,%) -> %
+ -? : % -> % ?=? : (%,%) -> Boolean
+ 1 : () -> % 0 : () -> %
+ ?^? : (%,NonNegativeInteger) -> % ?^? : (%,PositiveInteger) -> %
+ coerce : Integer -> % coerce : % -> OutputForm
+ hash : % -> SingleInteger latex : % -> String
+ one? : % -> Boolean recip : % -> Union(%,"failed")
+ sample : () -> % zero? : % -> Boolean
+ ?~=? : (%,%) -> Boolean
+ characteristic : () -> NonNegativeInteger
+ subtractIfCan : (%,%) -> Union(%,"failed")
+\end{verbatim}
+
+In particular we have the operations of addition, subtraction and
+multiplication that are required to make sense of the definition of
+matrix with entries from $R$. In fact the actual definition of {\tt Matrix}
+is more complicated, and the category of the result is defined to be
+\begin{verbatim}
+Matrix(R:Ring): MatrixCategory(R,Row,Col) with
+
+ diagonalMatrix : Vector R -> %
+ ++ \spad{diagonalMatrix(v)} returns a diagonal matrix where the elements
+ ++ of v appear on the diagonal.
+
+ if R has Field then
+
+ inverse : % -> Union(%,"failed")
+
+\end{verbatim}
+
+Note the conditional definition: the coefficients $R$ need only be a
+{\tt Ring}, but if, in addition, they are a {\tt Field}, i.e. division
+is possible, then it makes sense to talk about the inverse of a matrix.
+Of course, the inverse operation may fail if the matrix is singular, so the
+return domain of {\tt inverse} is defined to be {\tt Union}(\pct{},"failed").
+{\tt MatrixCategory} is not itself a descendant of {\tt Ring}, because
+matrices can only be added, multiplied etc. if they conform. However, square
+matrices do form a ring, and Axiom knows this.
+
+{\bf Convention 10}. {\sl The infix binary predicate {\tt has} can be used
+to test if domains belong to categories, or if they have specified attributes.}
+\begin{verbatim}
+-> SquareMatrix(2,Integer) has Ring
+
+ (7) true
+ Type: Boolean
+\end{verbatim}
+
+This implies that a square matrix domain would itself be an acceptble
+parameter to matrix.
+\begin{verbatim}
+-> [[ [[1,2],[3,4]],1,0],[0,[[5,6],[7,8]],1]]::Matrix SquareMatrix(2,Integer)
+
+ ++1 2+ +1 0+ +0 0++
+ || | | | | ||
+ |+3 4+ +0 1+ +0 0+|
+ (8) | |
+ |+0 0+ +5 6+ +1 0+|
+ || | | | | ||
+ ++0 0+ +7 8+ +0 1++
+ Type: Matrix(SquareMatrix(2,Integer))
+\end{verbatim}
+\begin{verbatim}
+-> transpose %
+
+ ++1 2+ +0 0++
+ || | | ||
+ |+3 4+ +0 0+|
+ | |
+ |+1 0+ +5 6+|
+ (9) || | | ||
+ |+0 1+ +7 8+|
+ | |
+ |+0 0+ +1 0+|
+ || | | ||
+ ++0 0+ +0 1++
+ Type: Matrix(SquareMatrix(2,Integer))
+\end{verbatim}
+\begin{verbatim}
+-> %%(8)*%
+
+ ++8 10+ +5 6+ +
+ || | | | |
+ |+15 23+ +7 8+ |
+ (10) | |
+ | +5 6+ +68 78 +|
+ | | | | ||
+ + +7 8+ +91 107++
+ Type: Matrix(SquareMatrix(2,Integer))
+\end{verbatim}
+\begin{verbatim}
+-> square? %
+
+ (11) true
+ Type: Boolean
+\end{verbatim}
+
+This is not necessarily the most stunning application of Axiom, but it
+does show that the type system can be used to construct some truly
+amazing objects. We notice also that the type system interpreted some
+occurrences of 1 and 0 as requiring appropriate matrices as their
+values, in order to make the command type-consistent.
+
+In practice these extremely complex types are often used in the middle
+of a calculation, even when the final result is quite simple or
+straight-forward. Grabmeier\cite{Grab91a} gives an example from genetics,
+where one of the intermediate objects in his construction belonged to
+the domain
+\begin{verbatim}
+List PolynomialIdeals(Fraction Integer,
+ DirectProduct(4,NonNegativeInteger),
+ [x1,x2,x3,x4],
+ DistributedMultivariatePolynomial([x1,x2,x3,x4],
+ Fraction Integer))
+\end{verbatim}
+
+{\bf Convention 11}. {\sl Every Axiom {\bf constructor}, i.e. functor or
+category, has an {\bf abbreviation}, consisting of at most eight
+upper-case letters (seven in the case of categories). These serve
+two purposes: they can be used on input and output in order to make the
+names of the types shorter, and they denote the directory in which the
+corresponding Axiom library lives. The defaults for category {\tt Cat},
+with abbreviation {\tt CAT}, are called {\tt Cat\&} ,
+with abbreviation {\tt CAT-}.}
+
+For example, the abbreviation for {\tt Integer} is {\tt INT}, and
+the compiled library lives in the directory {\tt INT.nrlib}.
+Grabmeier's type can therefore also be written as
+\begin{verbatim}
+List IDEAL(FRAC INT,DIRPROD(4,NNI),[x1,x2,x3,x4],DMP([x1,x2,x3,x4],FRAC INT)
+\end{verbatim}
+which is certainly shorter, even though still somewhat of a mouthful.
+
+\subsection{Using the {\tt )display} command}
+
+Let us begin with a very simple example of the {\tt )display} command.
+\begin{verbatim}
+-> )d op pop!
+\end{verbatim}
+\begin{verbatim}
+There are 4 exposed functions called pop! :
+ [1] ArrayStack(D1) -> D1 from ArrayStack(D1) if D1 has SETCAT
+ [2] Dequeue(D1) -> D1 from Dequeue(D1) if D1 has SETCAT
+ [3] D -> D1 from D if D has SKAGG(D1) and D1 has TYPE
+ [4] Stack(D1) -> D1 from Stack(D1) if D1 has SETCAT
+\end{verbatim}
+\begin{verbatim}
+Examples of pop! from ArrayStack
+
+a:ArrayStack INT:= arrayStack [1,2,3,4,5]
+pop! a
+a
+\end{verbatim}
+\begin{verbatim}
+Examples of pop! from Dequeue
+
+a:Dequeue INT:= dequeue [1,2,3,4,5]
+pop! a
+a
+\end{verbatim}
+\begin{verbatim}
+Examples of pop! from StackAggregate
+
+a:Stack INT:= stack [1,2,3,4,5]
+pop! a
+a
+\end{verbatim}
+\begin{verbatim}
+Examples of pop! from Stack
+
+a:Stack INT:= stack [1,2,3,4,5]
+pop! a
+a
+\end{verbatim}
+There are 4 exposed functions listed, with their argument types,
+result type and (following the word {\tt from}) the source of their
+implementation: a combination known collectively as a {\bf signature}.
+Once one knows that {\tt SKAGG} is an abbreviation for {\tt StackAggregate},
+which is easy enough to find out
+\begin{verbatim}
+->)d abbrev SKAGG
+ SKAGG abbreviates category StackAggregate
+\end{verbatim}
+
+Axiom functions have a special syntax (a {\bf tagged comment}) that
+\index{tagged comment}
+provides examples of functions from the algebra source code. For example,
+the {\tt Stack} domain has the {\tt pop!} function.
+\begin{verbatim}
+ pop_! : % -> S
+ ++ pop! returns the top element of the stack, destructively
+ ++ modifying the stack to remove that element.
+ ++
+ ++X a:Stack INT:= stack [1,2,3,4,5]
+ ++X pop! a
+ ++X a
+\end{verbatim}
+The special form of the {\bf $++$} comment, which is {\bf ++X}
+provides an example of the use of the function. So, in the above output,
+we see
+\begin{verbatim}
+Examples of pop! from Stack
+
+a:Stack INT:= stack [1,2,3,4,5]
+pop! a
+a
+\end{verbatim}
+which shows three commands a user can execute to demonstrate the function
+\begin{verbatim}
+-> a:Stack INT:= stack [1,2,3,4,5]
+
+ (1) [1,2,3,4,5]
+ Type: Stack(Integer)
+\end{verbatim}
+\begin{verbatim}
+(2) -> pop! a
+
+ (2) 1
+ Type: PositiveInteger
+\end{verbatim}
+\begin{verbatim}
+(3) -> a
+
+ (3) [2,3,4,5]
+ Type: Stack(Integer)
+\end{verbatim}
+making it clear that the stack $a$ has been modified.
+
+A more complicated example would be given by {\tt )d op integrate}, and
+we will only explain some of the entries. The Axiom library has 32 exposed
+integrations and 10 unexposed ones.
+\begin{verbatim}
+ [29] D -> D from D
+ if D has UPXSCAT(D1) and D1 has RING and D1 has ALGEBRA(
+ FRAC(INT))
+ [7] (D2,Symbol) -> Union(D2,List(D2)) from FunctionSpaceIntegration(
+ D4,D2)
+ if D4 has Join(EuclideanDomain,OrderedSet,
+ CharacteristicZero,RetractableTo(Integer),
+ LinearlyExplicitRingOver(Integer)) and D2 has Join(
+ TranscendentalFunctionCategory,PrimitiveFunctionCategory,
+ AlgebraicallyClosedFunctionSpace(D4))
+\end{verbatim}
+The function [29] is the one we used to integrate the Puiseux series:
+{\tt UPXSCAT} is the abbreviation for {\tt UnivariatePuiseuxSeriesCategory},
+and $D1$, the coefficients of the series, must be an algebra over the
+rational numbers (otherwise we could not regard the exponents as coefficients,
+which one has to do when integrating $x^{p/q}$ to $\frac{q}{p+q}x^{1+p/q}$)
+and a ring.
+
+The function [7] is the one we used for most of the other integrations we have
+performed so far. Although the signature looks fairly lengthy, we have
+already analysed the fact that the signature is of the form
+\[{\tt (D2,Symbol)} \rightarrow {\tt Union(D2,List D2)}\]
+
+The rest of the lines are merely explaining what properties D2 must have.
+D4 plays the role of the coefficients in the function being integrated.
+We always had {\tt Integer} in there, but this is not strictly necessary.
+\begin{verbatim}
+-> 2*cos(4*x)**3::Expression RomanNumeral
+
+ 3
+ (1) II cos(IV x)
+ Type: Expression(RomanNumeral)
+\end{verbatim}
+\begin{verbatim}
+(2) -> integrate(%,x)
+
+ 2
+ (cos(IV x) + II)sin(IV x)
+ (2) --------------------------
+ VI
+ Type: Union(Expression(RomanNumeral),List(Expression(RomanNumeral)))
+\end{verbatim}
+It can clearly be seen that, in {\tt Expression RomanNumeral}, the
+coefficients are indeed members of {\tt RomanNumeral}, but the exponents
+are not.
+
+\chapter{How does one program in the Axiom system by James H. Davenport}
+This is (mostly) quoted verbatim, with permission,
+from Davenport\cite{Dave92b}.
+
+\section{Introduction}
+
+Axiom can be used in essentially three ways. The first corresponds to
+the ``pocket calculator'' style of use -- simple commands can be typed
+and the answer is printed. These commands can be issued from the
+keyboard in traditional style, or via the Hyperdoc menu system, or
+through ``.input'' files, and are handled by what is generally called
+the ``Axiom interpreter''. This interpreter does more than traditional
+computer algebra systems do, since Axiom is a typed system, and the
+interpreter has to do type inference.
+
+The second style corresponds to what might be called the ``programmable
+pocket calculator'' style, where simple functions are defined, or variables
+given values for later use. An example of a simple function would be
+\begin{verbatim}
+fac n == if n < 3 then n else n*fac(n-1)
+\end{verbatim}
+as a definition of the factorial function. A slightly more complicated
+example (take from IBM\cite{IBMx91} and Jenks \& Sutor\cite{Jenk92})
+goes as follows.
+\begin{verbatim}
+mersenne i == 2**i - 1
+\end{verbatim}
+This line defines a function for computing the $i$-th Mersenne number
+\begin{verbatim}
+mersenneIndex := [n for n in 1.. | prime?(mersenne(n))]
+This line, which produces the following output from Axiom,
+\begin{verbatim}
+ (2) [2,3,5,7,13,17,19,31,61,89,...]
+ Type: Stream(PositiveInteger)
+\end{verbatim}
+computes an infinite (but lazily evaluated) list of the indices of those
+Mersenne numbers which are actually prime.
+\begin{verbatim}
+mersennePrime n == mersenne mersenneIndex(n)
+\end{verbatim}
+This defines a function which produces the $n$-th Mersenne prime. It can
+be used as in the following input line (and corresponding output).
+\begin{verbatim}
+mersennePrime 5
+
+ (4) 8191
+ Type: PositiveInteger
+\end{verbatim}
+
+In this style, we have various ``one-liners'' which interact with each
+other, much as programmed functions on a pocket calculator.
+
+In the third style, we define new complete data types to Axiom.
+It is this third style of programming that this paper addresses.
+
+\section{Programming concepts}
+
+Axiom has several fundamental concepts, which we have to outline briefly.
+
+\begin{tabular}{rp{11cm}}
+{\bf Domain} & A domain is what many other languages would call an
+{\sl abstract data type}, i.e. a specification of certain data objects
+and the operations on them. A typical domain would be {\tt Integer},
+whose elements are the underlying integers of the implementation
+(infinite precision, of course), and which supports the following
+operations, as given by the Axiom command {\tt )show Integer}, or by
+using the Hyperdoc browser. We remind the reader that \pct{} is Axiom's
+notation for the ``current domain'', i.e. {\tt Integer} in this case,
+and that all operations are prefix unless shown otherwise (e.g. the
+infix {\tt *} and {\tt quo}).
+\end{tabular}
+
+\begin{verbatim}
+ Integer is a domain constructor
+ Abbreviation for Integer is INT
+ This constructor is exposed in this frame.
+ Issue )edit bookvol10.3.pamphlet to see algebra source code for INT
+
+------------------------------- Operations --------------------------------
+ ?*? : (%,%) -> % ?*? : (Integer,%) -> %
+ ?*? : (NonNegativeInteger,%) -> % ?*? : (PositiveInteger,%) -> %
+ ?**? : (%,NonNegativeInteger) -> % ?**? : (%,PositiveInteger) -> %
+ ?+? : (%,%) -> % ?-? : (%,%) -> %
+ -? : % -> % ? Boolean
+ ?<=? : (%,%) -> Boolean ?=? : (%,%) -> Boolean
+ ?>? : (%,%) -> Boolean ?>=? : (%,%) -> Boolean
+ D : % -> % D : (%,NonNegativeInteger) -> %
+ OMwrite : (%,Boolean) -> String OMwrite : % -> String
+ 1 : () -> % 0 : () -> %
+ ?^? : (%,NonNegativeInteger) -> % ?^? : (%,PositiveInteger) -> %
+ abs : % -> % addmod : (%,%,%) -> %
+ associates? : (%,%) -> Boolean base : () -> %
+ binomial : (%,%) -> % bit? : (%,%) -> Boolean
+ coerce : Integer -> % coerce : % -> %
+ coerce : Integer -> % coerce : % -> OutputForm
+ convert : % -> String convert : % -> DoubleFloat
+ convert : % -> Float convert : % -> Pattern(Integer)
+ convert : % -> InputForm convert : % -> Integer
+ copy : % -> % dec : % -> %
+ differentiate : % -> % even? : % -> Boolean
+ factor : % -> Factored(%) factorial : % -> %
+ gcd : List(%) -> % gcd : (%,%) -> %
+ hash : % -> % hash : % -> SingleInteger
+ inc : % -> % init : () -> %
+ invmod : (%,%) -> % latex : % -> String
+ lcm : List(%) -> % lcm : (%,%) -> %
+ length : % -> % mask : % -> %
+ max : (%,%) -> % min : (%,%) -> %
+ mulmod : (%,%,%) -> % negative? : % -> Boolean
+ nextItem : % -> Union(%,"failed") odd? : % -> Boolean
+ one? : % -> Boolean permutation : (%,%) -> %
+ positive? : % -> Boolean positiveRemainder : (%,%) -> %
+ powmod : (%,%,%) -> % prime? : % -> Boolean
+ ?quo? : (%,%) -> % random : % -> %
+ random : () -> % rational : % -> Fraction(Integer)
+ rational? : % -> Boolean recip : % -> Union(%,"failed")
+ ?rem? : (%,%) -> % retract : % -> Integer
+ sample : () -> % shift : (%,%) -> %
+ sign : % -> Integer sizeLess? : (%,%) -> Boolean
+ squareFree : % -> Factored(%) squareFreePart : % -> %
+ submod : (%,%,%) -> % symmetricRemainder : (%,%) -> %
+ unit? : % -> Boolean unitCanonical : % -> %
+ zero? : % -> Boolean ?~=? : (%,%) -> Boolean
+ OMwrite : (OpenMathDevice,%,Boolean) -> Void
+ OMwrite : (OpenMathDevice,%) -> Void
+ characteristic : () -> NonNegativeInteger
+ differentiate : (%,NonNegativeInteger) -> %
+ divide : (%,%) -> Record(quotient: %,remainder: %)
+ euclideanSize : % -> NonNegativeInteger
+ expressIdealMember : (List(%),%) -> Union(List(%),"failed")
+ exquo : (%,%) -> Union(%,"failed")
+ extendedEuclidean : (%,%) -> Record(coef1: %,coef2: %,generator: %)
+ extendedEuclidean : (%,%,%) -> Union(Record(coef1: %,coef2: %),"failed")
+ gcdPolynomial : (SparseUnivariatePolynomial(%),SparseUnivariatePolynomial(%))
+ -> SparseUnivariatePolynomial(%)
+ lcmCoef : (%,%) -> Record(llcmres: %,coeff1: %,coeff2: %)
+ multiEuclidean : (List(%),%) -> Union(List(%),"failed")
+ patternMatch : (%,Pattern(Integer),PatternMatchResult(Integer,%))
+ -> PatternMatchResult(Integer,%)
+ principalIdeal : List(%) -> Record(coef: List(%),generator: %)
+ rationalIfCan : % -> Union(Fraction(Integer),"failed")
+ reducedSystem : Matrix(%) -> Matrix(Integer)
+ reducedSystem : (Matrix(%),Vector(%))
+ -> Record(mat: Matrix(Integer),vec: Vector(Integer))
+ retractIfCan : % -> Union(Integer,"failed")
+ subtractIfCan : (%,%) -> Union(%,"failed")
+ unitNormal : % -> Record(unit: %,canonical: %,associate: %)
+\end{verbatim}
+\begin{tabular}{rp{11cm}}
+{\hskip 1.5cm}
+& It must be stressed that the use of {\tt )show} or the browser is essential
+to understanding what is already present in Axiom, and what one has to add
+to produce a valid domain. If fact, a user cannot write a domain, merely
+a function (see later) which, when called, will create a domain.
+\end{tabular}
+
+\begin{tabular}{rp{11cm}}
+{\bf Category} & The set of all domains (declared as) belonging to this
+category, i.e. having the stated operations and associated axioms. For
+example, the domain {\tt Integer} belongs to the category {\tt Ring},
+which has the following operations, again given by {\tt )show Ring} or
+the browser.
+\end{tabular}
+\begin{verbatim}
+ Ring is a category constructor
+ Abbreviation for Ring is RING
+ This constructor is exposed in this frame.
+ Issue )edit bookvol10.2.pamphlet to see algebra source code for RING
+
+------------------------------- Operations --------------------------------
+ ?*? : (%,%) -> % ?*? : (Integer,%) -> %
+ ?*? : (NonNegativeInteger,%) -> % ?*? : (PositiveInteger,%) -> %
+ ?**? : (%,NonNegativeInteger) -> % ?**? : (%,PositiveInteger) -> %
+ ?+? : (%,%) -> % ?-? : (%,%) -> %
+ -? : % -> % ?=? : (%,%) -> Boolean
+ 1 : () -> % 0 : () -> %
+ ?^? : (%,NonNegativeInteger) -> % ?^? : (%,PositiveInteger) -> %
+ coerce : Integer -> % coerce : % -> OutputForm
+ hash : % -> SingleInteger latex : % -> String
+ one? : % -> Boolean recip : % -> Union(%,"failed")
+ sample : () -> % zero? : % -> Boolean
+ ?~=? : (%,%) -> Boolean
+ characteristic : () -> NonNegativeInteger
+ subtractIfCan : (%,%) -> Union(%,"failed")
+\end{verbatim}
+\begin{tabular}{rp{11cm}}
+{\hskip 1.5cm}
+& Note that 0 and 1 are {\sl nullary operations}, since their actual
+value may well be very different in different domains belonging to the
+category {\tt Ring}, e.g. in the ring of $n$-by-$n$ square matrices,
+the 1 is the identity matrix, and not the matrix consisting entirely
+of 1.\\
+& Categories can be parameterized, as in {\tt Algebra($R$)}, where $R$
+is some {\tt CommutativeRing}, which gives the category of all
+algebras over $R$.
+\end{tabular}
+
+\begin{tabular}{rp{11cm}}
+{\bf Functor} & A function which takes arguments which are either
+individual objects, in which case the domain they come from is
+specified, or domains, in which case the category they come from is
+specified, and which returns a domain specified to live in a particular
+category. for Example:
+\begin{tabular}{rp{9cm}}
+{\bf Z=Integer} & is the result of applying the function {\tt Integer}
+to no arguments;\\
+{\bf Q} & is the result of applying the function {\tt Fraction} (which
+requires an {\tt IntegralDomain} as its argument) to the
+{\tt IntegralDomain Integer}. The result is a {\tt Field}.\\
+{\bf Z}[$y$] & is the result of applying the functor
+{\tt UnivariatePolynomial} to the object $y$ (from the domain
+{\tt Symbol}) and the domain {\tt Integer} (from the category {\tt Ring}).
+The result is declared to be a {\tt Ring}, or, more precisely, to belong
+to the category {\tt UnivariatePolynomialCategory($R$)}, where $R$ is
+the {\tt Ring} supplied.
+\end{tabular}
+\end{tabular}
+
+\begin{tabular}{rp{11cm}}
+{\bf Package} & Very like a function, but does not specify a new data
+object, merely some new functions. A typical example would be
+{\tt UnivariatePolynomialFunctions2}, which defines the operation
+\begin{verbatim}
+map:(R -> S, UnivariatePolynomial(x,R)) -> UnivariatePolynomial(y,S)
+\end{verbatim}
+where $x$ and $y$ are elements of {\tt Symbol}, and $R$ and $S$ belong
+to the category {\tt Ring}. In mathematical terms, this function takes
+a function $\theta$ from $R$ to $S$, and performs the corresponding
+function from $R[x]$ to $S[y]$. To get the actual function from
+$R[x]$ to $S[y]$, one would have to use Axiom's notation for ``lambda
+expressions'', viz. {\tt map(f,\#1)}, i.e. that function which, given
+an element $p$ of {\tt UnivariatePolynomial(x,R)} computes
+{\tt map(f,$p$)}.
+\end{tabular}
+
+\begin{tabular}{rp{11cm}}
+{\bf Constructor} & The generic term including category, functor, and package.
+\end{tabular}
+
+\section{A first problem -- Weighted Polynomials}
+
+\subsection{The problem definition}
+
+Our aim iere is to emulate CAMAL's (Fitch\cite{Fitc74}) handling of
+``weighted polynomials'', a concept which is also found in Reduce
+(Hearn\cite{Hear87}) via the commands {\tt weight} and
+{\tt wtlevel}. For those not familiar with the idea, we give a quick
+summary here. We will then develop two alternative implementations
+incrementally. The complete definitions will be given in appendices.
+
+Some of the polynomial variables have a (positive integer) {\tt weight}
+associated to them. If $x$ has weight $k$, the $x^n$ has weight $kn$,
+and the weight of a monomial is the sum of the weights of the powers in it.
+This means that the weight of a product of two monomials is the sum of
+the weights. A certain integer (the {\tt weight level}) is chosen, and
+all monomials of weight exceeding this are dropped. If we call this
+dropping operation $\lfloor\rfloor$ (by analogy with the rounding of
+integers), we see that
+$\lfloor{}f+g\rfloor=\lfloor{}f\rfloor+\lfloor{}g\rfloor$, and that
+$\lfloor{}fg\rfloor=\lfloor\lfloor{}f\rfloor\lfloor{}g\rfloor\rfloor$.
+
+The outline implementation we suggest is conceptually similar to that of
+Reduce (Hearn\cite{Hear87}). The weight is stored as the exponent of a
+virtual variable ({\bf k*} in Reduce), and monomials are stored as
+coefficients of the appropriate power of this variable. Reduce does not
+ensure that {\bf k*} has to be the most significant variable, in terms of
+polynomial ordering, and hence the truncation is not as efficient as it
+might be.
+
+The key Axiom functions that we need to use are briefly explained now.
+\begin{itemize}
+\item {\bf Polynomial} is the type Axiom assigns by default to polynomial-like
+objects. These types can be seen in Axiom after every object is computed (use
+the Axiom system command {\tt )set message type on} if they are not being
+shown). This is a functor, which, given a {\tt Ring} $R$, returns a domain in\\
+{\tt PolynomialCategory(R,Symbol,IndexedExponents(Symbol))}, i.e. the
+variables are the elements of the {\tt Symbol} domain, which corresponds to
+ordinary symbols, and the exponents are from {\tt IndexedExponents}, which
+gives a non-negative integer for every symbol (for which it is non-zero).
+Hence this type is a traditional sparse multivariate polynomial, and is
+Axiom's default type. There are others, in particular dense polynomials
+and polynomials represented in a distributed, rather than recursive, fashion,
+but these do not appear unless explicitly called for.
+\item {\bf PolynomialCategory} is the category of the result of
+{\tt Polynomial}, as is show by the browser (the {\tt Parents} option on
+{\tt Polynomial}). This category takes as arguments a {\tt Ring} $R$,
+an {\tt OrderedSet}, known typically as {\tt VarSet}, which represents the
+``variables'' of the polynomial structure, and an
+{\tt OrderedAbelianMonoidSup}\footnote{An
+{\tt OrderedCancellationAbelianMonoid} is a cancellation abelian monoid which
+is also a totally ordered set, such that the ordering is compatible with
+addition: $x\le{}y\Rightarrow{}x+z\le{}y+z$. Since it is a cancellation
+abelian monoid, i.e. satisfies $x+y=y+z\Rightarrow{}x=y$, there is a
+partial subtraction operation: $x-y$ is the unique $z$ such that
+$z+y=x$, if it exists. An {\tt OrderedAbelianMonoidSup} is an
+{\tt OrderedCancellationAbelianMonoid} in which, in addition, there is an
+operation {\tt sup} with respect to the partial ordering induced by
+subtraction. In other words ${\tt sup}(x,y)-x$ and ${\tt sup}(x,y)-y$
+exist, and ${\tt sup}(x,y)$ is minimal (with respect to $<$) with this
+property.}, known as $E$, which represents the exponents of the polynomial
+structure. So a domain in the category {\tt PolynomialCategory(R,E,VarSet)}
+is a representation of polynomials with variables {\tt VarSet} and coefficients
+from $R$, using $E$ as the representation of the exponents.
+\item {\bf PolynomialRing} is used in the implementation of {\tt Polynomial}
+(via\\
+{\tt SparseMultivariatePolynomial}, as can be found by the {\tt Lineage}
+option of the browser). This functor takes as arguments a {\tt Ring} $R$,
+the ring of coefficients, and an\\
+{\tt OrderedAbelianMonoid} $E$, the
+set of exponents, and produces formal polynomials. In particular, if $E$
+is $\mathbb{N}$ (the domain {\tt NonNegativeInteger} in Axiom parlance),
+one gets the standard univariate polynomials, where no name has been
+given to the variable.
+\item {\bf FreeModule} is used in the implementation of {\tt PolynomialRing},
+as can be found by using the {\tt Lineage} option of the browser. This takes
+as arguments a {\tt Ring} $R$ and an {\tt OrderedSet} $S$, and generates
+the free module over $R$ whose generators are indexed by the elements of
+$S$. {\tt PolynomialRing} builds on this, by keeping the definition of
+addition etc., but adding definitions of multiplication, relying on the
+addition between the exponents to define the multiplication of polynomials.
+Let us see precisely how this is defined (we have deleted lines redundant
+to the expository points we wish to make)
+\end{itemize}
+\begin{verbatim}
+PolynomialRing(R:Ring,E:OrderedAbelianMonoid):
+ FiniteAbelianMonoidRing(R,E) with
+ if R has canonicalUnitNormal then canonicalUnitNormal
+ == FreeModule(R,E) add
+ Term:= Record(k:E,c:R)
+ Rep:= List Term
+ 1 == [[0$E,1$R]]
+ p1,p2: %
+ if R has EntireRing then
+ p1 * p2 ==
+ null p1 => 0
+ null p2 => 0
+ p1.first.k = 0 => p1.first.c * p2
+ ps = 1 => p1
+ +/[[[t1.k+t2.k,t1.c*t2.c]$Term for t2 in p2]
+ for t1 in reverse(p1)]
+ -- This 'reverse' is an efficiency improvemant:
+ -- reduces both time and space [Abbot/Bradford/Davenport]
+ else
+ p1 * p2 ==
+ null p1 => 0
+ null p2 => 0
+ p1.first.k = 0 => p1.first.c * p2
+ p2 = 1 => p1
+ +/[[[t1.k+t2.k,r]$Term for t2 in p2 | (r:=t1.c*t2.c) ^= 0]
+ for t1 in reverse(p1)]
+ -- This 'reverse' is an efficiency improvemant:
+ -- reduces both time and space [Abbot/Bradford/Davenport]
+
+ if R has CommutativeRing then
+ p ** nn ==
+ null p => 0
+ nn = 0 => 1
+ p.rest = [] => [[nn * p.first.k, p.first.c ** nn]]
+ binomThmExpt([p.first],p.rest,nn)
+
+ binomThmExpt(x,y,nn) ==
+ nn = 0 => 1$%
+ ans,xn,yn:%
+ bincoef: Integer
+ powl: List(%):= [x]
+ for i in 2..n repeat pow1:=[x * powl.first, :powl]
+ yn:=y; ans:=powl.first; i:=1; bincoef:=nn
+ for xn in powl.rest repeat
+ ans:= bincoef * xn * yn + ans
+ bincoef:= (nn-1) * bincoef quo (i+1); i:=i+1
+ -- last I and BINCOEF unused
+ yn:= y * yn
+ ans + yn
+ else
+ p ** nn == repeatMultExpt(p,nn)
+
+ repeatNultExpt(x,nn) ==
+ nn = 0 => 1
+ y:= x
+ for i in 2..nn repeat y:= x * y
+ y
+\end{verbatim}
+
+The returned domain belongs to the category
+{\tt FiniteAbelianMonoidRing}\footnote{An ``abelian monoid ring'' bears the
+obvious relationship to a ``group ring'': viz. it is the set of formal sums
+of ring elements, indexed by elements of the abelian monoid, with addition
+etc. being defined component-wise, and multiplication making use of the
+addition of abelian monoid indices. The use of the word ``finite'' here is
+to indicate that we consider only {\sl finite} sumes, i.e. the ring element
+is zero for all but finitely many elements of the abelian monoid.}, with the
+additional property {\tt canonicalUnitNormal} (see Davenport \& Trager
+\cite{Dave90} for an explanation of this property) if the ground ring $R$
+has this property. The implementation is to take {\tt FreeModule($R$,$E$)},
+and to add (hence the use of this keyword) certain additional operations
+-- we have just quoted the definition of the unit and multiplication, in
+fact there are more. We find it convenient to work in terms of the
+internal representation of {\tt FreeModule}, hence the {\tt Rep} line
+(which in turn relies on the definition of {\tt Term}). We will see
+further examples of this methodology later on, as method (4) for the
+definition of Axiom functors.
+
+\subsection{The problem specification}
+
+Proceeding in a top-down fashion, we can see that we are going to need
+a construction which takes as arguments a {\tt Ring} $R$, some weights
+for some symbols, and an initial weight level. This will return a {\tt
+Ring} as result, the ring of weighted polynomials, in the named
+symbols (at least), over $R$, with the weight level as specified. At
+this point, certain design decisions need to be made.
+\begin{itemize}
+\item Should the weight level be changeable? In Reduce, it is, and advice
+from the theory of repeated approximation (see, for example, Barton \&
+Fitch\cite{Bart72}) led us to believe that the weight level should be
+changeable.
+\item Should the weights themselves be changeable? In Reduce, they are
+not, and making them changeable would require the re-computation of
+the weights of all products. Of course, the user of Axiom is free to
+build two different domains with different weights assigned in each,
+a flexibility that is not possible in Reduce, and we believe that this
+should be sufficient.
+\item How should the weights be represented. We could produce a separate
+Axiom data type, we could accept them as equations, and insist at run
+time that they be of the form ``symbol=non-negative integer'', or we
+could treat them as a list of symbols and a corresponding list of
+non-negative integers. For simplicity, we chose the last as the user
+interface (but see later for the internal handling).
+\item Should the weighted polynomials contain only the symbols specified
+in the weight list, or others? This is debatable, but it seemed simpler,
+as the implementation progressed, to allow other symbols, which then
+effectively have a weight of 0.
+\end{itemize}
+
+We can now probably write the specification part of this functor.
+\begin{verbatim}
+)abbrev domain OWP OrdinaryWeightedPolynomials
+
+OrdinaryWeightedPolynomials(R:RIng,
+ vl:List Symbol,
+ wl:List NonNegativeInteger,
+ wtlevel:NonNegativeInteger):
+ Ring with
+
+ if R has CommutativeRIng then Algebra(R)
+
+ coerce : % -> Polynomial(R)
+ ++ coerce will convert back into a Polynomial(R), ignoring weights
+
+ coerce : Polynomial(R) -> %
+ ++ coerce a Polynomial(R) into Weighted form,
+ ++ applying weights and ignoring terms
+
+ if R has Field then
+
+ "/" : (%,%) -> Union(%,"failed")
+ ++ a / b, the division only works if minimum weight
+ ++ of divisor is zero, and if R is a Field
+
+ changeWeightLevel : NonNegativeInteger -> Void
+ ++ changeWeightLevel changes the weight level to the new value given:
+ ++ NB: previously calculated terms are not affected
+\end{verbatim}
+
+The {\tt )abbrev} line is necessary for the definition of any functor,
+since the abbreviation (up to eight letters, or seven for a category)
+defines, among other things, the name of the directory in which the
+compiled code will be stored.
+
+Axiom comments begin with either $--$ or $++$. The former
+fulfil the traditional role of commenting programs. The latter, which can
+only appear in the appropriate contexts, are picked out by the program
+that builds the HyperDoc database, and can be retrieved by HyperDoc
+when it comes to describing operations (as in the case of the
+{\tt changeWeightLevel} operation quoted above) or the whole
+constructors.
+
+Axiom checks the first word of $++$ comments on functions to
+see that it is the name of the function. If not, it complains.
+
+In general, there should be examples given for every function, using
+the $++{\rm X}$ syntax. Comment lines starting with these three
+characters are displayed as help text when the user asks about a
+function with {\tt )display operation}.
+
+We could now start implementing this data type, but a thought crosses
+our mind. While {\tt Polynomial} is Axiom's default representation, it
+is not the only one, and it would be a pity for this ``weighted
+polynomial'' facility not to be available for other implementations
+as well. Hence we decide that we will implement
+{\tt OrdinaryWeightedPolynomials} in terms of a more general constructor,
+which takes the polynomial type as an argument. This leads to the
+following implementation for the body of {\tt OrdinaryWeightedPolynomials}.
+\begin{verbatim}
+ == WeightedPolynomials(R,Symbol,IndexedExponents(Symbol),
+ Polynomal(R),vl,wl,wtlevel)
+\end{verbatim}
+This is essentially and {\tt add} form in which nothing is being added:
+the operations of\\
+{\tt OrdinaryWeightedPolynomials} will be precisely
+those of {\tt WeightedPolynomials}.
+
+The header of {\tt WeightedPolynomials} now practically writes itself.
+\begin{verbatim}
+)abbrev domain WP WeightedPolynomials
+
+WeightedPolynomials(R:RIng,VarSet: OrderedSet, E:OrderedAbelianMonoidSup,
+ P:PolynomialCategory(R,E,Varset),
+ vl:List Varset, wl:List NonNegativeInteger,
+ wtlevel:NonNegativeInteger):
+ Ring with
+ if R has CommutativeRing then Algebra(R)
+
+ coerce : % -> P
+ ++ coerce convers back into a "P", ignoring weights
+
+ if R has Field then
+
+ "/": (%,%) -> Union(%,"failed")
+ ++ a / b division only works if minimum weight
+ ++ of divisor is zero, and if R is a Field
+
+ coerce : P -> %
+ ++ coerce a "P" into Weighted form, applying weights and ignoring terms
+
+ changeWeightLevel : NonNegativeInteger -> Void
+ ++ changeWeightLevel changes the weight level to the new value given:
+ ++ NB: previously calculated terms are not affected
+\end{verbatim}
+
+How are we going to implement this type? There are various possibilities
+for implementing a functor in Axiom.
+\begin{itemize}
+\item[(1)] Direct re-use of another domain, as\\
+{\tt OrdinaryWeightedPolynomials} re-uses {\tt WeightedPolynomials}
+\item[(2)] An existing domain with new operators added by means of an
+{\tt add} clause. The previous method can be viewed as a trivial case
+of this method.
+\item[(3)] A new implementation, where the representation of the data
+objects is defined, but all operations are defined from scratch (or
+provided by the default definitions given in certain categories)
+\item[(4)] A hybrid approach, where a domain is added to, but we also
+quote its representation in order to dive into its internals. This is
+quite common (see, for example, the definition of {\tt PolynomialRing}
+in terms of {\tt FreeModule}), but also the most dangerous, as the
+domain to which one adds is no longer being treated as a ``black box'',
+but rather as something one can dive into at will. Any changes in the
+representation of the domain being added to can invalidate the new
+domain being built.
+\end{itemize}
+
+\subsection{The problem implementation}
+
+Let us first try the third method, where we use {\tt PolynomialRing} as
+our representation. The essentials of our implementation will then
+look as follows (the details of {\tt coerce (p\pageref{coerce})}
+ etc. will be discussed
+later).
+\begin{verbatim}
+ Rep := PolynomialRing(P,NonNegativeInteger)
+ w,x1,x2:%
+
+ 0 == 0$Rep
+
+ 1 == 1$Rep
+
+ x1 = x2 ==
+ -- Note that we must strip out any terms greater than wtlevel
+ while degree x1 > wtlevel repeat
+ x1 := reductum x1
+ while degree x2 > wtlevel repeat
+ x1 := reductum x2
+ x1 =$Rep x2
+
+ x1 + x2 == x1 +$Rep x2
+
+ -x1 == -$Rep x1
+
+ x1 * x2 ==
+ -- Note that this is probalby an extremely inefficient definition
+ w:=x1 * $Rep x2
+ while degree(w) > wtlevel repeat
+ w:=reductum w
+ w
+\end{verbatim}
+
+One important point that crops up here is the necessity to distinguish
+the operations of the representation ({\tt PolynomialRing}) from those
+of the type being defined. Since elements can be viewed as belonging
+to either the data type or its representation, there is a potential for
+ambiguity, when the data type and the representation have operations of
+the same signature. In this case, the unqualified operation name will
+refer to that of the data type, and that of the representation has to
+be obtained by use of the {\tt \$Rep} syntax -- meaning use the operation
+from the data type {\tt Rep}. A trivial example of the definition of
+$+$ given above, which can be paraphrased in English as ``to add
+two elements of {\tt WeightedPolynomials}, add them as if they were
+elements of the representation, i.e. elements of {\tt PolynomialRing}.''
+Slightly more complicated is the definition of equality, which can be
+paraphrased in English as ``to test two elements of {\tt WeightedPolynomials}
+for equality, first remove any terms of weight greater than the current
+weight level, then test them for equality as elements of the represention,
+i.e. elements of {\tt PolynomialRing}''. It is perhaps worth noting that
+a side-effect of this is that calls to {\tt changeWeightLevel} can
+affect the result of equality tests.
+
+The reader may well say ``{\tt Ring} was meant to define many more
+operations than you have done there -- where are the rest?'' The answer
+is that these are provided by the defaulting operations in the various
+categories. For example, the first operation we have not defined is the
+multiplication operation with signature {\tt "*":(Integer,\pct) -> \pct}.
+This is acquired by default from the category {\tt AbelianGroup}, an
+ancestor of {\tt Ring}, where the operation is defined by
+\begin{verbatim}
+AbelianGroup() : Category == SIG where
+
+ SIG ==> CancellationAbelianMonoid with
+
+ "*" : (Integer,%) -> %
+ ++ n*x is the product of x by the integer n.
+\end{verbatim}
+
+\subsection{The {\tt PolynomialRing} implementation}
+
+Here we use {\tt PolynomialRing} as our base type, as well as our
+representation, in what corresponds to method (4) of the choice
+outlined earlier. Again, we have left the various definitions of
+{\tt coerce (p\pageref{coerce})} etc.
+for later consideration: we focus here on the
+differences between this implementation and the previous one.
+\begin{verbatim}
+ == PolynomialRing(P,NonNegativeIntger)
+ add
+ --representations
+ Term := Record(k:NonNegativeInteger,c:P)
+ Rep := List Term
+ w,x1,x2:%
+
+ x1 * x2 ==
+ null x1 => 0
+ null x2 => 0
+ r:P
+ x1.first.k = 0 =>
+ [[t2.k,r]$Term for t2 in x2 | (r:=x1.first.c * t2.c) ^= 0]
+ x2 = 1 => x1
+ +/[[[n,r]$Term for t2 in x2 | (n:=t1.k+t2.k) <= wtlevel and
+ (r:=t1.c*t2.c) ^= 0]
+ for t1 in reverse(x1)]
+ -- This 'reverse' is an efficiency improvement:
+ -- reduces both time and space [Abbott/Bradford/Davenport]
+
+ import RepeatedSquaring(%)
+
+ x:% ** n:NonNegativeInteger ==
+ zero? n => 1
+ expt(x,n pretend PositiveInteger)
+\end{verbatim}
+
+We still need a definition of equality, since the definition from
+{\tt PolynomialRing} is not adequate, as it does not take account of
+the current value of the weight level. While the algorithm is very
+similar, the implementation has to be in terms of the newly-defined
+{\tt Rep}, which is a list of terms. Hence {\tt degree(x1)} is
+replaced by {\tt x1.first.k}. Simliarly, the construction {\tt =\$Rep}
+does not work, since the {\tt Rep} is now just a list of objects, and
+has to be replaced by an explicit copy of the definition of equality
+from {\tt PolynomialRing}, which is in fact inherited from
+{\tt IndexedDirectProductAbelianGroup}.
+
+We no longer need definitions of 0 and 1, which are picked up from
+{\tt PolynomialRing}, nor definitions of addition and subtraction.
+We do, however, need a definition of multiplication, since the
+definition in {\tt PolynomialRing} does not drop terms greater than
+the weight level. This definition is based on that given earlier for
+multiplication in {\tt PolynomialRing}.
+
+In addition, we now need a definition of exponentiation. The reason
+for this is related to one of the major stumbling-blocks people find
+when programming in Axiom, so we shall analyse it carefully. We have
+already said that it is not necessary to provide all the definitions
+required for a data type, as they could be picked up from defaulting
+packages. When methodologies (2) or (4) are used, there are in fact
+two places where such missing definitions could be picked up from:
+the defaulting packages or the so-called {\tt add} chain -- the functor
+which is quoted in the {\tt add} clause, or, recursively, the functor
+which is quoted in its {\tt add} clause, and so on. Which should we
+use? The rule in Axiom is quite simple, though its implications are
+profound.
+
+{\bf Principle 9}: {\sl A function is first searched for in the
+implementation of a given functor, then recursively up the {\tt add}
+chain, without examining defaulting packages. If this fails to find a
+definition, then the defaulting packages are searched, from most
+specific to most general.}
+
+
+The implications of this rule for exponentiation are as follows.
+\begin{itemize}
+\item[(i)] There is a default definition of exponentiation in {\tt Monoid},
+and hence in {\tt Ring}, which works by repeated squaring. This
+definition would be perfectly adequate for our use (using multiplication
+we have just defined in {\tt WeightedPolynomials})
+\item[(ii)] There are other definitions of exponentiation in
+{\tt PolynomialRing}, as we have seen earlier, which use the binomial
+theorem if the coefficient ring is commutative, and a repeated
+multiplication algorithm otherwise.
+\item[(iii)] Therefore, by the rule quoted above, it is one of the
+definitions in (ii) which will be used. Hence, they will use the definition
+of multiplication defined in {\tt PolynomialRing}, and so will not take
+advantage of the weight level.
+\end{itemize}
+Hence, in order to get a satisfactory implementation of exponentiation,
+we need to repeat the defaulting definition, or provide some definition
+that will use the multiplication of {\tt WeightedPolynomials}.
+
+A related issue comes up in the definitions of {\tt zero?} and {\tt one?}.
+These are defined, in {\tt AbelianMonoid} and {\tt Monoid} respectively,
+to have defaulting definitions {\tt zero? x == x=0} and
+{\tt one? x == x=1}. Since these definitions happen not to be over-ridden
+in the {\tt add} chain, they are the definitions that apply in
+{\tt WeightedPolynomials}, and so use {\tt WeightedPolynomials}'
+definition of equality.
+
+{\sl However}, were a later author of {\sl PolynomialRing} to add other
+definitions, these would be picked up instead.
+
+\subsection{Miscellaneous definitions}
+
+Here we give some miscellaneous definitions that should form part of
+the implementation of {\tt WeightedPolynomials}. The first three lines
+deal with the definition of {\tt changeWeightLevel}.
+\begin{verbatim}
+ n:NonNegativeInteger
+
+ changeWeightLevel(n) ==
+ wtlevel:=n
+\end{verbatim}
+
+We had earlier decide to represent the weights by a list of variables
+and a corresponding list of weights, but this is rather clumsy for
+internal manipulation. Hence the next few lines define an internal
+data structure called {\tt lookupList}, initialize it, and provide a
+local function (i.e. one not usable outside the body of the functor)
+for looking up the weight attached to a particular variable.
+\begin{verbatim}
+ lookupList: List Record(var:VarSet, weight:NonNegativeInteger)
+
+ if #vl ^= #wl then error "incompatible length lists in WeightedPolynomial"
+
+ lookupList:=[[v,n] for v in vl for n in wl]
+
+ lookup:Varset -> NonNegativeInteger
+ lookup v ==
+ l:=lookupList
+ while l ^= [] repeat
+ v = l.first.var => return l.first.weight
+ l:=l.rest
+ 0
+\end{verbatim}
+We now have to have some method of creating elements of the domain
+{\tt WeightedPolynomials}. The obvious way is to provide a coercion
+operator from $P$ (which in the case of\\
+{\tt OrdinaryWeightedPolnomials}
+will be the usual type {\tt Polynomial} of Axiom) to\\
+{\tt WeightedPolynomials}. This is the function of the next few lines.
+{\tt coerce} itself is simple: it just calls {\tt innercoerce}, passing
+it the weight level. {\tt innercoerce} recursively deconstructs the
+input polynomial, decreasing the weight level as appropriate.
+\begin{verbatim}
+ p:P
+ z:Integer
+
+ innercoerce:(p,z) -> %
+ innercoerc(p,z) ==
+ z < 0 => 0
+ zero? p => 0
+ mv:= mainVariable p
+ mv case "failed" => [[0,p]]
+ n:=lookup(mv)
+ up:=univariate(p,mv)
+ ans:%
+ ans:=0
+ while not zero? up repeat
+ d:=degree up
+ f:=n*d
+ lcup:=leadingCoefficient up
+ up:=up-leadingMonomial up
+ mon:=monomial(1,mv,d)
+ f <= z => ans:=ans+[[tm.k+f,mon*tm.c] for tm in innercoerce(lcup,z-f)]
+ ans
+
+ coerce(p):% == innercoerce(p,wtlevel)
+\end{verbatim}
+\label{coerce}
+The inverse operation is much simpler: we have merely to add up the
+coefficients.
+\begin{verbatim}
+ coerce(w):P == "+"/[tm.c for tm in w]
+\end{verbatim}
+The last definition is that of coercion from {\tt WeightedPolynomials}
+into {\tt OutputForm} -- Axiom's type for output (and conversion to
+TeX etc.). This is fairly simple: the main complexity is in the
+specification. Here we have decided that a single term of zero weight
+will print as such, but that otherwise each group of terms of a particular
+weight will be printed parenthesised (even if there is only one term
+of that weight). Clearly, it would be possible to adapt this definition
+to almost any other desired behaviour.
+\begin{verbatim}
+ coerce(p:%):OutputForm ==
+ zero? p => (0$Integer)::OutputForm
+ p.first.k = 0 => p.first.c::OutputForm
+ reduce("+",(reverse [paren(t1.c::OutputForm) for t1 in p])::List OutputForm
+\end{verbatim}
+
+\section{A second problem -- FourierSeries}
+
+\subsection{The problem definition}
+
+Our aim here is to implement an equivalent of CAMAL's (Fitch\cite{Fitc74})
+handling of truncated Fourier series. We have some domain of ``angles''
+-- in CAMAL's case linear combinations with integer coefficients (lying
+in the range $-63\ldots 63$) of the eight angular variables
+$s,\ldots,z$. We can build sin or cos of these variables, and use them as
+coefficients in polynomial expressions, where products of trigonometric
+functions are always linearised. There are more operations provided in
+CAMAL, e.g. integration with respect to an angular variable, but we will
+not bother with these for simplicity of exposition.
+
+Within CAMAL, the coefficients of expressions in these trigonometric
+functions will therefore not involve other trigonometric functions, but
+will involved weighted polynomials. These we have already defined, and
+there seems no absolute need to use weighted polynomials, though they
+are in practice the most common type of coefficient required. However,
+we probably need to assume that the coefficients commute with each other
+and with the trigonometric terms, since otherwise the linearisation of
+products is not well-defined. Furthermore, since
+\[\sin(A)\sin(B)=\frac{\cos(A-B)-\cos(A+B)}{2}\]
+we must be able to divide by two. For simplicity, therefore, we insist
+on the ability to divide by any non-zero integer, i.e. that the
+coefficients should be an Algebra over $\mathbb{Q}$, the Axiom
+type {\tt Fraction Integer}.
+
+\subsection{The problem specification}
+
+The header of our type Fourier Series now nearly writes itself. The
+arguments of the trigonometric functions had better be an ordered set,
+so that we can order the various trigonometric functions, and an
+abelian group so that the addition and subtraction rules can take place.
+It would therefore be possible to require that the domain of these
+arguments should be an {\tt OrderedAbelianGroup}, but this may be
+too strong, and we will restrict ourselves to insisting on
+{\tt Join(OrderedSet,AbelianGroup)}\footnote{An
+{\tt OrderedAbelianGroup} would also have the property that
+$a** %
+ ++ coerce convers coefficients into Fourier Series
+
+ coerce : FourierCompoents(E) -> %
+ ++ coerce converts sin/cos terms into Fourier Series
+
+ makeSin : (E,R) -> %
+ ++ makeSin makes a sin expression with given argument and coefficient
+
+ makeCos : (E,R) -> %
+ ++ makeCos makes a cos expression with given argument and coefficent
+\end{verbatim}
+The operations here (with the exception of the last
+{\tt coerce (p\pageref{coerce2})}, will be explained in the next
+section, are pretty obvious. What about the line containing the word
+``{\tt canonical}''? Axiom's definition of the attribute {\tt canonical}
+\index{canonical}
+is that a domain is canonical if mathematical equality implies
+equality of data structure. In particular, it authorises the use of
+hash-based techniques. There is a discussion in Davenport \&
+Trager\cite{Dave90} and more detail is available in
+Davenport et al.\cite{Dave88}. In our case, we are saying that, if the
+coefficients and arguments are canonical, then the data type returned
+will also be.
+
+The obvious implementation of this is via some kind of {\tt FreeModule},
+using $R$ as the coefficients and the trigonometric functions as the
+indices. However, we first need to define the trigonometric functions
+themselves, and this is the purpose of the next secion. We will return to
+the type {\tt FourierSeries} in the section following.
+
+\subsection{The {\tt FourierComponent implementation}}
+
+It would be possible to use Axiom's general-purpose type {\tt Expression}
+to represent trigonometric functions, but we settled, for pedagogic reasons
+and partly to keep our code reasonably self-contained, on a separate
+data type.
+
+The requirements on this data type are quite straight-forward. It should
+provide ways of making sin and cos functions, and the result should be an
+{\tt OrderedSet} so that it can be passed to {\tt FreeModule}. The header
+is then equally straight-forward.
+\begin{verbatim}
+FourierComponent(E:OrderedSet):
+
+ OrderedSet with
+
+ sin : E -> %
+ ++ sin makes a sin kernel for use in Fourier series
+
+ cos : E -> %
+ ++ cos makes a cos kernel for use in Fourier series
+
+ sin? : % -> Boolean
+ ++ sin? is true if term is a sin, otherwise false
+
+ argument : % -> E
+ ++ argument returns the argument of a given sin/cos expression
+ ==
+\end{verbatim}
+
+Here method (3) seems an appropriate way of defining the data type -- all
+we need store is the argument and a flag indicating whether we have a
+sin or cos expression. The first part of the implementation is trivial.
+\begin{verbatim}
+ add
+
+ --representations
+ Rep:=Record(SinIfTrue:Boolean, arg:E)
+ e:E
+ x,y:%
+
+ sin e == [true,e]
+
+ cos e == [false,e]
+
+ sin? x == x.SinIfTrue
+
+ argument x == x.arg
+\end{verbatim}
+The harder question is the order to be imposed on {\tt FourierComponent}.
+We have chosen, for no very good reason, to use the order of the arguments,
+and break ties by sorting cos $a$ as less than sin $a$. Clearly this
+definition could be adapted to any other strategy.
+\begin{verbatim}
+ x < y ==
+ x.arg < y.arg => true
+ y.arg < x.arg => false
+ x.SinIfTrue => false
+ y.SinIfTrue
+\end{verbatim}
+The last task of this method of printing the results -- again this is
+achieved by means of a conversion to {\tt OutputForm}. We have used the
+constructor {\tt bracket}, which places the argument in square brackets,
+in order to distinguish these elements from the ordinary {\tt Expression}
+constructions of Axiom.
+\begin{verbatim}
+ coerce(x):OutputForm ==
+ hconcat((if x.SinIfTrue then "sin" else "cos")::OutputForm,
+ bracket((x.arg)::OutputForm))
+\end{verbatim}
+
+\subsection{The {\tt FourierSeries implementation}}
+
+Now that we have {\tt FourierComponent}, we can define {\tt FourierSeries}.
+We chose again to use method (4), basing the definition on
+{\tt FreeModule(R,FourierComponent(E)). Hence the start of the definition
+looks as follows.
+\begin{verbatim}
+ == FreeModule(R,FourierComponent(E)) add
+ -- representations
+ Term := Record(k:FourierComponent(E),c:R)
+ Rep := List Term
+ multiply : (Term,Term) -> %
+ w,x1,x2 : %
+ t1,t2 : Term
+ n : NonNegativeInteger
+ z : Integer
+ e : FourierComponent(E)
+ a : E
+ r : R
+\end{verbatim}
+{\tt multiply (p\pageref{multiply})} is a local function,
+to be defined later, which will
+multiply two terms. The result may well not be a single term, due to
+linearisation, but is an element of the FourierSeries domain. We know
+that cos 0 = 1 and sin 0 = 0. Furthermore, in order to ensure the
+``canonical'' part, we must be careful about trigonometric functions
+with negative arguments (the concept of ``negative'' makes sense: an
+element is negative if it is less than 0). The following definitions
+help implement this policy.
+\label{coerce2}
+\begin{verbatim}
+ 1 == [[cos 0,1]]
+
+ coerce e ==
+ sin? e and zero? argument e => 0
+ if argument e < 0 then
+ not sin? e => e:=cos(- argument e)
+ return [[sin(- argument e),-1]]
+ [[e,1]]
+
+ makeCos(a,r) ==
+ a < 0 => [[cos(-a),r]]
+ [[cos a,r]]
+
+ makeSin(a,r) ==
+ zero? a => []
+ a < 0 => [[sin(-a),-r]]
+ [[sin a,r]]
+\end{verbatim}
+The operations of addition and subtraction, as well as multiplication by
+elements of $R$, are all well-inherited from {\tt FreeModule}. We do
+however have to define multiplication of two Fourier series, and this
+is done below.
+\label{multiply}
+\begin{verbatim}
+ multiply(t1,t2) ==
+ r:=(t1.c*t2.c)*(1/2)
+ s1:=argument t1.k
+ s2:=argument t2.k
+ sum:=s1+s2
+ diff:=s1-s2
+ sin? t1.k =>
+ sin? t2.k =>
+ makeCos(diff,r)+makeCos(sum,-r)
+ makeSin(sum,r) + makeSin(diff,r)
+ sin? t2.k =>
+ makeSin(sum,r) + makeSin(diff,r)
+ makeCos(diff,r) + makeCos(sum,r)
+
+ x1+x2 ==
+ null x1 => 0
+ null x2 => 0
+ +/[+/[multiply(t1,t2) for t2 in x2] for t1 in x1]
+\end{verbatim}
+
\chapter{Axiom and Category Theory}
\section{Covariance and Contravariance}
Axiom has an order relation between types. The types can be in one of
@@ -337,6 +2659,614 @@ non-commutative algebra, LiePolynomial and XPBWPolynomial.
\end{verbatim}
which is correct.
+\chapter{Writing test cases}
+
+\appendix
+\chapter{The Principles of Axiom}
+{\bf Principle 1}. {\sl AXIOM has an interpreter for interactive use, much
+like any other system, and a compiler for creating new user-defined
+data types. The compiler emphasises strict type-checking, whilst the
+interpreter is more oriented towards ease of use.}
+
+{\bf Principle 2}. {\sl Every internal Axiom data object belongs to
+one and only one domain.}
+
+{\bf Principle 3}. {\sl Values can freely move from sub-domains to
+larger ones, and, in the interpreter only, in the other direction,
+provided that this conversion is legitimate.}
+
+{\bf Principle 4}. {\sl The interpreter is responsible for performing any
+chain of coercions necessary to understand the user's intentions, or
+when required to do so by an explicit use of {\bf ::} . The compiler will
+perform a chain of coercions when instructed to do so by the {\bf ::}
+operator in compiled code.}
+
+{\bf Principle 5}. {\sl Any set of Axiom domains $D_1,\ldots,D_n$ can be
+combined into a (disjoint) union domain, denoted
+{\tt Union}($D_1,\ldots,D_n$). The $D_i$ are called the {\bf branches} of the
+union. The operations available on this union domain are:}
+\begin{itemize}
+\item {\sl equality -- two elements are equal if they come from the same
+branch and are equal in that branch;}
+\item {\sl coercion to OutputForm;}
+\item {\sl coercion from each $D_i$ to the union domain;}
+\item {\sl coercion to each $D_i$ from the union domain, which may fail if
+the union object is not in the correct branch;}
+\item {\sl an in x predicate case , for testing if the union object
+actually is in a particular branch or not.}
+\end{itemize}
+{\sl These union domains correspond to what some other languages call
+``sum types''. A particularly useful case is exemplified by the
+``exact quotient'' operation on {\tt Integer}: its return type is
+{\tt Union(Integer,"failed")},
+where the special token {\tt failed} is returned if the division is not exact.}
+
+{\bf Principle 6}. {\sl The Axiom library declares a family of second-order
+types, known as {\bf categories}. The categories are arranged in a directed
+acyclic graph, and each domain belong to a specific category, and to all
+the ancestors of that category. The specification of a category includes}
+\begin{itemize}
+\item {\sl all its direct ancestors,}
+\item {\sl any additional operations that this category supports, and}
+\item {\sl any additional axioms that the operations must satisfy.}
+\end{itemize}
+{\sl The operation {\tt Join} is used to construct new categories.}
+
+{\bf Principle 7}. {\sl Categories can introduce {\bf default definitions}
+of operations, which will take effect in any domain belonging to that
+category unless overridden by a definition in that domain, or in a
+more specific category.}
+
+{\bf Principle 8}.
+{\sl The functors of Axiom are strongly typed: each parameter which is
+an Axiom object is specified to come from a particular domain; each parameter
+which is an Axiom domain is specified to belong to a particular Axiom
+category. Similarly, the domain returned by a particular functor is
+specified to belong to a particular category. All construction of domains
+must satisfy these constraints on the functors.}
+
+{\bf Principle 9}.
+{\sl A function is first searched for in the implementation of a given functor,
+then recursively up the {\tt add} chain, without examining defaulting
+packages. If this fails to find a definition, then the defaulting
+packages are searched, from most specific to most general.}
+
+\chapter{The Axiom Conventions}
+{\bf Convention 1}.
+{\sl Juxtaposition corresponds to (unary) function application.}
+
+{\bf Convention 2 (borrowed from APL)}. {\sl All system commands,
+i.e. those that do not perform, or affect the performance of, algebraic
+operations, begin with {\bf )}. In general, they may be contracted as far
+as is unambiguous, so that {\tt )set message type on} can be contracted as
+far as {\tt )se m ty on}}
+
+{\bf Convention 3}. {\sl The symbol {\bf \pct} refers to the most recently
+computed proper value (i.e. not of the {\tt Void} domain). {\bf \pct\pct(n)},
+or {\bf \pct\pct n}, refers to the value numbered $n$, if $n$
+is a positive integer.
+If n is a negative integer, {\bf \pct\pct (n)} refers to the value of the
+$\vert{}n\vert$'th previous step. Also, {\bf \pct{}pi} refers to $\pi$,
+{\bf \pct{}e} to $e \approx 2.718281828$ and {\bf \pct{}i} to $\sqrt{-1}$}
+
+{\bf Convention 4 (a convention of the library, rather than of the kernel)}.
+{\sl Parentheses -- {\bf ()} -- are used for grouping and function
+application, brackets -- {\bf []} -- are used for constructing lists,
+and braces -- {\bf \{\}} -- are used for constructing sets.}
+
+{\bf Convention 5}. {\sl The {\bf ::} in x operator, used as in}
+\[Axiom\thinspace{} object :: Axiom\thinspace{} domain\]
+{\sl can be used to convert the object to lie in the specified domain.}
+
+{\bf Convention 6 (Of the library authors)}. {\sl The notation}
+\[list\thinspace{} of\thinspace{} variables +-> expression\]
+{\sl defines an anonymous function of those variables. It corresponds
+to the lambda-calculus expression ``$\lambda$variables.expression''.}
+
+{\bf Convention 7}. {\sl The names of Axiom functions are either special
+symbols (such as $+$) or complete english words strung together. In this
+case, every word after the first is capitalised. Thus {\tt integrate}
+but {\tt complexIntegrate}. In addition:}
+\begin{itemize}
+\item {\sl all boolean predicates end in a {\bf ?} , as in {\tt odd?},
+which tests if a number is odd}
+\item {\sl all destructive functions which operate on data structures
+end in a {\bf !} , as in {\tt reverse!}, which reverses a list destructively.}
+\end{itemize}
+{\sl Conversely, the names of domains (and other constructors we will come
+to later) consist of english words strung together, all of which are
+capitalised, as in {\tt IntegerMod} or {\tt UnivariatePuiseuxSeries}.}
+
+{\bf Convention 8}. {\sl Whenever a category, or domain, is being discussed
+in Axiom, the symbol \pct{} stands for the domain in question, or for any
+domain from the category in question.}
+
+{\bf Convention 9}. {\sl Axiom comments can be introduced by {\bf $--$} or
+{\bf $++$}. Those beginning {\bf $++$} are intended for the user, and can
+be retrieved by the on-line help system.}
+
+{\bf Convention 10}. {\sl The infix binary predicate {\tt has} can be used
+to test if domains belong to categories, or if they have specified attributes.}
+
+{\bf Convention 11}. {\sl Every Axiom {\bf constructor}, i.e. functor or
+category, has an {\bf abbreviation}, consisting of at most eight
+upper-case letters (seven in the case of categories). These serve
+two purposes: they can be used on input and output in order to make the
+names of the types shorter, and they denote the directory in which the
+corresponding Axiom library lives. The defaults for category {\tt Cat},
+with abbreviation {\tt CAT}, are called {\tt Cat\&} ,
+with abbreviation {\tt CAT-}.}
+
+\chapter{Example Code}
+\section{domain WP WeightedPolynomials}
+--Copyright The Numerical Algorithms Group Limited 1992.
+\begin{chunk}{domain WP WeightedPolynomials}
+)abbrev domain WP WeightedPolynomials
+++ Author: James Davenport
+++ Date Created: 17 April 1992
+++ Date Late Updated: 13 July 2016 by Tim Daly
+++ Basic Functions: Ring, changeWeightLevel
+++ Related Constructors: PolynomialRing
+++ Also See: OrdinaryWeightedPolynomials
+++ AMS Classificaitons:
+++ Keywords:
+++ References:
+++ Description:
+++ This domain represents truncated weighted polynomials over a general
+++ (not necessarily commutative) polynomial type. The variables must be
+++ specified, as must the weights.
+++ The representation is sparse
+++ in the sense that only non-zero terms are represented
+WeightedPolynomials(R,VarSet,E,P,vl,wl,wtlevel) : SIG == CODE where
+ R : Ring
+ Varset : OrderedSet
+ E : OrderedAbelianMonoidSup
+ P : PolynomialCategory(R,E,Varset)
+ vl : List Varset
+ wl : List NonNegativeInteger
+ wtlevel : NonNegativeInteger
+
+ SIG ==> Ring with
+
+ if R has CommutativeRing then Algebra(R)
+
+ coerce : % -> P
+ ++ coerce converts back into "P", ignoring weights
+
+ if R has Field then
+
+ "/" : (%,%) -> Union(%,"failed")
+
+ coerce : P -> %
+ ++ coerce a "P" into Weighted form, applying weights and ignoring terms
+
+ changeWeightLevel : NonNegativeInteger -> Void
+ ++ changeWeightLevel changes the weight level to the new value given:
+ ++ NB: previously calculated terms are not affected
+
+ CODE ==> add
+
+ -- representations
+ Rep := PolynomialRIng(P,NonNegativeInteger)
+ p : P
+ w,x1,x2 : %
+ n : NonNegativeInteger
+ z : Integer
+
+ changeWeightLevel(n) ==
+ wtlevel := n
+
+ lookupList : List Record(var:Varset, weight:NonNegativeInteger)
+
+ if #vl ^= #wl then error "incompatible length lists in WeightedPolynomial"
+
+ lookupList := [[v,n] for v in vl for n in wl]
+
+ -- local operations
+
+ lookup : Varset -> NonNegativeInteger
+ loopkup v ==
+ l := lookupList
+ while l ^= [] repeat
+ v = l.first.var => return l.first.weight
+ l := l.rest
+ 0
+
+ innercoerce : (p,z) -> %
+ innercoerce(p,z) ==
+ z < 0 => 0
+ zero? p => 0
+ mv := mainVariable p
+ mv case "failed" => monomial(p,0)
+ n := lookup(mv)
+ up := univariate(p,mv)
+ ans : %
+ ans := 0
+ while not zero? up repeat
+ d := degree up
+ f := n*d
+ lcup := leadingCoefficient up
+ up := up-leadingMonomial up
+ mon := monomial(1,mv,d)
+ f <= z =>
+ tmp := innercoerce(lcup,z-f)
+ while not zero? tmp repeat
+ ans := ans+monomial(mon*leadingCoefficent(tmp),degree(tmp)+f)
+ tmp := reductum tmp
+ ans
+
+ coerce(p):% == innercoerce(p,wtlevel)
+
+ coerce(w):P == "+"/[c for c in coefficients w]
+
+ coerce(p:%):OutputForm ==
+ zero? p => (0$Integer)::OutputForm
+ degree p = 0 => leadingCoefficient(p)::OutputForm
+ reduce("+",(reverse [paren(c::OutputForm) for c in coefficients p])
+ ::List OutputForm)
+
+ 0 == 0$Rep
+
+ 1 == 1$Rep
+
+ x1 = x2 ==
+ -- Note that we must strip out any terms greater than wtlevel
+ while degree x1 > wtlevel repeat
+ x1 := reductum x1
+ while degree x2 > wtlevel repeat
+ x2 := reductum x2
+ x1 = $Rep x2
+
+ x1 + x2 ==
+ x1 +$Rep x2
+
+ x1 * x2 ==
+ -- Note that this is probably an extremely inefficient definition
+ w := x1 *$Rep x2
+ while degree(2) > wtlevel repeat
+ w := reductum w
+ w
+\end{chunk}
+
+\section{domain OWP OrdinaryWeightedPolynomials}
+--Copyright The Numerical Algorithms Group Limited 1992.
+
+\begin{chunk}{domain OWP OrdinaryWeightedPolynomials}
+)abbrev domain OWP OrdinaryWeightedPolynomials
+++ Author: James Davenport
+++ Date Created: 17 April 1992
+++ Date Last Updated 13 July 2016 by Tim Daly
+++ Basic Functions: Ring, changeWeightLevel
+++ Related Constructors: WeightedPolynomials
+++ Also See: PolynomialRing
+++ AMS classifications:
+++ Keywords:
+++ References:
+++ Description:
+++ This domain represents truncated weighted polynomials over the
+++ "Polynomial" type. The variables must be
+++ specified, as must the weights.
+++ The representation is sparse
+++ in the sense that only non-zero terms are represented
+OrdinaryWeightedPolynomials(R,vl,wl,wtlevel) : SIG == CODE where
+ R : Ring
+ vl : List Symbol
+ wl : List NonNegativeInteger
+ wtlevel : NonNegativeInteger
+
+ SIG ==> Ring with
+
+ if R has CommutativeRing then Algebra(R)
+
+ coerce : % -> Polynomial(R)
+ ++ coerce converts back into a Polynomial(R), ignoring weights
+
+ coerce : Polynomial(R) -> %
+ ++ coerce a Polynomial(R) into Weighted form,
+ ++ applying weights and ignoring terms
+
+ if R has Field then
+
+ "/": (%,%) -> Union(%,"failed")
+ ++ a / b only works if minimum weight of divisor is zero,
+ ++ and if R is a Field
+
+ changeWeightLevel : NonNegativeInteger -> Void
+ ++ This changes the weight level to the new value given:
+ ++ NB: previously calculated terms are not affected
+
+ CODE ==> WeightedPolynomials(R,Symbol,IndexedExponents(Symbol),
+ Polynomial(R),vl,wl,wtlevel)
+\end{chunk}
+
+\section{domain WP2 WeightedPolynomials2}
+\begin{chunk}{domain WP2 WeightedPolynomials2}
+)abbrev domain WP2 WeightedPolynomials2
+++ Author: James Davenport
+++ Date Created: 17 April 1992
+++ Date Last Updated 13 July 2016 by Tim Daly
+++ Basic Functions: Ring, changeWeightLevel
+++ Related Constructors: PolynomialRing
+++ Also See: OrdinaryWeightedPolynomials
+++ AMS classifications:
+++ Keywords:
+++ References:
+++ Description:
+++ This domain represents truncated weighted polynomials over a general
+++ (not necessarily commutative) polynomial type. The variables must be
+++ specified, as must the weights.
+++ The representation is sparse
+++ in the sense that only non-zero terms are represented
+WeightedPolynomials2(R,Varset,E,P,vl,wl,wtlevel) : SIG == CODE where
+ R : Ring
+ Varset : OrderedSet
+ E : OrderedAbelianMonoidSup
+ P : PolynomialCategory(R,E,VarSet)
+ vl : List VarSet
+ wl : List NonNegativeInteger
+ wtlevel : NonNegativeInteger
+
+ SIG ==> Ring with
+
+ if R has CommutativeRing then Algebra(R)
+
+ coerce : % -> P
+ ++ coerce converts back into a "P", ignoring weights
+
+ if R has Filed then
+
+ "/" : (%,%) -> Union(%,"failed")
+ ++ a / b division only works if minimum weight of divisor is zero,
+ ++ and if R is a Field
+
+ coerce : P -> %
+ ++ coerce a "P" into Weighted form, applying weights and ignoring terms
+
+ changeWeightLevel : NonNegativeInteger -> Void
+ ++ This changes the weight level to the new value given:
+ ++ NB: previously calculated terms are not affected
+
+ CODE ==> PolynomialRing(P,NonNegativeInteger) add
+
+ -- representations
+ Term := Record(k:NonNegativeInteger,c:P)
+ Rep := List Term
+ p : P
+ w,x1,x2 : %
+ n : NonNegativeInteger
+ z : Integer
+
+ changeWeightLevel(n) ==
+ wtlevel := n
+
+ lookupList : List Record(var: VarSet, weight:NonNegativeInteger)
+
+ if #vl ^= #wl then error "incompatible length lists in WeightedPolymonial"
+
+ lookupList := [[v,n] for v in vl for n in wl]
+
+ -- local operation
+
+ lookup : VarSet -> NonNegativeIntger
+ lookup v ==
+ l := lookupList
+ while l ^= [] repeat
+ v = l.first.var => return l.first.weight
+ l := l.rest
+ 0
+
+ innercoerce:(p,z) -> %
+ innercoerce(p,z) ==
+ z < 0 => 0
+ zero? p => 0
+ mv := mainVariable p
+ mv case "failed" => [[0,p]]
+ n := lookup(mv)
+ up := univariate(p,mv)
+ ans : %
+ ans := 0
+ while not zero? up repeat
+ d := degree up
+ f := n*d
+ lcup := leadingCoefficient up
+ up := up - leadingMonomial up
+ mon := monomial(1,mv,d)
+ f < z => ans:=ans+[[tm.k+f,mon*tm.c] for tm in innercoerce(lcup,z-f)]
+ ans
+
+ coerce(p):% ==
+ innercoerce(p,wtlevel)
+
+ coerce(w):P ==
+ "+"/[tm.c for tm in w]
+
+ x1 = x2 ==
+ -- Not that we must strip out any terms greater than wtlevel
+ while not null x1 and x1.first.k > wtlevel repeat
+ x1 := x1.rest
+ while not null x2 and x2.first.k > wtlevel repeat
+ x2 := x2.rest
+ while not null x1 and not null x2 repeat
+ x1.first.k ^= x2.first.k => return false
+ x1.first.c ^= x2.first.c => return false
+ x1 := x1.rest
+ x2 := x2.rest
+ null x1 and null x2
+
+ x1 * x2 ==
+ null x1 => 0
+ null x2 => 0
+ r : P
+ x1.first.k = 0 =>
+ [[t2.k,r]$Term for t2 in x2 | (r:=x1.first.c * t2.c) ^=0 ]
+ x2 = 1 => x1
+ +/[[[n,r]$Term for t2 in x2 | (n:=t1.k+t2.k) <= wtlevel and
+ (r:=t1.c*t2.c) ^= 0]
+ for t1 in reverse(x1)]
+ -- This 'reverse' is an efficiency improvement:
+ -- reduces both time and space [Abbott/Bradford/Davenport]
+
+ import RepeatedSquaring(%)
+
+ x:% ** n:NonNegativeInteger ==
+ zero? n => 1
+ expt(x,n pretend PositiveInteger)
+
+ coerce(p:%):OutputForm ==
+ zero? p => (0$Integer)::OutputForm
+ p.first.k = 0 => p.first.c::OutputForm
+ reduce("+",(reverse [paren(t1.c::OutputForm) for t1 in p])
+ ::List OutputForm)
+\end{chunk}
+
+\section{domain FCOMP FourierComponent}
+--Copyright The Numerical Algorithms Group Limited 1992
+\begin{chunk}{domain FCOMP FourierComponent}
+)abbrev domain FCOMP FourierComponent
+++ Author: James Davenport
+++ Date Created: 17 April 1992
+++ Date Last Updated: 13 July 2016 by Tim Daly
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ References:
+++ Description:
+FourierComponent(E) : SIG == CODE where
+ E : OrderedSet
+
+ SIG ==> OrderedSet with
+
+ sin : E -> %
+ ++ sin makes a sin kernel for use in Fourier series
+
+ cos : E -> %
+ ++ cos makes a cos kernel for use in Fourier series
+
+ sin? : % -> Boolean
+ ++ sin? true if term is a sin, otherwise false
+
+ argument : % -> E
+ ++ argument returns the argument of a given sin/cos expression
+
+ CODE ==> add
+
+ -- representations
+ Rep := Record(SinIfTrue:Boolean, arg:E)
+ e : E
+ x,y : %
+
+ sin e ==
+ [true,e]
+
+ cos e ==
+ [false,e]
+
+ sin? x ==
+ x.arg
+
+ argument x ==
+ x.arg
+
+ coerce(x):OutputForm ==
+ hconcat((if x.SinIfTrue then "sin" else "cos")::OutputForm,
+ bracket((x.arg)::OutputForm))
+
+ x < y ==
+ x.arg < y.arg => true
+ y.arg < x.arg => false
+ x.SinIfTrue => false
+ y.SinIfTrue
+\end{chunk}
+
+\section{domain FSERIES FourierSeries}
+\begin{chunk}{domain FSERIES FourierSeries}
+)abbrev domain FSERIES FourierSeries
+++ Author: James Davenport
+++ Date Created: 17 April 1992
+++ Date Last Updated: 13 July 2016 by Tim Daly
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ References:
+++ Description:
+FourierSeries(R,E) : SIG == CODE where
+ R : Join(CommutativeRing,Algebra(Fraction Integer))
+ E : Join(OrderedSet,AbelianGroup)
+
+ SIG ==> Algebra(R) with
+
+ if E has canonical and R has canonical the canonical
+
+ coerce : R -> %
+ ++ coerce converts coefficents into Fourier Series
+
+ coerce : FourierComponent(E) -> %
+ ++ coerc converts sin/cos terms into Fourier Series
+
+ makeSin : (E,R) -> %
+ ++ makeSin makes a sin expression with given argument and coefficient
+
+ makeCos : (E,R) -> %
+ ++ makeCos makes a cos expression with given argument and coefficient
+
+ CODE ==> FreeModule(R,FourierCompoent(E)) add
+
+ -- representations
+ Term := Record(k:FourierComponent(E),c:R)
+ Rep := List Term
+ w,x1,x2 : %
+ t1,t2 : Term
+ n : NonNegativeInteger
+ z : Integer
+ e : FourierComponent(E)
+ a : E
+ r : R
+
+ 1 ==
+ [[cos 0,1]]
+
+ coerce e ==
+ sin? e and zero? argument e => 0
+ if argument e < 0 then
+ not sin? e => e:=cos(- argument e)
+ return [[sin(- argument e),-1]]
+ [[e,1]]
+
+ multiply : (Term,Term) -> %
+ multiply(t1,t2) ==
+ r := (t1.c*t2.c)*(1/2)
+ s1 := argument t1.k
+ s2 := argument t2.k
+ sum := s1+s2
+ diff := s1-s2
+ sin? t1.k =>
+ sin? t2.k =>
+ makeCos(diff,r) + makeCos(sum,-r)
+ makeSin(sum,r) + makeSin(diff,r)
+ sin? t2.k =>
+ makeSin(sum,r) + makeSin(diff,r)
+ makeCos(diff,r) + makeCos(sum,r)
+
+ x1*x2 ==
+ null x1 => 0
+ null x2 => 0
+ +/[+/[multiply(t1,t2) for t2 in x2] for t1 in x1]
+
+ makeCos(a,r) ==
+ a < 0 => [[cos(-a),r]]
+ [[cos a,r]]
+
+ makeSing(a,r) ==
+ zero? a => []
+ a < 0 => [[sin(-a),-r]]
+ [[sin a,r]]
+\end{chunk}
+
+\chapter{The Makefile}
\begin{chunk}{*}
PROJECT=bookvol2
TANGLE=/usr/local/bin/NOTANGLE
diff --git a/changelog b/changelog
index 4301b22..3944157 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,5 @@
+20160714 tpd src/axiom-website/patches.html 20160714.06.tpd.patch
+20160714 tpd books/bookvol2 Add Davenport chapters
20160714 tpd src/axiom-website/patches.html 20160714.05.tpd.patch
20160714 tpd books/bookvol10.* add literature references to algebra
20160714 tpd src/axiom-website/patches.html 20160714.04.tpd.patch
diff --git a/patch b/patch
index 125090a..75cfd2e 100644
--- a/patch
+++ b/patch
@@ -1,4 +1,4 @@
-books/bookvol10.* add literature references to algebra
+books/bookvol2 Add Davenport chapters
Goal: Axiom Literate Programming
diff --git a/src/axiom-website/patches.html b/src/axiom-website/patches.html
index 856a3ff..2ccd632 100644
--- a/src/axiom-website/patches.html
+++ b/src/axiom-website/patches.html
@@ -5478,6 +5478,8 @@ books/bookheader.tex add books/appendix.sty for latex appendix**

books/bookvolbib Axiom Citations in the Literature

20160714.05.tpd.patch
books/bookvol10.* add literature references to algebra

+20160714.06.tpd.patch
+books/bookvol2 Add Davenport chapters

--
1.7.5.4