diff --git a/books/bookvol10.2.pamphlet b/books/bookvol10.2.pamphlet
index 9be4f7e..c479832 100644
--- a/books/bookvol10.2.pamphlet
+++ b/books/bookvol10.2.pamphlet
@@ -1525,6 +1525,7 @@ digraph pic {
 \pagepic{ps/v102radicalcategory.ps}{RADCAT}{1.00}
 
 {\bf See:}\\
+\pageto{AlgebraicallyClosedField}{ACF}
 \pageto{RealNumberSystem}{RNS}
 \pagefrom{Category}{CATEGORY}
 
@@ -7196,7 +7197,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{IndexedAggregate}{IXAGG}
-\pagepic{ps/v102indexedaggregate.ps}{IXAGG}{1.00}
+\pagepic{ps/v102indexedaggregate.ps}{IXAGG}{0.90}
 
 {\bf See:}\\
 \pageto{LinearAggregate}{LNAGG}
@@ -8137,7 +8138,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{TwoDimensionalArrayCategory}{ARR2CAT}
-\pagepic{ps/v102twodimensionalarraycategory.ps}{ARR2CAT}{0.60}
+\pagepic{ps/v102twodimensionalarraycategory.ps}{ARR2CAT}{0.65}
 
 TwoDimensionalArrayCategory is a general array category which
 allows different representations and indexing schemes.
@@ -9733,7 +9734,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{LinearAggregate}{LNAGG}
-\pagepic{ps/v102linearaggregate.ps}{LNAGG}{1.00}
+\pagepic{ps/v102linearaggregate.ps}{LNAGG}{0.90}
 
 {\bf See:}\\
 \pageto{ExtensibleLinearAggregate}{ELAGG}
@@ -10676,7 +10677,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{SetAggregate}{SETAGG}
-\pagepic{ps/v102setaggregate.ps}{SETAGG}{1.00}
+\pagepic{ps/v102setaggregate.ps}{SETAGG}{0.90}
 
 {\bf See:}\\
 \pageto{FiniteSetAggregate}{FSAGG}
@@ -12454,7 +12455,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{ExtensibleLinearAggregate}{ELAGG}
-\pagepic{ps/v102extensiblelinearaggregate.ps}{ELAGG}{1.00}
+\pagepic{ps/v102extensiblelinearaggregate.ps}{ELAGG}{0.90}
 
 {\bf See:}\\
 \pageto{ListAggregate}{LSAGG}
@@ -12749,7 +12750,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FiniteLinearAggregate}{FLAGG}
-\pagepic{ps/v102finitelinearaggregate.ps}{FLAGG}{1.00}
+\pagepic{ps/v102finitelinearaggregate.ps}{FLAGG}{0.90}
 
 {\bf See:}\\
 \pageto{OneDimensionalArrayAggregate}{A1AGG}
@@ -13095,7 +13096,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{MultiDictionary}{MDAGG}
-\pagepic{ps/v102multidictionary.ps}{MDAGG}{1.00}
+\pagepic{ps/v102multidictionary.ps}{MDAGG}{0.90}
 
 {\bf See:}\\
 \pageto{MultisetAggregate}{MSETAGG}
@@ -13410,7 +13411,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{StreamAggregate}{STAGG}
-\pagepic{ps/v102streamaggregate.ps}{STAGG}{0.50}
+\pagepic{ps/v102streamaggregate.ps}{STAGG}{0.60}
 
 {\bf See:}\\
 \pageto{LazyStreamAggregate}{LZSTAGG}
@@ -15315,7 +15316,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{ListAggregate}{LSAGG}
-\pagepic{ps/v102listaggregate.ps}{LSAGG}{0.50}
+\pagepic{ps/v102listaggregate.ps}{LSAGG}{0.60}
 
 {\bf See:}\\
 \pageto{AssociationListAggregate}{ALAGG}
@@ -15889,7 +15890,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{MultisetAggregate}{MSETAGG}
-\pagepic{ps/v102multisetaggregate.ps}{MSETAGG}{0.75}
+\pagepic{ps/v102multisetaggregate.ps}{MSETAGG}{0.80}
 
 {\bf See:}\\
 \pageto{OrderedMultisetAggregate}{OMSAGG}
@@ -16978,7 +16979,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{Rng}{RNG}
-\pagepic{ps/v102rng.ps}{RNG}{1.00}
+\pagepic{ps/v102rng.ps}{RNG}{0.90}
 
 Rng is a Ring that does not necessarily have a unit.
 
@@ -19261,7 +19262,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{OrderedAbelianMonoidSup}{OAMONS}
-\pagepic{ps/v102orderedabelianmonoidsup.ps}{OAMONS}{0.75}
+\pagepic{ps/v102orderedabelianmonoidsup.ps}{OAMONS}{0.80}
 
 {\bf See:}\\
 \pagefrom{OrderedCancellationAbelianMonoid}{OCAMON}
@@ -19834,7 +19835,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{StringCategory}{STRICAT}
-\pagepic{ps/v102stringcategory.ps}{STRICAT}{1.00}
+\pagepic{ps/v102stringcategory.ps}{STRICAT}{0.75}
 
 {\bf See:}\\
 \pagefrom{OpenMath}{OM}
@@ -21783,7 +21784,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{OrderedRing}{ORDRING}
-\pagepic{ps/v102orderedring.ps}{ORDRING}{0.65}
+\pagepic{ps/v102orderedring.ps}{ORDRING}{0.75}
 
 {\bf See:}\\
 \pageto{OrderedIntegralDomain}{OINTDOM}
@@ -22207,7 +22208,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{XAlgebra}{XALG}
-\pagepic{ps/v102xalgebra.ps}{XALG}{0.65}
+\pagepic{ps/v102xalgebra.ps}{XALG}{0.70}
 
 {\bf See:}\\
 \pageto{XFreeAlgebra}{XFALG}
@@ -22976,6 +22977,7 @@ digraph pic {
 \pagepic{ps/v102fullylinearlyexplicitringover.ps}{FLINEXP}{1.00}
 
 {\bf See:}\\
+\pageto{MonogenicAlgebra}{MONOGEN}
 \pageto{PolynomialCategory}{POLYCAT}
 \pagefrom{LinearlyExplicitRingOver}{LINEXP}
 
@@ -24716,7 +24718,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FiniteRankNonAssociativeAlgebra}{FINAALG}
-\pagepic{ps/v102finiteranknonassociativealgebra.ps}{FINAALG}{0.75}
+\pagepic{ps/v102finiteranknonassociativealgebra.ps}{FINAALG}{0.80}
 
 {\bf See:}\\
 \pageto{FramedNonAssociativeAlgebra}{FRNAALG}
@@ -24810,11 +24812,13 @@ These are directly exported but not implemented:
  conditionsForIdempotents : Vector % -> List Polynomial R
  coordinates : (%,Vector %) -> Vector R
  leftUnit : () -> Union(%,"failed") if R has INTDOM
- leftUnits : () -> Union(Record(particular: %,basis: List %),"failed") if R has INTDOM
+ leftUnits : () -> Union(Record(particular: %,basis: List %),"failed") 
+     if R has INTDOM
  powerAssociative? : () -> Boolean    
  rank : () -> PositiveInteger
  rightUnit : () -> Union(%,"failed") if R has INTDOM
- rightUnits : () -> Union(Record(particular: %,basis: List %),"failed") if R has INTDOM
+ rightUnits : () -> Union(Record(particular: %,basis: List %),"failed") 
+     if R has INTDOM
  someBasis : () -> Vector %
  unit : () -> Union(%,"failed") if R has INTDOM
 \end{verbatim}
@@ -26267,7 +26271,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FramedNonAssociativeAlgebra}{FRNAALG}
-\pagepic{ps/v102framednonassociativealgebra.ps}{FRNAALG}{0.65}
+\pagepic{ps/v102framednonassociativealgebra.ps}{FRNAALG}{0.75}
 
 {\bf See:}\\
 \pagefrom{FiniteRankNonAssociativeAlgebra}{FINAALG}
@@ -28001,7 +28005,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{PolynomialFactorizationExplicit}{PFECAT}
-\pagepic{ps/v102polynomialfactorizationexplicit.ps}{PFECAT}{0.75}
+\pagepic{ps/v102polynomialfactorizationexplicit.ps}{PFECAT}{0.80}
 
 {\bf See:}\\
 \pageto{PolynomialCategory}{POLYCAT}
@@ -28277,6 +28281,7 @@ digraph pic {
 \pagepic{ps/v102field.ps}{FIELD}{1.00}
 
 {\bf See:}\\
+\pageto{AlgebraicallyClosedField}{ACF}
 \pageto{ExtensionField}{XF}
 \pageto{FieldOfPrimeCharacteristic}{FPC}
 \pageto{FiniteRankAlgebra}{FINRALG}
@@ -28520,7 +28525,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{PolynomialCategory}{POLYCAT}
-\pagepic{ps/v102polynomialcategory.ps}{POLYCAT}{1.00}
+\pagepic{ps/v102polynomialcategory.ps}{POLYCAT}{0.30}
 
 {\bf See:}\\
 \pageto{UnivariatePolynomialCategory}{UPOLYC}
@@ -29480,6 +29485,376 @@ digraph pic {
 @
 \chapter{Category Layer 17}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{AlgebraicallyClosedField}{ACF}
+\pagepic{ps/v102algebraicallyclosedfield.ps}{ACF}{0.75}
+
+{\bf See:}\\
+\pagefrom{Field}{FIELD}
+\pagefrom{RadicalCategory}{RADCAT}
+
+{\bf Exports:}\\
+\begin{tabular}{llll}
+\cross{ACF}{0} &
+\cross{ACF}{1} &
+\cross{ACF}{associates?} &
+\cross{ACF}{characteristic} \\
+\cross{ACF}{coerce} &
+\cross{ACF}{divide} &
+\cross{ACF}{euclideanSize} &
+\cross{ACF}{expressIdealMember} \\
+\cross{ACF}{exquo} &
+\cross{ACF}{extendedEuclidean} &
+\cross{ACF}{factor} &
+\cross{ACF}{gcd} \\
+\cross{ACF}{gcdPolynomial} &
+\cross{ACF}{hash} &
+\cross{ACF}{inv} &
+\cross{ACF}{latex} \\
+\cross{ACF}{lcm} &
+\cross{ACF}{multiEuclidean} &
+\cross{ACF}{nthRoot} &
+\cross{ACF}{one?} \\
+\cross{ACF}{prime?} &
+\cross{ACF}{principalIdeal} &
+\cross{ACF}{recip} &
+\cross{ACF}{rootOf} \\
+\cross{ACF}{rootsOf} &
+\cross{ACF}{sample} &
+\cross{ACF}{sizeLess?} &
+\cross{ACF}{sqrt} \\
+\cross{ACF}{squareFree} &
+\cross{ACF}{squareFreePart} &
+\cross{ACF}{subtractIfCan} &
+\cross{ACF}{unit?} \\
+\cross{ACF}{unitCanonical} &
+\cross{ACF}{unitNormal} &
+\cross{ACF}{zero?} &
+\cross{ACF}{zeroOf} \\
+\cross{ACF}{zerosOf} &
+\cross{ACF}{?*?} &
+\cross{ACF}{?**?} &
+\cross{ACF}{?+?} \\
+\cross{ACF}{?-?} &
+\cross{ACF}{-?} &
+\cross{ACF}{?/?} &
+\cross{ACF}{?=?} \\
+\cross{ACF}{?quo?} &
+\cross{ACF}{?rem?} &
+\cross{ACF}{?\~{}=?} &
+\cross{ACF}{?*?} \\
+\cross{ACF}{?\^{}?} &&&
+\end{tabular}
+
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{ACF}{canonicalUnitNormal}}
+is true if we can choose a canonical representative for each class 
+of associate elements, that is {\tt associates?(a,b)} returns true 
+if and only if {\tt unitCanonical(a) = unitCanonical(b)}.
+\item {\bf \cross{ACF}{canonicalsClosed}}
+is true if\\
+{\tt unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
+\item {\bf \cross{ACF}{noZeroDivisors}}
+is true if $x * y \ne 0$ implies both x and y are non-zero.
+\item {\bf \cross{ACF}{commutative("*")}}
+is true if it has an operation $"*": (D,D) -> D$
+which is commutative.
+\item {\bf \cross{ACF}{unitsKnown}}
+is true if a monoid (a multiplicative semigroup with a 1) has 
+unitsKnown means that  the operation {\tt recip} can only return 
+``failed'' if its argument is not a unit.
+\item {\bf \cross{ACF}{leftUnitary}}
+is true if $1 * x = x$ for all x.
+\item {\bf \cross{ACF}{rightUnitary}}
+is true if $x * 1 = x$ for all x.
+\end{itemize}
+
+These are implemented by this category:
+\begin{verbatim}
+ rootOf : SparseUnivariatePolynomial % -> %
+ rootOf : (SparseUnivariatePolynomial %,Symbol) -> %
+ rootsOf : Polynomial % -> List %
+ rootsOf : (SparseUnivariatePolynomial %,Symbol) -> List %
+ rootsOf : SparseUnivariatePolynomial % -> List %
+ zeroOf : (SparseUnivariatePolynomial %,Symbol) -> %
+ zeroOf : Polynomial % -> %           
+ zeroOf : SparseUnivariatePolynomial % -> %
+ zerosOf : Polynomial % -> List %
+ zerosOf : (SparseUnivariatePolynomial %,Symbol) -> List %
+ zerosOf : SparseUnivariatePolynomial % -> List %
+\end{verbatim}
+
+These exports come from \refto{Field}():
+\begin{verbatim}
+ 0 : () -> %                          
+ 1 : () -> %
+ associates? : (%,%) -> Boolean
+ characteristic : () -> NonNegativeInteger
+ coerce : % -> %
+ coerce : Integer -> %                
+ coerce : % -> OutputForm
+ coerce : Fraction Integer -> %       
+ divide : (%,%) -> Record(quotient: %,remainder: %)
+ euclideanSize : % -> NonNegativeInteger
+ expressIdealMember : (List %,%) -> Union(List %,"failed")
+ exquo : (%,%) -> Union(%,"failed")
+ extendedEuclidean : (%,%,%) -> Union(Record(coef1: %,coef2: %),"failed")
+ extendedEuclidean : (%,%) -> Record(coef1: %,coef2: %,generator: %)
+ factor : % -> Factored %             
+ gcd : (%,%) -> %                     
+ gcd : List % -> %
+ gcdPolynomial :
+   (SparseUnivariatePolynomial %,
+    SparseUnivariatePolynomial %) ->
+       SparseUnivariatePolynomial %
+ hash : % -> SingleInteger
+ inv : % -> %                         
+ latex : % -> String
+ lcm : List % -> %                    
+ lcm : (%,%) -> %
+ multiEuclidean : (List %,%) -> Union(List %,"failed")
+ one? : % -> Boolean
+ prime? : % -> Boolean                
+ principalIdeal : List % -> Record(coef: List %,generator: %)
+ recip : % -> Union(%,"failed")       
+ sample : () -> %                     
+ sizeLess? : (%,%) -> Boolean
+ squareFree : % -> Factored %
+ squareFreePart : % -> %              
+ subtractIfCan : (%,%) -> Union(%,"failed")
+ unit? : % -> Boolean
+ unitCanonical : % -> %               
+ unitNormal : % -> Record(unit: %,canonical: %,associate: %)
+ zero? : % -> Boolean
+ ?*? : (Fraction Integer,%) -> %      
+ ?*? : (%,Fraction Integer) -> %
+ ?**? : (%,Integer) -> %              
+ ?^? : (%,Integer) -> %
+ ?+? : (%,%) -> %                     
+ ?=? : (%,%) -> Boolean               
+ ?~=? : (%,%) -> Boolean              
+ ?*? : (%,%) -> %                     
+ ?*? : (Integer,%) -> %
+ ?*? : (PositiveInteger,%) -> %       
+ ?*? : (NonNegativeInteger,%) -> %
+ ?-? : (%,%) -> %
+ -? : % -> %                          
+ ?**? : (%,PositiveInteger) -> %
+ ?**? : (%,NonNegativeInteger) -> %
+ ?^? : (%,PositiveInteger) -> %       
+ ?^? : (%,NonNegativeInteger) -> %
+ ?/? : (%,%) -> %
+ ?quo? : (%,%) -> %
+ ?rem? : (%,%) -> %
+\end{verbatim}
+
+These exports come from \refto{RadicalCategory}():
+\begin{verbatim}
+ nthRoot : (%,Integer) -> %           
+ sqrt : % -> %                        
+ ?**? : (%,Fraction Integer) -> %
+\end{verbatim}
+
+<<category ACF AlgebraicallyClosedField>>=
+)abbrev category ACF AlgebraicallyClosedField
+++ Author: Manuel Bronstein
+++ Date Created: 22 Mar 1988
+++ Date Last Updated: 27 November 1991
+++ Description:
+++   Model for algebraically closed fields.
+++ Keywords: algebraic, closure, field.
+
+AlgebraicallyClosedField(): Category == Join(Field,RadicalCategory) with
+    rootOf: Polynomial $ -> $
+      ++ rootOf(p) returns y such that \spad{p(y) = 0}.
+      ++ Error: if p has more than one variable y.
+    rootOf: SparseUnivariatePolynomial $ -> $
+      ++ rootOf(p) returns y such that \spad{p(y) = 0}.
+    rootOf: (SparseUnivariatePolynomial $, Symbol) -> $
+      ++ rootOf(p, y) returns y such that \spad{p(y) = 0}.
+      ++ The object returned displays as \spad{'y}.
+    rootsOf: Polynomial $ -> List $
+      ++ rootsOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
+      ++ Note: the returned symbols y1,...,yn are bound in the
+      ++ interpreter to respective root values.
+      ++ Error: if p has more than one variable y.
+    rootsOf: SparseUnivariatePolynomial $ -> List $
+      ++ rootsOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
+      ++ Note: the returned symbols y1,...,yn are bound in the interpreter
+      ++ to respective root values.
+    rootsOf: (SparseUnivariatePolynomial $, Symbol) -> List $
+      ++ rootsOf(p, y) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0};
+      ++ The returned roots display as \spad{'y1},...,\spad{'yn}.
+      ++ Note: the returned symbols y1,...,yn are bound in the interpreter
+      ++ to respective root values.
+    zeroOf: Polynomial $ -> $
+      ++ zeroOf(p) returns y such that \spad{p(y) = 0}.
+      ++ If possible, y is expressed in terms of radicals.
+      ++ Otherwise it is an implicit algebraic quantity.
+      ++ Error: if p has more than one variable y.
+    zeroOf: SparseUnivariatePolynomial $ -> $
+      ++ zeroOf(p) returns y such that \spad{p(y) = 0};
+      ++ if possible, y is expressed in terms of radicals.
+      ++ Otherwise it is an implicit algebraic quantity.
+    zeroOf: (SparseUnivariatePolynomial $, Symbol) -> $
+      ++ zeroOf(p, y) returns y such that \spad{p(y) = 0};
+      ++ if possible, y is expressed in terms of radicals.
+      ++ Otherwise it is an implicit algebraic quantity which
+      ++ displays as \spad{'y}.
+    zerosOf: Polynomial $ -> List $
+      ++ zerosOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
+      ++ The yi's are expressed in radicals if possible.
+      ++ Otherwise they are implicit algebraic quantities.
+      ++ The returned symbols y1,...,yn are bound in the interpreter
+      ++ to respective root values.
+      ++ Error: if p has more than one variable y.
+    zerosOf: SparseUnivariatePolynomial $ -> List $
+      ++ zerosOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
+      ++ The yi's are expressed in radicals if possible, and otherwise
+      ++ as implicit algebraic quantities.
+      ++ The returned symbols y1,...,yn are bound in the interpreter
+      ++ to respective root values.
+    zerosOf: (SparseUnivariatePolynomial $, Symbol) -> List $
+      ++ zerosOf(p, y) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
+      ++ The yi's are expressed in radicals if possible, and otherwise
+      ++ as implicit algebraic quantities
+      ++ which display as \spad{'yi}.
+      ++ The returned symbols y1,...,yn are bound in the interpreter
+      ++ to respective root values.
+ add
+    SUP ==> SparseUnivariatePolynomial $
+
+    assign  : (Symbol, $) -> $
+    allroots: (SUP, Symbol, (SUP, Symbol) -> $) -> List $
+    binomialRoots: (SUP, Symbol, (SUP, Symbol) -> $) -> List $
+
+    zeroOf(p:SUP)            == assign(x := new(), zeroOf(p, x))
+
+    rootOf(p:SUP)            == assign(x := new(), rootOf(p, x))
+
+    zerosOf(p:SUP)           == zerosOf(p, new())
+
+    rootsOf(p:SUP)           == rootsOf(p, new())
+
+    rootsOf(p:SUP, y:Symbol) == allroots(p, y, rootOf)
+
+    zerosOf(p:SUP, y:Symbol) == allroots(p, y, zeroOf)
+
+    assign(x, f)             == (assignSymbol(x, f, $)$Lisp; f)
+
+    zeroOf(p:Polynomial $) ==
+      empty?(l := variables p) => error "zeroOf: constant polynomial"
+      zeroOf(univariate p, first l)
+
+    rootOf(p:Polynomial $) ==
+      empty?(l := variables p) => error "rootOf: constant polynomial"
+      rootOf(univariate p, first l)
+
+    zerosOf(p:Polynomial $) ==
+      empty?(l := variables p) => error "zerosOf: constant polynomial"
+      zerosOf(univariate p, first l)
+
+    rootsOf(p:Polynomial $) ==
+      empty?(l := variables p) => error "rootsOf: constant polynomial"
+      rootsOf(univariate p, first l)
+
+    zeroOf(p:SUP, y:Symbol) ==
+      zero?(d := degree p) => error "zeroOf: constant polynomial"
+      zero? coefficient(p, 0) => 0
+      a := leadingCoefficient p
+      d = 2 =>
+        b := coefficient(p, 1)
+        (sqrt(b**2 - 4 * a * coefficient(p, 0)) - b) / (2 * a)
+      (r := retractIfCan(reductum p)@Union($,"failed")) case "failed" =>
+        rootOf(p, y)
+      nthRoot(- (r::$ / a), d)
+
+    binomialRoots(p, y, fn) ==
+     -- p = a * x**n + b
+      alpha := assign(x := new(y)$Symbol, fn(p, x))
+--      one?(n := degree p) =>  [ alpha ]
+      ((n := degree p) = 1) =>  [ alpha ]
+      cyclo := cyclotomic(n,monomial(1,1)$SUP)_
+                    $NumberTheoreticPolynomialFunctions(SUP)
+      beta := assign(x := new(y)$Symbol, fn(cyclo, x))
+      [alpha*beta**i for i in 0..(n-1)::NonNegativeInteger]
+
+    import PolynomialDecomposition(SUP,$)
+
+    allroots(p, y, fn) ==
+      zero? p => error "allroots: polynomial must be nonzero"
+      zero? coefficient(p,0) =>
+         concat(0, allroots(p quo monomial(1,1), y, fn))
+      zero?(p1:=reductum p) => empty()
+      zero? reductum p1 => binomialRoots(p, y, fn)
+      decompList := decompose(p)
+      # decompList > 1 =>
+          h := last decompList
+          g := leftFactor(p,h) :: SUP
+          groots := allroots(g, y, fn)
+          "append"/[allroots(h-r::SUP, y, fn) for r in groots]
+      ans := nil()$List($)
+      while not ground? p repeat
+        alpha := assign(x := new(y)$Symbol, fn(p, x))
+        q     := monomial(1, 1)$SUP - alpha::SUP
+        if not zero?(p alpha) then
+          p   := p quo q
+          ans := concat(alpha, ans)
+        else while zero?(p alpha) repeat
+          p   := (p exquo q)::SUP
+          ans := concat(alpha, ans)
+      reverse_! ans
+
+@
+<<ACF.dotabb>>=
+"ACF"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=ACF"];
+"ACF" -> "FIELD"
+"ACF" -> "RADCAT"
+
+@
+<<ACF.dotfull>>=
+"AlgebraicallyClosedField()"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=ACF"];
+"AlgebraicallyClosedField()" -> "Field()"
+"AlgebraicallyClosedField()" -> "RadicalCategory()"
+
+@
+<<ACF.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"AlgebraicallyClosedField()" [color=lightblue];
+"AlgebraicallyClosedField()" -> "Field()"
+"AlgebraicallyClosedField()" -> "RadicalCategory()"
+
+"Field()" [color=lightblue];
+"Field()" -> "EuclideanDomain()"
+"Field()" -> "UniqueFactorizationDomain()"
+"Field()" -> "DIVRING..."
+
+"EuclideanDomain()" [color=lightblue];
+"EuclideanDomain()" -> "PrincipalIdealDomain()"
+
+"UniqueFactorizationDomain()" [color=lightblue];
+"UniqueFactorizationDomain()" -> "GCDDOM..."
+
+"PrincipalIdealDomain()" [color=lightblue];
+"PrincipalIdealDomain()" -> "GCDDOM..."
+
+"DIVRING..." [color=lightblue];
+"GCDDOM..." [color=lightblue];
+
+"RadicalCategory()" [color=lightblue];
+"RadicalCategory()" -> "Category"
+
+"Category" [color=lightblue];
+}
+
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FieldOfPrimeCharacteristic}{FPC}
 \pagepic{ps/v102fieldofprimecharacteristic.ps}{FPC}{1.00}
 
@@ -29489,23 +29864,23 @@ digraph pic {
 \pagefrom{Field}{FIELD}
 
 {\bf Exports:}\\
-\begin{tabular}{lllll}
+\begin{tabular}{llll}
 \cross{FPC}{0} &
 \cross{FPC}{1} &
 \cross{FPC}{associates?} &
-\cross{FPC}{characteristic} &
-\cross{FPC}{charthRoot} \\
+\cross{FPC}{characteristic} \\
+\cross{FPC}{charthRoot} &
 \cross{FPC}{coerce} &
 \cross{FPC}{discreteLog} &
-\cross{FPC}{divide} &
+\cross{FPC}{divide} \\
 \cross{FPC}{euclideanSize} &
-\cross{FPC}{expressIdealMember} \\
+\cross{FPC}{expressIdealMember} &
 \cross{FPC}{exquo} &
-\cross{FPC}{extendedEuclidean} &
+\cross{FPC}{extendedEuclidean} \\
 \cross{FPC}{factor} &
 \cross{FPC}{gcd} &
-\cross{FPC}{gcdPolynomial} \\
-\cross{FPC}{hash} &
+\cross{FPC}{gcdPolynomial} &
+\cross{FPC}{hash} \\
 \cross{FPC}{inv} &
 \cross{FPC}{latex} &
 \cross{FPC}{lcm} &
@@ -29513,19 +29888,19 @@ digraph pic {
 \cross{FPC}{one?} &
 \cross{FPC}{order} &
 \cross{FPC}{prime?} &
-\cross{FPC}{primeFrobenius} &
-\cross{FPC}{principalIdeal} \\
+\cross{FPC}{primeFrobenius} \\
+\cross{FPC}{principalIdeal} &
 \cross{FPC}{recip} &
 \cross{FPC}{sample} &
-\cross{FPC}{sizeLess?} &
+\cross{FPC}{sizeLess?} \\
 \cross{FPC}{squareFree} &
-\cross{FPC}{squareFreePart} \\
+\cross{FPC}{squareFreePart} &
 \cross{FPC}{subtractIfCan} &
-\cross{FPC}{unit?} &
+\cross{FPC}{unit?} \\
 \cross{FPC}{unitCanonical} &
 \cross{FPC}{unitNormal} &
-\cross{FPC}{zero?} \\
-\cross{FPC}{?*?} &
+\cross{FPC}{zero?} &
+\cross{FPC}{?*?} \\
 \cross{FPC}{?**?} &
 \cross{FPC}{?+?} &
 \cross{FPC}{?-?} &
@@ -29533,9 +29908,9 @@ digraph pic {
 \cross{FPC}{?/?} &
 \cross{FPC}{?=?} &
 \cross{FPC}{?\^{}?} &
-\cross{FPC}{?rem?} &
-\cross{FPC}{?quo?} \\
-\cross{FPC}{?\~{}=?} &&&&
+\cross{FPC}{?rem?} \\
+\cross{FPC}{?quo?} &
+\cross{FPC}{?\~{}=?} &&
 \end{tabular}
 
 {\bf Attributes Exported:}
@@ -29723,7 +30098,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FiniteRankAlgebra}{FINRALG}
-\pagepic{ps/v102finiterankalgebra.ps}{FINRALG}{0.45}
+\pagepic{ps/v102finiterankalgebra.ps}{FINRALG}{0.50}
 
 {\bf See:}\\
 \pageto{FramedAlgebra}{FRAMALG}
@@ -29982,182 +30357,8 @@ digraph pic {
 
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\pagehead{MonogenicAlgebra}{MONOGEN}
-\pagepic{ps/v102monogenicalgebra.ps}{MONOGEN}{0.70}
-
-{\bf See:}\\
-
-{\bf Attributes Exported:}
-\begin{itemize}
-\item if \$ has Field then canonicalUnitNormal where
-{\bf \cross{MONOGEN}{canonicalUnitNormal}}
-is true if we can choose a canonical representative for each class 
-of associate elements, that is {\tt associates?(a,b)} returns true 
-if and only if {\tt unitCanonical(a) = unitCanonical(b)}.
-\item if \$ has Field then canonicalClosed where
-{\bf \cross{MONOGEN}{canonicalsClosed}}
-is true if\\
-{\tt unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
-\item if \$ has Field then noZeroDivisors where
-{\bf \cross{MONOGEN}{noZeroDivisors}}
-is true if $x * y \ne 0$ implies both x and y are non-zero.
-\item {\bf \cross{MONOGEN}{commutative("*")}}
-is true if it has an operation $"*": (D,D) -> D$
-which is commutative.
-\item {\bf \cross{MONOGEN}{unitsKnown}}
-is true if a monoid (a multiplicative semigroup with a 1) has 
-unitsKnown means that  the operation {\tt recip} can only return 
-``failed'' if its argument is not a unit.
-\item {\bf \cross{MONOGEN}{leftUnitary}}
-is true if $1 * x = x$ for all x.
-\item {\bf \cross{MONOGEN}{rightUnitary}}
-is true if $x * 1 = x$ for all x.
-\end{itemize}
-
-
-\pageto{FunctionFieldCategory}{FFCAT}
-\pagefrom{CommutativeRing}{COMRING}
-\pagefrom{ConvertibleTo}{KONVERT}
-\pagefrom{FramedAlgebra}{FRAMALG}
-\pagefrom{FullyRetractableTo}{FRETRCT}
-\pagefrom{LinearlyExplicitRingOver}{LINEXP}
-<<category MONOGEN MonogenicAlgebra>>=
-)abbrev category MONOGEN MonogenicAlgebra
-++ Author: Barry Trager
-++ Date Created:
-++ Date Last Updated:
-++ Basic Functions:
-++ Related Constructors:
-++ Also See:
-++ AMS Classifications:
-++ Keywords:
-++ References:
-++ Description:
-++ A \spadtype{MonogenicAlgebra} is an algebra of finite rank which
-++ can be generated by a single element.
-
-MonogenicAlgebra(R:CommutativeRing, UP:UnivariatePolynomialCategory R):
- Category ==
-    Join(FramedAlgebra(R, UP), CommutativeRing, ConvertibleTo UP,
-              FullyRetractableTo R, FullyLinearlyExplicitRingOver R) with
-      generator         : () -> %
-        ++ generator() returns the generator for this domain.
-      definingPolynomial: () -> UP
-        ++ definingPolynomial() returns the minimal polynomial which
-        ++ \spad{generator()} satisfies.
-      reduce            : UP -> %
-        ++ reduce(up) converts the univariate polynomial up to an algebra
-        ++ element, reducing by the \spad{definingPolynomial()} if necessary.
-      convert           : UP -> %
-        ++ convert(up) converts the univariate polynomial up to an algebra
-        ++ element, reducing by the \spad{definingPolynomial()} if necessary.
-      lift              : % -> UP
-        ++ lift(z) returns a minimal degree univariate polynomial up such that
-        ++ \spad{z=reduce up}.
-      if R has Finite then Finite
-      if R has Field then
-        Field
-        DifferentialExtension R
-        reduce               : Fraction UP -> Union(%, "failed")
-          ++ reduce(frac) converts the fraction frac to an algebra element.
-        derivationCoordinates: (Vector %, R -> R) -> Matrix R
-          ++ derivationCoordinates(b, ') returns M such that \spad{b' = M b}.
-      if R has FiniteFieldCategory then FiniteFieldCategory
-  add
-   convert(x:%):UP == lift x
-   convert(p:UP):% == reduce p
-   generator()     == reduce monomial(1, 1)$UP
-   norm x          == resultant(definingPolynomial(), lift x)
-   retract(x:%):R  == retract lift x
-   retractIfCan(x:%):Union(R, "failed") == retractIfCan lift x
-
-   basis() ==
-     [reduce monomial(1,i)$UP for i in 0..(rank()-1)::NonNegativeInteger]
-
-   characteristicPolynomial(x:%):UP ==
-     characteristicPolynomial(x)$CharacteristicPolynomialInMonogenicalAlgebra(R,UP,%)
-
-   if R has Finite then
-     size()   == size()$R ** rank()
-     random() == represents [random()$R for i in 1..rank()]$Vector(R)
-
-   if R has Field then
-     reduce(x:Fraction UP) == reduce(numer x) exquo reduce(denom x)
-
-     differentiate(x:%, d:R -> R) ==
-       p := definingPolynomial()
-       yprime := - reduce(map(d, p)) / reduce(differentiate p)
-       reduce(map(d, lift x)) + yprime * reduce differentiate lift x
-
-     derivationCoordinates(b, d) ==
-       coordinates(map(differentiate(#1, d), b), b)
-
-     recip x ==
-       (bc := extendedEuclidean(lift x, definingPolynomial(), 1))
-                                                case "failed" => "failed"
-       reduce(bc.coef1)
-
-@
-<<MONOGEN.dotabb>>=
-"MONOGEN"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=MONOGEN"];
-"MONOGEN" -> "FRAMALG"
-"MONOGEN" -> "COMRING"
-"MONOGEN" -> "KONVERT"
-"MONOGEN" -> "FRETRCT"
-"MONOGEN" -> "FLINEXP"
-
-@
-<<MONOGEN.dotfull>>=
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=MONOGEN"];
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "CommutativeRing()"
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "ConvertibleTo(UnivariatePolynomialCategory(CommutativeRing))"
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "FullyRetractableTo(a:CommutativeRing)"
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "FullyLinearlyExplicitRingOver(a:CommutativeRing)"
-
-"MonogenicAlgebra(a:FRAC(UPOLYC(UFD)),b:UPOLYC(FRAC(UPOLYC(UFD))))"
- [color=seagreen,href="bookvol10.2.pdf#nameddest=MONOGEN"];
-"MonogenicAlgebra(a:FRAC(UPOLYC(UFD)),b:UPOLYC(FRAC(UPOLYC(UFD))))" ->
-    "MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
-
-@
-<<MONOGEN.dotpic>>=
-digraph pic {
- fontsize=10;
- bgcolor="#FFFF66";
- node [shape=box, color=white, style=filled];
-
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
- [color=lightblue];
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "FRAMALG..."
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "COMRING..."
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "KONVERT..."
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "FRETRCT..."
-"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "FLINEXP..."
-
-"FRAMALG..." [color=lightblue];
-"COMRING..." [color=lightblue];
-"KONVERT..." [color=lightblue];
-"FRETRCT..." [color=lightblue];
-"FLINEXP..." [color=lightblue];
-}
-
-@
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{RealNumberSystem}{RNS}
-\pagepic{ps/v102realnumbersystem.ps}{RNS}{0.40}
+\pagepic{ps/v102realnumbersystem.ps}{RNS}{0.50}
 
 {\bf See:}\\
 \pageto{FloatingPointSystem}{FPS}
@@ -31814,7 +32015,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FiniteFieldCategory}{FFIELDC}
-\pagepic{ps/v102finitefieldcategory.ps}{FFIELDC}{0.60}
+\pagepic{ps/v102finitefieldcategory.ps}{FFIELDC}{0.70}
 
 {\bf See:}\\
 \pagefrom{DifferentialRing}{DIFRING}
@@ -31915,10 +32116,10 @@ These are directly exported but not implemented:
 \begin{verbatim}
  factorsOfCyclicGroupSize : () ->
     List Record(factor: Integer,exponent: Integer)
- tableForDiscreteLogarithm : Integer ->
-    Table(PositiveInteger,NonNegativeInteger)
  primitiveElement : () -> %           
  representationType : () -> Union("prime",polynomial,normal,cyclic)
+ tableForDiscreteLogarithm : Integer ->
+    Table(PositiveInteger,NonNegativeInteger)
 \end{verbatim}
 
 These are implemented by this category:
@@ -32314,7 +32515,7 @@ digraph pic {
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FloatingPointSystem}{FPS}
-\pagepic{ps/v102floatingpointsystem.ps}{FPS}{0.40}
+\pagepic{ps/v102floatingpointsystem.ps}{FPS}{0.50}
 
 {\bf See:}\\
 \pagefrom{RealNumberSystem}{RNS}
@@ -32693,6 +32894,1422 @@ digraph pic {
 
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{FramedAlgebra}{FRAMALG}
+\pagepic{ps/v102framedalgebra.ps}{FRAMALG}{0.50}
+
+{\bf See:}\\
+\pageto{MonogenicAlgebra}{MONOGEN}
+\pagefrom{FiniteRankAlgebra}{FINRALG}
+
+{\bf Exports:}\\
+\begin{tabular}{lllll}
+\cross{FRAMALG}{0} &
+\cross{FRAMALG}{1} &
+\cross{FRAMALG}{basis} \\
+\cross{FRAMALG}{characteristic} &
+\cross{FRAMALG}{characteristicPolynomial} &
+\cross{FRAMALG}{charthRoot} \\
+\cross{FRAMALG}{coerce} &
+\cross{FRAMALG}{convert} &
+\cross{FRAMALG}{coordinates} \\
+\cross{FRAMALG}{discriminant} &
+\cross{FRAMALG}{hash} &
+\cross{FRAMALG}{latex} \\
+\cross{FRAMALG}{minimalPolynomial} &
+\cross{FRAMALG}{norm} &
+\cross{FRAMALG}{one?} \\
+\cross{FRAMALG}{rank} &
+\cross{FRAMALG}{recip} &
+\cross{FRAMALG}{regularRepresentation} \\
+\cross{FRAMALG}{represents} &
+\cross{FRAMALG}{sample} &
+\cross{FRAMALG}{subtractIfCan} \\
+\cross{FRAMALG}{trace} &
+\cross{FRAMALG}{traceMatrix} &
+\cross{FRAMALG}{zero?} \\
+\cross{FRAMALG}{?*?} &
+\cross{FRAMALG}{?**?} &
+\cross{FRAMALG}{?+?} \\
+\cross{FRAMALG}{?-?} &
+\cross{FRAMALG}{-?} &
+\cross{FRAMALG}{?=?} \\
+\cross{FRAMALG}{?\^{}?} &
+\cross{FRAMALG}{?\~{}=?} &
+\end{tabular}
+
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{FRAMALG}{unitsKnown}}
+is true if a monoid (a multiplicative semigroup with a 1) has 
+unitsKnown means that  the operation {\tt recip} can only return 
+``failed'' if its argument is not a unit.
+\item {\bf \cross{FRAMALG}{leftUnitary}}
+is true if $1 * x = x$ for all x.
+\item {\bf \cross{FRAMALG}{rightUnitary}}
+is true if $x * 1 = x$ for all x.
+\end{itemize}
+
+These are directly exported but not implemented:
+\begin{verbatim}
+ basis : () -> Vector %
+ represents : Vector R -> %           
+\end{verbatim}
+
+These are implemented by this category:
+\begin{verbatim}
+ convert : Vector R -> %
+ convert : % -> Vector R              
+ coordinates : Vector % -> Matrix R
+ coordinates : % -> Vector R
+ discriminant : () -> R               
+ regularRepresentation : % -> Matrix R
+ traceMatrix : () -> Matrix R
+\end{verbatim}
+
+These exports come from \refto{FiniteRankAlgebra}(R, UP)\\
+where R:CommutativeRing and UP:UnivariatePolynomialCategory R):
+\begin{verbatim}
+ 0 : () -> %
+ 1 : () -> %                          
+ characteristic : () -> NonNegativeInteger
+ characteristicPolynomial : % -> UP
+ charthRoot : % -> Union(%,"failed") if R has CHARNZ
+ coerce : R -> %                      
+ coerce : Integer -> %
+ coerce : % -> OutputForm             
+ coordinates : (%,Vector %) -> Vector R
+ coordinates : (Vector %,Vector %) -> Matrix R
+ discriminant : Vector % -> R
+ hash : % -> SingleInteger            
+ latex : % -> String
+ minimalPolynomial : % -> UP if R has FIELD
+ norm : % -> R                        
+ one? : % -> Boolean
+ rank : () -> PositiveInteger         
+ recip : % -> Union(%,"failed")
+ regularRepresentation : (%,Vector %) -> Matrix R
+ represents : (Vector R,Vector %) -> %
+ sample : () -> %
+ subtractIfCan : (%,%) -> Union(%,"failed")
+ trace : % -> R                       
+ traceMatrix : Vector % -> Matrix R
+ zero? : % -> Boolean                 
+ ?+? : (%,%) -> %                     
+ ?=? : (%,%) -> Boolean
+ ?~=? : (%,%) -> Boolean
+ ?*? : (%,%) -> %                     
+ ?*? : (Integer,%) -> %
+ ?*? : (PositiveInteger,%) -> %       
+ ?*? : (NonNegativeInteger,%) -> %
+ ?*? : (R,%) -> %                     
+ ?*? : (%,R) -> %
+ ?-? : (%,%) -> %
+ -? : % -> %                          
+ ?**? : (%,PositiveInteger) -> %
+ ?**? : (%,NonNegativeInteger) -> %
+ ?^? : (%,PositiveInteger) -> %       
+ ?^? : (%,NonNegativeInteger) -> %
+\end{verbatim}
+
+<<category FRAMALG FramedAlgebra>>=
+)abbrev category FRAMALG FramedAlgebra
+++ Author: Barry Trager
+++ Date Created:
+++ Date Last Updated:
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ References:
+++ Description:
+++ A \spadtype{FramedAlgebra} is a \spadtype{FiniteRankAlgebra} together
+++ with a fixed R-module basis.
+
+FramedAlgebra(R:CommutativeRing, UP:UnivariatePolynomialCategory R):
+ Category == FiniteRankAlgebra(R, UP) with
+      basis                 : () -> Vector %
+        ++ basis() returns the fixed R-module basis.
+      coordinates           : % -> Vector R
+        ++ coordinates(a) returns the coordinates of \spad{a} with 
+        ++ respect to the fixed R-module basis.
+      coordinates           : Vector % -> Matrix R
+        ++ coordinates([v1,...,vm]) returns the coordinates of the
+        ++ vi's with to the fixed basis.  The coordinates of vi are
+        ++ contained in the ith row of the matrix returned by this
+        ++ function.
+      represents            : Vector R -> %
+        ++ represents([a1,..,an]) returns \spad{a1*v1 + ... + an*vn}, where
+        ++ v1, ..., vn are the elements of the fixed basis.
+      convert               : % -> Vector R
+        ++ convert(a) returns the coordinates of \spad{a} with respect to the
+        ++ fixed R-module basis.
+      convert               : Vector R -> %
+        ++ convert([a1,..,an]) returns \spad{a1*v1 + ... + an*vn}, where
+        ++ v1, ..., vn are the elements of the fixed basis.
+      traceMatrix           : () -> Matrix R
+        ++ traceMatrix() is the n-by-n matrix ( \spad{Tr(vi * vj)} ), where
+        ++ v1, ..., vn are the elements of the fixed basis.
+      discriminant          : () -> R
+        ++ discriminant() = determinant(traceMatrix()).
+      regularRepresentation : % -> Matrix R
+        ++ regularRepresentation(a) returns the matrix of the linear
+        ++ map defined by left multiplication by \spad{a} with respect
+        ++ to the fixed basis.
+    --attributes
+      --separable <=> discriminant() ^= 0
+  add
+   convert(x:%):Vector(R)  == coordinates(x)
+   convert(v:Vector R):%   == represents(v)
+   traceMatrix()           == traceMatrix basis()
+   discriminant()          == discriminant basis()
+   regularRepresentation x == regularRepresentation(x, basis())
+   coordinates x           == coordinates(x, basis())
+   represents x            == represents(x, basis())
+
+   coordinates(v:Vector %) ==
+     m := new(#v, rank(), 0)$Matrix(R)
+     for i in minIndex v .. maxIndex v for j in minRowIndex m .. repeat
+       setRow_!(m, j, coordinates qelt(v, i))
+     m
+
+   regularRepresentation x ==
+     m := new(n := rank(), n, 0)$Matrix(R)
+     b := basis()
+     for i in minIndex b .. maxIndex b for j in minRowIndex m .. repeat
+       setRow_!(m, j, coordinates(x * qelt(b, i)))
+     m
+
+   characteristicPolynomial x ==
+      mat00 := (regularRepresentation x)
+      mat0 := map(#1 :: UP,mat00)$MatrixCategoryFunctions2(R, Vector R,
+                  Vector R, Matrix R, UP, Vector UP,Vector UP, Matrix UP)
+      mat1 : Matrix UP := scalarMatrix(rank(),monomial(1,1)$UP)
+      determinant(mat1 - mat0)
+
+   if R has Field then
+    -- depends on the ordering of results from nullSpace, also see FFP
+      minimalPolynomial(x:%):UP ==
+        y:%:=1
+        n:=rank()
+        m:Matrix R:=zero(n,n+1)
+        for i in 1..n+1 repeat
+          setColumn_!(m,i,coordinates(y))
+          y:=y*x
+        v:=first nullSpace(m)
+        +/[monomial(v.(i+1),i) for i in 0..#v-1]
+
+@
+<<FRAMALG.dotabb>>=
+"FRAMALG"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FRAMALG"];
+"FRAMALG" -> "FINRALG"
+
+@
+<<FRAMALG.dotfull>>=
+"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FRAMALG"];
+"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+   "FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+
+@
+<<FRAMALG.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+ [color=lightblue];
+"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+   "FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+
+"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+ [color=lightblue];
+"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "Algebra(a:CommutativeRing)"
+"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "Field()"
+"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "CharacteristicNonZero()"
+"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "CharacteristicZero()"
+
+"Algebra(a:CommutativeRing)" [color=lightblue];
+"Algebra(a:CommutativeRing)" -> "RING..."
+"Algebra(a:CommutativeRing)" -> "MODULE..."
+
+"Field()" [color=lightblue];
+"Field()" -> "EUCDOM..."
+"Field()" -> "UFD..."
+"Field()" -> "DIVRING..."
+
+"CharacteristicNonZero()" [color=lightblue];
+"CharacteristicNonZero()" -> "RING..."
+
+"CharacteristicZero()" [color=lightblue];
+"CharacteristicZero()" -> "RING..."
+
+"EUCDOM..." [color=lightblue];
+"UFD..." [color=lightblue];
+"DIVRING..." [color=lightblue];
+"RING..." [color=lightblue];
+"MODULE..." [color=lightblue];
+}
+
+@
+\chapter{Category Layer 19}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{FiniteAlgebraicExtensionField}{FAXF}
+\pagepic{ps/v102finitealgebraicextensionfield.ps}{FAXF}{0.75}
+
+{\bf See:}\\
+\pagefrom{ExtensionField}{XF}
+\pagefrom{RetractableTo}{RETRACT}
+
+{\bf Exports:}\\
+\begin{tabular}{lllll}
+\cross{FAXF}{0} &
+\cross{FAXF}{1} &
+\cross{FAXF}{algebraic?} \\
+\cross{FAXF}{associates?} &
+\cross{FAXF}{basis} &
+\cross{FAXF}{characteristic} \\
+\cross{FAXF}{charthRoot} &
+\cross{FAXF}{coerce} &
+\cross{FAXF}{conditionP} \\
+\cross{FAXF}{coordinates} &
+\cross{FAXF}{createNormalElement} &
+\cross{FAXF}{createPrimitiveElement} \\
+\cross{FAXF}{D} &
+\cross{FAXF}{definingPolynomial} &
+\cross{FAXF}{degree} \\
+\cross{FAXF}{differentiate} &
+\cross{FAXF}{dimension} &
+\cross{FAXF}{discreteLog} \\
+\cross{FAXF}{divide} &
+\cross{FAXF}{euclideanSize} &
+\cross{FAXF}{expressIdealMember} \\
+\cross{FAXF}{exquo} &
+\cross{FAXF}{extendedEuclidean} &
+\cross{FAXF}{extensionDegree} \\
+\cross{FAXF}{factor} &
+\cross{FAXF}{factorsOfCyclicGroupSize} &
+\cross{FAXF}{Frobenius} \\
+\cross{FAXF}{gcd} &
+\cross{FAXF}{gcdPolynomial} &
+\cross{FAXF}{generator} \\
+\cross{FAXF}{hash} &
+\cross{FAXF}{index} &
+\cross{FAXF}{inGroundField?} \\
+\cross{FAXF}{init} &
+\cross{FAXF}{inv} &
+\cross{FAXF}{latex} \\
+\cross{FAXF}{lcm} &
+\cross{FAXF}{linearAssociatedExp} &
+\cross{FAXF}{linearAssociatedLog} \\
+\cross{FAXF}{linearAssociatedOrder} &
+\cross{FAXF}{lookup} &
+\cross{FAXF}{minimalPolynomial} \\
+\cross{FAXF}{multiEuclidean} &
+\cross{FAXF}{nextItem} &
+\cross{FAXF}{norm} \\
+\cross{FAXF}{normal?} &
+\cross{FAXF}{normalElement} &
+\cross{FAXF}{one?} \\
+\cross{FAXF}{order} &
+\cross{FAXF}{prime?} &
+\cross{FAXF}{primeFrobenius} \\
+\cross{FAXF}{primitive?} &
+\cross{FAXF}{primitiveElement} &
+\cross{FAXF}{principalIdeal} \\
+\cross{FAXF}{random} &
+\cross{FAXF}{recip} &
+\cross{FAXF}{representationType} \\
+\cross{FAXF}{represents} &
+\cross{FAXF}{retract} &
+\cross{FAXF}{retractIfCan} \\
+\cross{FAXF}{sample} &
+\cross{FAXF}{size} &
+\cross{FAXF}{sizeLess?} \\
+\cross{FAXF}{squareFree} &
+\cross{FAXF}{squareFreePart} &
+\cross{FAXF}{subtractIfCan} \\
+\cross{FAXF}{tableForDiscreteLogarithm} &
+\cross{FAXF}{trace} &
+\cross{FAXF}{transcendenceDegree} \\
+\cross{FAXF}{transcendent?} &
+\cross{FAXF}{unit?} &
+\cross{FAXF}{unitCanonical} \\
+\cross{FAXF}{unitNormal} &
+\cross{FAXF}{zero?} &
+\cross{FAXF}{?*?} \\
+\cross{FAXF}{?**?} &
+\cross{FAXF}{?+?} &
+\cross{FAXF}{?-?} \\
+\cross{FAXF}{-?} &
+\cross{FAXF}{?/?} &
+\cross{FAXF}{?/?} \\
+\cross{FAXF}{?=?} &
+\cross{FAXF}{?\^{}?} &
+\cross{FAXF}{?quo?} \\
+\cross{FAXF}{?rem?} &
+\cross{FAXF}{?\~{}=?} &
+\end{tabular}
+
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{FAXF}{canonicalUnitNormal}}
+is true if we can choose a canonical representative for each class 
+of associate elements, that is {\tt associates?(a,b)} returns true 
+if and only if {\tt unitCanonical(a) = unitCanonical(b)}.
+\item {\bf \cross{FAXF}{canonicalsClosed}}
+is true if\\
+{\tt unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
+\item {\bf \cross{FAXF}{noZeroDivisors}}
+is true if $x * y \ne 0$ implies both x and y are non-zero.
+\item {\bf \cross{FAXF}{commutative("*")}}
+is true if it has an operation $"*": (D,D) -> D$
+which is commutative.
+\item {\bf \cross{FAXF}{unitsKnown}}
+is true if a monoid (a multiplicative semigroup with a 1) has 
+unitsKnown means that  the operation {\tt recip} can only return 
+``failed'' if its argument is not a unit.
+\item {\bf \cross{FAXF}{leftUnitary}}
+is true if $1 * x = x$ for all x.
+\item {\bf \cross{FAXF}{rightUnitary}}
+is true if $x * 1 = x$ for all x.
+\end{itemize}
+
+These are directly exported but not implemented:
+\begin{verbatim}
+ basis : () -> Vector %               
+ basis : PositiveInteger -> Vector %
+ coordinates : % -> Vector F          
+ definingPolynomial : () -> SparseUnivariatePolynomial F
+ generator : () -> % if F has FINITE
+ minimalPolynomial : (%,PositiveInteger) ->
+    SparseUnivariatePolynomial % 
+      if F has FINITE
+ normalElement : () -> % if F has FINITE
+\end{verbatim}
+
+These are implemented by this category:
+\begin{verbatim}
+ algebraic? : % -> Boolean            
+ charthRoot : % -> Union(%,"failed") 
+     if F has CHARNZ or F has FINITE
+ coordinates : Vector % -> Matrix F
+ createNormalElement : () -> % if F has FINITE
+ degree : % -> PositiveInteger
+ dimension : () -> CardinalNumber     
+ extensionDegree : () -> PositiveInteger
+ linearAssociatedExp : (%,SparseUnivariatePolynomial F) -> % 
+     if F has FINITE
+ linearAssociatedLog : (%,%) ->
+    Union(SparseUnivariatePolynomial F,"failed") 
+      if F has FINITE
+ linearAssociatedLog : % -> SparseUnivariatePolynomial F 
+     if F has FINITE
+ linearAssociatedOrder : % -> SparseUnivariatePolynomial F 
+     if F has FINITE
+ minimalPolynomial : % -> SparseUnivariatePolynomial F
+ norm : % -> F                        
+ norm : (%,PositiveInteger) -> % if F has FINITE
+ normal? : % -> Boolean if F has FINITE
+ represents : Vector F -> %           
+ size : () -> NonNegativeInteger if F has FINITE
+ trace : % -> F                       
+ trace : (%,PositiveInteger) -> % if F has FINITE
+ transcendenceDegree : () -> NonNegativeInteger
+ transcendent? : % -> Boolean
+\end{verbatim}
+
+These exports come from \refto{ExtensionField}(F:Field):
+\begin{verbatim}
+ 0 : () -> %
+ 1 : () -> %                          
+ associates? : (%,%) -> Boolean
+ characteristic : () -> NonNegativeInteger
+ coerce : F -> %
+ coerce : % -> %
+ coerce : Integer -> %                
+ coerce : % -> OutputForm
+ coerce : Fraction Integer -> %       
+ discreteLog : (%,%) ->
+    Union(NonNegativeInteger,"failed")
+      if F has CHARNZ or F has FINITE
+ divide : (%,%) -> Record(quotient: %,remainder: %)
+ euclideanSize : % -> NonNegativeInteger
+ expressIdealMember : (List %,%) -> Union(List %,"failed")
+ exquo : (%,%) -> Union(%,"failed")
+ extendedEuclidean : (%,%,%) ->
+    Union(Record(coef1: %,coef2: %),"failed")
+ extendedEuclidean : (%,%) ->
+    Record(coef1: %,coef2: %,generator: %)
+ factor : % -> Factored %
+ Frobenius : (%,NonNegativeInteger) -> % if F has FINITE
+ Frobenius : % -> % if F has FINITE
+ gcd : List % -> %                    
+ gcd : (%,%) -> %
+ gcdPolynomial : (SparseUnivariatePolynomial %,
+                  SparseUnivariatePolynomial %) ->
+                     SparseUnivariatePolynomial %
+ hash : % -> SingleInteger            
+ inGroundField? : % -> Boolean
+ inv : % -> %                         
+ latex : % -> String
+ lcm : List % -> %                    
+ lcm : (%,%) -> %
+ multiEuclidean : (List %,%) -> Union(List %,"failed")
+ one? : % -> Boolean
+ order : % -> OnePointCompletion PositiveInteger
+      if F has CHARNZ or F has FINITE
+ prime? : % -> Boolean                
+ primeFrobenius : % -> % 
+     if F has CHARNZ or F has FINITE
+ primeFrobenius : (%,NonNegativeInteger) -> % 
+     if F has CHARNZ or F has FINITE
+ principalIdeal : List % -> Record(coef: List %,generator: %)
+ recip : % -> Union(%,"failed")       
+ retract : % -> F
+ retractIfCan : % -> Union(F,"failed")
+ sample : () -> %                     
+ squareFree : % -> Factored %         
+ squareFreePart : % -> %
+ sizeLess? : (%,%) -> Boolean
+ subtractIfCan : (%,%) -> Union(%,"failed")
+ unit? : % -> Boolean                 
+ unitCanonical : % -> %
+ unitNormal : % -> Record(unit: %,canonical: %,associate: %)
+ zero? : % -> Boolean                 
+ ?/? : (%,%) -> %
+ ?+? : (%,%) -> %
+ ?=? : (%,%) -> Boolean               
+ ?~=? : (%,%) -> Boolean
+ ?*? : (%,%) -> %                     
+ ?*? : (Integer,%) -> %
+ ?*? : (PositiveInteger,%) -> %       
+ ?*? : (NonNegativeInteger,%) -> %
+ ?*? : (Fraction Integer,%) -> %      
+ ?*? : (%,Fraction Integer) -> %
+ ?*? : (F,%) -> %                     
+ ?*? : (%,F) -> %
+ ?-? : (%,%) -> %                     
+ -? : % -> %
+ ?**? : (%,NonNegativeInteger) -> %
+ ?**? : (%,PositiveInteger) -> %      
+ ?**? : (%,Integer) -> %
+ ?^? : (%,Integer) -> %               
+ ?^? : (%,PositiveInteger) -> %
+ ?^? : (%,NonNegativeInteger) -> %
+ ?quo? : (%,%) -> %
+ ?rem? : (%,%) -> %
+ ?/? : (%,F) -> %                     
+\end{verbatim}
+
+These exports come from \refto{RetractableTo}(F:Field):
+\begin{verbatim}
+\end{verbatim}
+
+These exports come from \refto{FiniteFieldCategory}():
+\begin{verbatim}
+ charthRoot : % -> % if F has FINITE
+ conditionP : Matrix % -> Union(Vector %,"failed") 
+     if F has FINITE
+ createPrimitiveElement : () -> % if F has FINITE
+ D : % -> % if F has FINITE
+ D : (%,NonNegativeInteger) -> % if F has FINITE
+ differentiate : % -> % if F has FINITE
+ differentiate : (%,NonNegativeInteger) -> % 
+     if F has FINITE
+ discreteLog : % -> NonNegativeInteger if F has FINITE
+ factorsOfCyclicGroupSize : () ->
+    List Record(factor: Integer,exponent: Integer) 
+      if F has FINITE
+ index : PositiveInteger -> % if F has FINITE
+ init : () -> % if F has FINITE
+ lookup : % -> PositiveInteger if F has FINITE
+ nextItem : % -> Union(%,"failed") if F has FINITE
+ order : % -> PositiveInteger if F has FINITE
+ primitive? : % -> Boolean if F has FINITE
+ primitiveElement : () -> % if F has FINITE
+ random : () -> % if F has FINITE
+ representationType : () ->
+    Union("prime",polynomial,normal,cyclic) 
+      if F has FINITE
+ tableForDiscreteLogarithm : Integer ->
+    Table(PositiveInteger,NonNegativeInteger) 
+      if F has FINITE
+\end{verbatim}
+
+
+<<category FAXF FiniteAlgebraicExtensionField>>=
+)abbrev category FAXF FiniteAlgebraicExtensionField
+++ Author: J. Grabmeier, A. Scheerhorn
+++ Date Created: 11 March 1991
+++ Date Last Updated: 31 March 1991
+++ Basic Operations: _+, _*, extensionDegree,
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords: field, extension field, algebraic extension, finite extension
+++ References:
+++  R.Lidl, H.Niederreiter: Finite Field, Encycoldia of Mathematics and
+++  Its Applications, Vol. 20, Cambridge Univ. Press, 1983, 
+++  ISBN 0 521 30240 4 J. Grabmeier, A. Scheerhorn: Finite Fields in AXIOM.
+++  AXIOM Technical Report Series, ATR/5 NP2522.
+++ Description:
+++  FiniteAlgebraicExtensionField {\em F} is the category of fields
+++  which are finite algebraic extensions of the field {\em F}.
+++  If {\em F} is finite then any finite algebraic extension of {\em F} 
+++  is finite, too. Let {\em K} be a finite algebraic extension of the 
+++  finite field {\em F}. The exponentiation of elements of {\em K} 
+++  defines a Z-module structure on the multiplicative group of {\em K}. 
+++  The additive group of {\em K} becomes a module over the ring of 
+++  polynomials over {\em F} via the operation 
+++  \spadfun{linearAssociatedExp}(a:K,f:SparseUnivariatePolynomial F)
+++  which is linear over {\em F}, i.e. for elements {\em a} from {\em K},
+++  {\em c,d} from {\em F} and {\em f,g} univariate polynomials over {\em F}
+++  we have \spadfun{linearAssociatedExp}(a,cf+dg) equals {\em c} times
+++  \spadfun{linearAssociatedExp}(a,f) plus {\em d} times
+++  \spadfun{linearAssociatedExp}(a,g).
+++  Therefore \spadfun{linearAssociatedExp} is defined completely by
+++  its action on  monomials from {\em F[X]}:
+++  \spadfun{linearAssociatedExp}(a,monomial(1,k)\$SUP(F)) is defined to be
+++  \spadfun{Frobenius}(a,k) which is {\em a**(q**k)} where {\em q=size()\$F}.
+++  The operations order and discreteLog associated with the multiplicative
+++  exponentiation have additive analogues associated to the operation
+++  \spadfun{linearAssociatedExp}. These are the functions
+++  \spadfun{linearAssociatedOrder} and \spadfun{linearAssociatedLog},
+++  respectively.
+
+FiniteAlgebraicExtensionField(F : Field) : Category == _
+  Join(ExtensionField F, RetractableTo F) with
+  -- should be unified with algebras
+  -- Join(ExtensionField F, FramedAlgebra F, RetractableTo F) with
+    basis : () -> Vector $
+      ++ basis() returns a fixed basis of \$ as \spad{F}-vectorspace.
+    basis : PositiveInteger -> Vector $
+      ++ basis(n) returns a fixed basis of a subfield of \$ as
+      ++ \spad{F}-vectorspace.
+    coordinates : $ -> Vector F
+      ++ coordinates(a) returns the coordinates of \spad{a} with respect
+      ++ to the fixed \spad{F}-vectorspace basis.
+    coordinates : Vector $ -> Matrix F
+      ++ coordinates([v1,...,vm]) returns the coordinates of the
+      ++ vi's with to the fixed basis.  The coordinates of vi are
+      ++ contained in the ith row of the matrix returned by this
+      ++ function.
+    represents:  Vector F -> $
+      ++ represents([a1,..,an]) returns \spad{a1*v1 + ... + an*vn}, where
+      ++ v1,...,vn are the elements of the fixed basis.
+    minimalPolynomial: $ -> SparseUnivariatePolynomial F
+      ++ minimalPolynomial(a) returns the minimal polynomial of an
+      ++ element \spad{a} over the ground field F.
+    definingPolynomial: () -> SparseUnivariatePolynomial F
+      ++ definingPolynomial() returns the polynomial used to define
+      ++ the field extension.
+    extensionDegree : () ->  PositiveInteger
+      ++ extensionDegree() returns the degree of field extension.
+    degree : $ -> PositiveInteger
+      ++ degree(a) returns the degree of the minimal polynomial of an
+      ++ element \spad{a} over the ground field F.
+    norm: $  -> F
+      ++ norm(a) computes the norm of \spad{a} with respect to the
+      ++ field considered as an algebra with 1 over the ground field F.
+    trace: $ -> F
+      ++ trace(a) computes the trace of \spad{a} with respect to
+      ++ the field considered as an algebra with 1 over the ground field F.
+    if F has Finite then
+      FiniteFieldCategory
+      minimalPolynomial: ($,PositiveInteger) -> SparseUnivariatePolynomial $
+        ++ minimalPolynomial(x,n) computes the minimal polynomial of x over
+        ++ the field of extension degree n over the ground field F.
+      norm: ($,PositiveInteger)  -> $
+        ++ norm(a,d) computes the norm of \spad{a} with respect to the field
+        ++ of extension degree d over the ground field of size.
+        ++ Error: if d does not divide the extension degree of \spad{a}.
+        ++ Note: norm(a,d) = reduce(*,[a**(q**(d*i)) for i in 0..n/d])
+      trace: ($,PositiveInteger)   -> $
+        ++ trace(a,d) computes the trace of \spad{a} with respect to the
+        ++ field of extension degree d over the ground field of size q.
+        ++ Error: if d does not divide the extension degree of \spad{a}.
+        ++ Note: \spad{trace(a,d)=reduce(+,[a**(q**(d*i)) for i in 0..n/d])}.
+      createNormalElement: () -> $
+        ++ createNormalElement() computes a normal element over the ground
+        ++ field F, that is,
+        ++ \spad{a**(q**i), 0 <= i < extensionDegree()} is an F-basis,
+        ++ where \spad{q = size()\$F}.
+        ++ Reference: Such an element exists Lidl/Niederreiter: Theorem 2.35.
+      normalElement: () -> $
+        ++ normalElement() returns a element, normal over the ground field F,
+        ++ i.e. \spad{a**(q**i), 0 <= i < extensionDegree()} is an F-basis,
+        ++ where \spad{q = size()\$F}.
+        ++ At the first call, the element is computed by
+        ++ \spadfunFrom{createNormalElement}{FiniteAlgebraicExtensionField}
+        ++ then cached in a global variable.
+        ++ On subsequent calls, the element is retrieved by referencing the
+        ++ global variable.
+      normal?: $ -> Boolean
+        ++ normal?(a) tests whether the element \spad{a} is normal over the
+        ++ ground field F, i.e.
+        ++ \spad{a**(q**i), 0 <= i <= extensionDegree()-1} is an F-basis,
+        ++ where \spad{q = size()\$F}.
+        ++ Implementation according to Lidl/Niederreiter: Theorem 2.39.
+      generator: () -> $
+        ++ generator() returns a root of the defining polynomial.
+        ++ This element generates the field as an algebra over the ground
+        ++ field.
+      linearAssociatedExp:($,SparseUnivariatePolynomial F) -> $
+        ++ linearAssociatedExp(a,f) is linear over {\em F}, i.e.
+        ++ for elements {\em a} from {\em \$}, {\em c,d} form {\em F} and
+        ++ {\em f,g} univariate polynomials over {\em F} we have
+        ++ \spadfun{linearAssociatedExp}(a,cf+dg) equals {\em c} times
+        ++ \spadfun{linearAssociatedExp}(a,f) plus {\em d} times
+        ++ \spadfun{linearAssociatedExp}(a,g). Therefore
+        ++ \spadfun{linearAssociatedExp} is defined completely by its 
+        ++ action on monomials from {\em F[X]}:
+        ++ \spadfun{linearAssociatedExp}(a,monomial(1,k)\$SUP(F)) is 
+        ++ defined to be \spadfun{Frobenius}(a,k) which is {\em a**(q**k)},
+        ++ where {\em q=size()\$F}.
+      linearAssociatedOrder: $ -> SparseUnivariatePolynomial F
+        ++ linearAssociatedOrder(a) retruns the monic polynomial {\em g} of
+        ++ least degree, such that \spadfun{linearAssociatedExp}(a,g) is 0.
+      linearAssociatedLog: $ -> SparseUnivariatePolynomial F
+        ++ linearAssociatedLog(a) returns a polynomial {\em g}, such that
+        ++ \spadfun{linearAssociatedExp}(normalElement(),g) equals {\em a}.
+      linearAssociatedLog: ($,$) -> _
+        Union(SparseUnivariatePolynomial F,"failed")
+        ++ linearAssociatedLog(b,a) returns a polynomial {\em g}, such 
+        ++ that the \spadfun{linearAssociatedExp}(b,g) equals {\em a}.
+        ++ If there is no such polynomial {\em g}, then
+        ++ \spadfun{linearAssociatedLog} fails.
+  add
+    I   ==> Integer
+    PI  ==> PositiveInteger
+    NNI ==> NonNegativeInteger
+    SUP ==> SparseUnivariatePolynomial
+    DLP ==> DiscreteLogarithmPackage
+
+    represents(v) ==
+      a:$:=0
+      b:=basis()
+      for i in 1..extensionDegree()@PI repeat
+        a:=a+(v.i)*(b.i)
+      a
+
+    transcendenceDegree() == 0$NNI
+
+    dimension() == (#basis()) ::NonNegativeInteger::CardinalNumber
+
+    coordinates(v:Vector $) ==
+      m := new(#v, extensionDegree(), 0)$Matrix(F)
+      for i in minIndex v .. maxIndex v for j in minRowIndex m .. repeat
+        setRow_!(m, j, coordinates qelt(v, i))
+      m
+
+    algebraic? a == true
+
+    transcendent? a == false
+
+-- This definition is a duplicate and has been removed
+--    extensionDegree():OnePointCompletion(PositiveInteger) ==
+--      (#basis()) :: PositiveInteger::OnePointCompletion(PositiveInteger)
+
+    extensionDegree() == (#basis()) :: PositiveInteger
+
+-- These definitions are duplicates and have been removed
+--    degree(a):OnePointCompletion(PositiveInteger) ==
+--      degree(a)@PI::OnePointCompletion(PositiveInteger)
+
+    -- degree a == degree(minimalPolynomial a)$SUP(F) :: PI
+
+    trace a ==
+      b := basis()
+      abs : F := 0
+      for i in 1..#b repeat
+        abs := abs + coordinates(a*b.i).i
+      abs
+
+    norm a ==
+      b := basis()
+      m := new(#b,#b, 0)$Matrix(F)
+      for i in 1..#b repeat
+        setRow_!(m,i, coordinates(a*b.i))
+      determinant(m)
+
+    if F has Finite then
+      linearAssociatedExp(x,f) ==
+        erg:$:=0
+        y:=x
+        for i in 0..degree(f) repeat
+          erg:=erg + coefficient(f,i) * y
+          y:=Frobenius(y)
+        erg
+
+      linearAssociatedLog(b,x) ==
+        x=0 => 0
+        l:List List F:=[entries coordinates b]
+        a:$:=b
+        extdeg:NNI:=extensionDegree()@PI
+        for i in 2..extdeg repeat
+          a:=Frobenius(a)
+          l:=concat(l,entries coordinates a)$(List List F)
+        l:=concat(l,entries coordinates x)$(List List F)
+        m1:=rowEchelon transpose matrix(l)$(Matrix F)
+        v:=zero(extdeg)$(Vector F)
+        rown:I:=1
+        for i in 1..extdeg repeat
+          if qelt(m1,rown,i) = 1$F then
+            v.i:=qelt(m1,rown,extdeg+1)
+            rown:=rown+1
+        p:=+/[monomial(v.(i+1),i::NNI) for i in 0..(#v-1)]
+        p=0 =>
+         messagePrint("linearAssociatedLog: second argument not in_
+                       group generated by first argument")$OutputForm
+         "failed"
+        p
+
+      linearAssociatedLog(x) == linearAssociatedLog(normalElement(),x) ::
+                              SparseUnivariatePolynomial(F)
+
+      linearAssociatedOrder(x) ==
+        x=0 => 0
+        l:List List F:=[entries coordinates x]
+        a:$:=x
+        for i in 1..extensionDegree()@PI repeat
+          a:=Frobenius(a)
+          l:=concat(l,entries coordinates a)$(List List F)
+        v:=first nullSpace transpose matrix(l)$(Matrix F)
+        +/[monomial(v.(i+1),i::NNI) for i in 0..(#v-1)]
+
+      charthRoot(x):Union($,"failed") ==
+        (charthRoot(x)@$)::Union($,"failed")
+      -- norm(e) == norm(e,1) pretend F
+      -- trace(e) == trace(e,1) pretend F
+
+      minimalPolynomial(a,n) ==
+        extensionDegree()@PI rem n ^= 0 =>
+          error "minimalPolynomial: 2. argument must divide extension degree"
+        f:SUP $:=monomial(1,1)$(SUP $) - monomial(a,0)$(SUP $)
+        u:$:=Frobenius(a,n)
+        while not(u = a) repeat
+          f:=f * (monomial(1,1)$(SUP $) - monomial(u,0)$(SUP $))
+          u:=Frobenius(u,n)
+        f
+
+      norm(e,s) ==
+        qr := divide(extensionDegree(), s)
+        zero?(qr.remainder) =>
+          pow := (size()-1) quo (size()$F ** s - 1)
+          e ** (pow::NonNegativeInteger)
+        error "norm: second argument must divide degree of extension"
+
+      trace(e,s) ==
+        qr:=divide(extensionDegree(),s)
+        q:=size()$F
+        zero?(qr.remainder) =>
+          a:$:=0
+          for i in 0..qr.quotient-1 repeat
+            a:=a + e**(q**(s*i))
+          a
+        error "trace: second argument must divide degree of extension"
+
+      size() == size()$F ** extensionDegree()
+
+      createNormalElement() ==
+        characteristic() = size() => 1
+        res : $
+        for i in 1.. repeat
+          res := index(i :: PI)
+          not inGroundField? res =>
+            normal? res => return res
+        -- theorem: there exists a normal element, this theorem is
+        -- unknown to the compiler
+        res
+
+      normal?(x:$) ==
+        p:SUP $:=(monomial(1,extensionDegree()) - monomial(1,0))@(SUP $)
+        f:SUP $:= +/[monomial(Frobenius(x,i),i)$(SUP $) _
+                   for i in 0..extensionDegree()-1]
+        gcd(p,f) = 1 => true
+        false
+
+      degree a ==
+        y:$:=Frobenius a
+        deg:PI:=1
+        while y^=a repeat
+          y := Frobenius(y)
+          deg:=deg+1
+        deg
+
+@
+<<FAXF.dotabb>>=
+"FAXF"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FAXF"];
+"FAXF" -> "XF"
+"FAXF" -> "RETRACT"
+
+@
+<<FAXF.dotfull>>=
+"FiniteAlgebraicExtensionField(a:Field)"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FAXF"];
+"FiniteAlgebraicExtensionField(a:Field)" -> "ExtensionField(a:Field)"
+"FiniteAlgebraicExtensionField(a:Field)" -> "RetractableTo(a:Field)"
+
+@
+<<FAXF.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"FiniteAlgebraicExtensionField(a:Field)"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FAXF"];
+"FiniteAlgebraicExtensionField(a:Field)" -> "ExtensionField(a:Field)"
+"FiniteAlgebraicExtensionField(a:Field)" -> "RetractableTo(Field)"
+
+"ExtensionField(a:Field)" [color=lightblue];
+"ExtensionField(a:Field)" -> "Field()"
+"ExtensionField(a:Field)" -> "RetractableTo(Field)"
+"ExtensionField(a:Field)" -> "VectorSpace(a:Field)"
+
+"Field()" [color=lightblue];
+"Field()" -> "EuclideanDomain()"
+"Field()" -> "UniqueFactorizationDomain()"
+"Field()" -> "DIVRING..."
+
+"EuclideanDomain()" [color=lightblue];
+"EuclideanDomain()" -> "PrincipalIdealDomain()"
+
+"UniqueFactorizationDomain()" [color=lightblue];
+"UniqueFactorizationDomain()" -> "GCDDOM..."
+
+"PrincipalIdealDomain()" [color=lightblue];
+"PrincipalIdealDomain()" -> "GCDDOM..."
+
+"RetractableTo(Field)" [color=seagreen];
+"RetractableTo(Field)" -> "RetractableTo(a:Type)"
+
+"RetractableTo(a:Type)" [color=lightblue];
+"RetractableTo(a:Type)" -> "Category"
+
+"VectorSpace(a:Field)" [color=lightblue];
+"VectorSpace(a:Field)" -> "MODULE..."
+
+"MODULE..." [color=lightblue];
+"DIVRING..." [color=lightblue];
+"GCDDOM..." [color=lightblue];
+"Category" [color=lightblue];
+}
+
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{MonogenicAlgebra}{MONOGEN}
+\pagepic{ps/v102monogenicalgebra.ps}{MONOGEN}{0.40}
+
+{\bf See:}\\
+\pageto{FunctionFieldCategory}{FFCAT}
+\pagefrom{CommutativeRing}{COMRING}
+\pagefrom{ConvertibleTo}{KONVERT}
+\pagefrom{FramedAlgebra}{FRAMALG}
+\pagefrom{FullyRetractableTo}{FRETRCT}
+\pagefrom{LinearlyExplicitRingOver}{LINEXP}
+
+{\bf Exports:}\\
+\begin{tabular}{lll}
+\cross{MONOGEN}{0} &
+\cross{MONOGEN}{1} &
+\cross{MONOGEN}{associates?} \\
+\cross{MONOGEN}{basis} &
+\cross{MONOGEN}{characteristic} &
+\cross{MONOGEN}{characteristicPolynomial} \\
+\cross{MONOGEN}{charthRoot} &
+\cross{MONOGEN}{coerce} &
+\cross{MONOGEN}{conditionP} \\
+\cross{MONOGEN}{convert} &
+\cross{MONOGEN}{coordinates} &
+\cross{MONOGEN}{createPrimitiveElement} \\
+\cross{MONOGEN}{D} &
+\cross{MONOGEN}{definingPolynomial} &
+\cross{MONOGEN}{derivationCoordinates} \\
+\cross{MONOGEN}{differentiate} &
+\cross{MONOGEN}{discreteLog} &
+\cross{MONOGEN}{discriminant} \\
+\cross{MONOGEN}{divide} &
+\cross{MONOGEN}{euclideanSize} &
+\cross{MONOGEN}{expressIdealMember} \\
+\cross{MONOGEN}{exquo} &
+\cross{MONOGEN}{extendedEuclidean} &
+\cross{MONOGEN}{factor} \\
+\cross{MONOGEN}{factorsOfCyclicGroupSize} &
+\cross{MONOGEN}{generator} &
+\cross{MONOGEN}{gcd} \\
+\cross{MONOGEN}{gcdPolynomial} &
+\cross{MONOGEN}{hash} &
+\cross{MONOGEN}{index} \\
+\cross{MONOGEN}{init} &
+\cross{MONOGEN}{inv} &
+\cross{MONOGEN}{latex} \\
+\cross{MONOGEN}{lcm} &
+\cross{MONOGEN}{lift} &
+\cross{MONOGEN}{lookup} \\
+\cross{MONOGEN}{minimalPolynomial} &
+\cross{MONOGEN}{multiEuclidean} &
+\cross{MONOGEN}{nextItem} \\
+\cross{MONOGEN}{norm} &
+\cross{MONOGEN}{one?} &
+\cross{MONOGEN}{order} \\
+\cross{MONOGEN}{prime?} &
+\cross{MONOGEN}{primeFrobenius} &
+\cross{MONOGEN}{primitive?} \\
+\cross{MONOGEN}{primitiveElement} &
+\cross{MONOGEN}{principalIdeal} &
+\cross{MONOGEN}{random} \\
+\cross{MONOGEN}{rank} &
+\cross{MONOGEN}{recip} &
+\cross{MONOGEN}{reduce} \\
+\cross{MONOGEN}{reducedSystem} &
+\cross{MONOGEN}{regularRepresentation} &
+\cross{MONOGEN}{represents} \\
+\cross{MONOGEN}{representationType} &
+\cross{MONOGEN}{retract} &
+\cross{MONOGEN}{retractIfCan} \\
+\cross{MONOGEN}{sample} &
+\cross{MONOGEN}{size} &
+\cross{MONOGEN}{sizeLess?} \\
+\cross{MONOGEN}{squareFree} &
+\cross{MONOGEN}{squareFreePart} &
+\cross{MONOGEN}{subtractIfCan} \\
+\cross{MONOGEN}{tableForDiscreteLogarithm} &
+\cross{MONOGEN}{trace} &
+\cross{MONOGEN}{traceMatrix} \\
+\cross{MONOGEN}{unit?} &
+\cross{MONOGEN}{unitCanonical} &
+\cross{MONOGEN}{unitNormal} \\
+\cross{MONOGEN}{zero?} &
+\cross{MONOGEN}{?*?} &
+\cross{MONOGEN}{?**?} \\
+\cross{MONOGEN}{?+?} &
+\cross{MONOGEN}{?-?} &
+\cross{MONOGEN}{-?} \\
+\cross{MONOGEN}{?=?} &
+\cross{MONOGEN}{?\^{}?} &
+\cross{MONOGEN}{?\~{}=?} \\
+\cross{MONOGEN}{?/?} &
+\cross{MONOGEN}{?quo?} &
+\cross{MONOGEN}{?rem?} \\
+\end{tabular}
+
+{\bf Attributes Exported:}
+\begin{itemize}
+\item if \$ has Field then canonicalUnitNormal where
+{\bf \cross{MONOGEN}{canonicalUnitNormal}}
+is true if we can choose a canonical representative for each class 
+of associate elements, that is {\tt associates?(a,b)} returns true 
+if and only if {\tt unitCanonical(a) = unitCanonical(b)}.
+\item if \$ has Field then canonicalClosed where
+{\bf \cross{MONOGEN}{canonicalsClosed}}
+is true if\\
+{\tt unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
+\item if \$ has Field then noZeroDivisors where
+{\bf \cross{MONOGEN}{noZeroDivisors}}
+is true if $x * y \ne 0$ implies both x and y are non-zero.
+\item {\bf \cross{MONOGEN}{commutative("*")}}
+is true if it has an operation $"*": (D,D) -> D$
+which is commutative.
+\item {\bf \cross{MONOGEN}{unitsKnown}}
+is true if a monoid (a multiplicative semigroup with a 1) has 
+unitsKnown means that  the operation {\tt recip} can only return 
+``failed'' if its argument is not a unit.
+\item {\bf \cross{MONOGEN}{leftUnitary}}
+is true if $1 * x = x$ for all x.
+\item {\bf \cross{MONOGEN}{rightUnitary}}
+is true if $x * 1 = x$ for all x.
+\end{itemize}
+
+These are directly exported but not implemented:
+\begin{verbatim}
+ definingPolynomial : () -> UP        
+ lift : % -> UP
+ reduce : UP -> %                     
+\end{verbatim}
+
+These are implemented by this category:
+\begin{verbatim}
+ basis : () -> Vector %
+ characteristicPolynomial : % -> UP
+ convert : % -> UP                    
+ convert : UP -> %
+ derivationCoordinates : (Vector %,(R -> R)) -> Matrix R 
+     if R has FIELD
+ differentiate : (%,(R -> R)) -> % if R has FIELD
+ generator : () -> %
+ norm : % -> R                        
+ random : () -> % if R has FINITE
+ recip : % -> Union(%,"failed")
+ reduce : Fraction UP -> Union(%,"failed") if R has FIELD
+ retract : % -> R                     
+ retractIfCan : % -> Union(R,"failed")
+ size : () -> NonNegativeInteger if R has FINITE
+\end{verbatim}
+
+These exports come from \refto{FramedAlgebra}(R,UP)\\
+where R:CommutativeRing and UP:UnivariatePolynomialCategory(a)
+\begin{verbatim}
+ 0 : () -> %
+ 1 : () -> %                          
+ characteristic : () -> NonNegativeInteger
+ charthRoot : % -> Union(%,"failed") if R has CHARNZ
+ coerce : R -> %                      
+ coerce : Integer -> %
+ coerce : % -> OutputForm             
+ convert : Vector R -> %
+ convert : % -> Vector R              
+ coordinates : (%,Vector %) -> Vector R
+ coordinates : (Vector %,Vector %) -> Matrix R
+ coordinates : Vector % -> Matrix R
+ coordinates : % -> Vector R
+ discriminant : Vector % -> R         
+ discriminant : () -> R
+ hash : % -> SingleInteger            
+ latex : % -> String                  
+ minimalPolynomial : % -> UP if R has FIELD
+ one? : % -> Boolean
+ rank : () -> PositiveInteger         
+ regularRepresentation : (%,Vector %) -> Matrix R
+ regularRepresentation : % -> Matrix R
+ represents : (Vector R,Vector %) -> %
+ represents : Vector R -> %
+ sample : () -> %
+ subtractIfCan : (%,%) -> Union(%,"failed")
+ trace : % -> R                       
+ traceMatrix : Vector % -> Matrix R
+ traceMatrix : () -> Matrix R
+ zero? : % -> Boolean                 
+ ?+? : (%,%) -> %                     
+ ?=? : (%,%) -> Boolean
+ ?~=? : (%,%) -> Boolean
+ ?*? : (%,%) -> %                     
+ ?*? : (Integer,%) -> %
+ ?*? : (PositiveInteger,%) -> %       
+ ?*? : (NonNegativeInteger,%) -> %
+ ?*? : (R,%) -> %                     
+ ?*? : (%,R) -> %
+ ?-? : (%,%) -> %
+ -? : % -> %                          
+ ?**? : (%,PositiveInteger) -> %
+ ?**? : (%,NonNegativeInteger) -> %
+ ?^? : (%,PositiveInteger) -> %       
+ ?^? : (%,NonNegativeInteger) -> %
+\end{verbatim}
+
+These exports come from \refto{CommutativeRing}()
+\begin{verbatim}
+\end{verbatim}
+
+These exports come from \refto{ConvertibleTo}\\
+where UP:UnivariatePolynomialCategory(CommutativeRing)
+\begin{verbatim}
+\end{verbatim}
+
+These exports come from \refto{FullyRetractableTo}(R)\\
+where R:CommutativeRing
+\begin{verbatim}
+ coerce : Fraction Integer -> % 
+     if R has FIELD or R has RETRACT FRAC INT
+ retract : % -> Integer if R has RETRACT INT
+ retract : % -> Fraction Integer 
+     if R has RETRACT FRAC INT
+ retractIfCan : % -> Union(Fraction Integer,"failed") 
+     if R has RETRACT FRAC INT
+ retractIfCan : % -> Union(Integer,"failed") 
+     if R has RETRACT INT
+\end{verbatim}
+
+These exports come from \refto{FullyLinearlyExplicitRingOver}(R)\\
+where R:CommutativeRing
+\begin{verbatim}
+ reducedSystem : Matrix % -> Matrix R
+ reducedSystem :
+   (Matrix %,Vector %) -> Record(mat: Matrix R,vec: Vector R)
+ reducedSystem :
+   (Matrix %,Vector %) ->
+      Record(mat: Matrix Integer,vec: Vector Integer) 
+        if R has LINEXP INT
+ reducedSystem : Matrix % -> Matrix Integer if R has LINEXP INT
+\end{verbatim}
+
+These exports come from \refto{Finite}()
+\begin{verbatim}
+ index : PositiveInteger -> % if R has FINITE
+ lookup : % -> PositiveInteger if R has FINITE
+\end{verbatim}
+
+These exports come from \refto{Field}()
+\begin{verbatim}
+ associates? : (%,%) -> Boolean if R has FIELD
+ coerce : % -> % if R has FIELD
+ divide : (%,%) -> Record(quotient: %,remainder: %) 
+     if R has FIELD
+ euclideanSize : % -> NonNegativeInteger if R has FIELD
+ expressIdealMember : (List %,%) -> Union(List %,"failed") 
+     if R has FIELD
+ exquo : (%,%) -> Union(%,"failed") if R has FIELD
+ extendedEuclidean : (%,%) -> Record(coef1: %,coef2: %,generator: %) 
+     if R has FIELD
+ extendedEuclidean : (%,%,%) -> Union(Record(coef1: %,coef2: %),"failed") 
+     if R has FIELD
+ factor : % -> Factored % if R has FIELD
+ gcd : (%,%) -> % if R has FIELD
+ gcd : List % -> % if R has FIELD
+ gcdPolynomial :
+    (SparseUnivariatePolynomial %,
+     SparseUnivariatePolynomial %) ->
+        SparseUnivariatePolynomial % if R has FIELD
+ inv : % -> % if R has FIELD
+ lcm : (%,%) -> % if R has FIELD
+ lcm : List % -> % if R has FIELD
+ multiEuclidean : (List %,%) -> Union(List %,"failed") 
+     if R has FIELD
+ prime? : % -> Boolean if R has FIELD
+ principalIdeal : List % -> Record(coef: List %,generator: %) 
+     if R has FIELD
+ sizeLess? : (%,%) -> Boolean if R has FIELD
+ squareFree : % -> Factored % if R has FIELD
+ squareFreePart : % -> % if R has FIELD
+ unit? : % -> Boolean if R has FIELD
+ unitCanonical : % -> % if R has FIELD
+ unitNormal : % -> Record(unit: %,canonical: %,associate: %) 
+     if R has FIELD
+ ?/? : (%,%) -> % if R has FIELD
+ ?*? : (%,Fraction Integer) -> % if R has FIELD
+ ?*? : (Fraction Integer,%) -> % if R has FIELD
+ ?**? : (%,Integer) -> % if R has FIELD
+ ?^? : (%,Integer) -> % if R has FIELD
+ ?quo? : (%,%) -> % if R has FIELD
+ ?rem? : (%,%) -> % if R has FIELD
+\end{verbatim}
+
+These exports come from \refto{DifferentialExtension}(R)\\
+where R:CommutativeRing
+\begin{verbatim}
+ D : (%,(R -> R)) -> % if R has FIELD
+ D : (%,(R -> R),NonNegativeInteger) -> % if R has FIELD
+ D : % -> % 
+     if and(has(R,DifferentialRing),has(R,Field)) 
+     or R has FFIELDC
+ D : (%,NonNegativeInteger) -> % 
+     if and(has(R,DifferentialRing),has(R,Field)) 
+     or R has FFIELDC
+ D : (%,List Symbol,List NonNegativeInteger) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+ D : (%,Symbol,NonNegativeInteger) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+ D : (%,List Symbol) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+ D : (%,Symbol) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+ differentiate : % -> % 
+     if and(has(R,DifferentialRing),has(R,Field)) 
+     or R has FFIELDC
+ differentiate : (%,NonNegativeInteger) -> % 
+     if and(has(R,DifferentialRing),has(R,Field)) 
+     or R has FFIELDC
+ differentiate : (%,List Symbol) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+ differentiate : (%,Symbol,NonNegativeInteger) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+ differentiate : (%,List Symbol,List NonNegativeInteger) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+ differentiate : (%,(R -> R),NonNegativeInteger) -> % 
+     if R has FIELD
+ differentiate : (%,Symbol) -> % 
+     if and(has(R,PartialDifferentialRing Symbol),has(R,Field))
+\end{verbatim}
+
+These exports come from \refto{FiniteFieldCategory}():
+\begin{verbatim}
+ charthRoot : % -> % if R has FFIELDC
+ conditionP : Matrix % -> Union(Vector %,"failed") 
+     if R has FFIELDC
+ createPrimitiveElement : () -> % if R has FFIELDC
+ discreteLog : % -> NonNegativeInteger if R has FFIELDC
+ discreteLog : (%,%) -> Union(NonNegativeInteger,"failed") 
+     if R has FFIELDC
+ factorsOfCyclicGroupSize : () ->
+    List Record(factor: Integer,exponent: Integer) 
+      if R has FFIELDC
+ init : () -> % if R has FFIELDC
+ nextItem : % -> Union(%,"failed") if R has FFIELDC
+ order : % -> OnePointCompletion PositiveInteger 
+     if R has FFIELDC
+ order : % -> PositiveInteger if R has FFIELDC
+ primeFrobenius : % -> % if R has FFIELDC
+ primeFrobenius : (%,NonNegativeInteger) -> % if R has FFIELDC
+ primitive? : % -> Boolean if R has FFIELDC
+ primitiveElement : () -> % if R has FFIELDC
+ representationType : () ->
+    Union("prime",polynomial,normal,cyclic) 
+      if R has FFIELDC
+ tableForDiscreteLogarithm : 
+    Integer -> Table(PositiveInteger,NonNegativeInteger) 
+      if R has FFIELDC
+\end{verbatim}
+
+<<category MONOGEN MonogenicAlgebra>>=
+)abbrev category MONOGEN MonogenicAlgebra
+++ Author: Barry Trager
+++ Date Created:
+++ Date Last Updated:
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ References:
+++ Description:
+++ A \spadtype{MonogenicAlgebra} is an algebra of finite rank which
+++ can be generated by a single element.
+
+MonogenicAlgebra(R:CommutativeRing, UP:UnivariatePolynomialCategory R):
+ Category ==
+    Join(FramedAlgebra(R, UP), CommutativeRing, ConvertibleTo UP,
+              FullyRetractableTo R, FullyLinearlyExplicitRingOver R) with
+      generator         : () -> %
+        ++ generator() returns the generator for this domain.
+      definingPolynomial: () -> UP
+        ++ definingPolynomial() returns the minimal polynomial which
+        ++ \spad{generator()} satisfies.
+      reduce            : UP -> %
+        ++ reduce(up) converts the univariate polynomial up to an algebra
+        ++ element, reducing by the \spad{definingPolynomial()} if necessary.
+      convert           : UP -> %
+        ++ convert(up) converts the univariate polynomial up to an algebra
+        ++ element, reducing by the \spad{definingPolynomial()} if necessary.
+      lift              : % -> UP
+        ++ lift(z) returns a minimal degree univariate polynomial up such that
+        ++ \spad{z=reduce up}.
+      if R has Finite then Finite
+      if R has Field then
+        Field
+        DifferentialExtension R
+        reduce               : Fraction UP -> Union(%, "failed")
+          ++ reduce(frac) converts the fraction frac to an algebra element.
+        derivationCoordinates: (Vector %, R -> R) -> Matrix R
+          ++ derivationCoordinates(b, ') returns M such that \spad{b' = M b}.
+      if R has FiniteFieldCategory then FiniteFieldCategory
+  add
+   convert(x:%):UP == lift x
+   convert(p:UP):% == reduce p
+   generator()     == reduce monomial(1, 1)$UP
+   norm x          == resultant(definingPolynomial(), lift x)
+   retract(x:%):R  == retract lift x
+   retractIfCan(x:%):Union(R, "failed") == retractIfCan lift x
+
+   basis() ==
+     [reduce monomial(1,i)$UP for i in 0..(rank()-1)::NonNegativeInteger]
+
+   characteristicPolynomial(x:%):UP ==
+     characteristicPolynomial(x)$CharacteristicPolynomialInMonogenicalAlgebra(R,UP,%)
+
+   if R has Finite then
+     size()   == size()$R ** rank()
+     random() == represents [random()$R for i in 1..rank()]$Vector(R)
+
+   if R has Field then
+     reduce(x:Fraction UP) == reduce(numer x) exquo reduce(denom x)
+
+     differentiate(x:%, d:R -> R) ==
+       p := definingPolynomial()
+       yprime := - reduce(map(d, p)) / reduce(differentiate p)
+       reduce(map(d, lift x)) + yprime * reduce differentiate lift x
+
+     derivationCoordinates(b, d) ==
+       coordinates(map(differentiate(#1, d), b), b)
+
+     recip x ==
+       (bc := extendedEuclidean(lift x, definingPolynomial(), 1))
+                                                case "failed" => "failed"
+       reduce(bc.coef1)
+
+@
+<<MONOGEN.dotabb>>=
+"MONOGEN"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=MONOGEN"];
+"MONOGEN" -> "FRAMALG"
+"MONOGEN" -> "COMRING"
+"MONOGEN" -> "KONVERT"
+"MONOGEN" -> "FRETRCT"
+"MONOGEN" -> "FLINEXP"
+"MONOGEN" -> "FINITE"
+"MONOGEN" -> "FIELD"
+"MONOGEN" -> "DIFEXT"
+"MONOGEN" -> "FFIELDC"
+
+@
+<<MONOGEN.dotfull>>=
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=MONOGEN"];
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "CommutativeRing()"
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "ConvertibleTo(UnivariatePolynomialCategory(CommutativeRing))"
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FullyRetractableTo(a:CommutativeRing)"
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FullyLinearlyExplicitRingOver(a:CommutativeRing)"
+
+"MonogenicAlgebra(a:FRAC(UPOLYC(UFD)),b:UPOLYC(FRAC(UPOLYC(UFD))))"
+ [color=seagreen,href="bookvol10.2.pdf#nameddest=MONOGEN"];
+"MonogenicAlgebra(a:FRAC(UPOLYC(UFD)),b:UPOLYC(FRAC(UPOLYC(UFD))))" ->
+    "MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+
+@
+<<MONOGEN.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+ [color=lightblue];
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FRAMALG..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "COMRING..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "KONVERT..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FRETRCT..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FLINEXP..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FINITE..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FIELD..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "DIFEXT..."
+"MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
+    "FFIELDC..."
+
+"FRAMALG..." [color=lightblue];
+"COMRING..." [color=lightblue];
+"KONVERT..." [color=lightblue];
+"FRETRCT..." [color=lightblue];
+"FLINEXP..." [color=lightblue];
+"FINITE..." [color=lightblue];
+"FIELD..." [color=lightblue];
+"DIFEXT..." [color=lightblue];
+"FFIELDC..." [color=lightblue];
+}
+
+@
+\chapter{Category Layer 20}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{FunctionFieldCategory}{FFCAT}
 \pagepic{ps/v102functionfieldcategory.ps}{FFCAT}{0.70}
 
@@ -32842,7 +34459,50 @@ is true if $1 * x = x$ for all x.
 is true if $x * 1 = x$ for all x.
 \end{itemize}
 
-TPDHERE:
+These are directly exported but not implemented:
+\begin{verbatim}
+ branchPointAtInfinity? : () -> Boolean
+ branchPoint? : UP -> Boolean         
+ branchPoint? : F -> Boolean
+ integralBasis : () -> Vector %       
+ integralBasisAtInfinity : () -> Vector %
+ ramifiedAtInfinity? : () -> Boolean
+ ramified? : UP -> Boolean            
+ ramified? : F -> Boolean
+ singularAtInfinity? : () -> Boolean
+ singular? : F -> Boolean             
+ singular? : UP -> Boolean
+\end{verbatim}
+
+These are implemented by this category:
+\begin{verbatim}
+ absolutelyIrreducible? : () -> Boolean
+ algSplitSimple : (%,(UP -> UP)) ->
+      Record(num: %,den: UP,derivden: UP,gd: UP)
+ complementaryBasis : Vector % -> Vector %
+ differentiate : (%,(UP -> UP)) -> %
+ elliptic : () -> Union(UP,"failed")
+ elt : (%,F,F) -> F
+ genus : () -> NonNegativeInteger
+ hyperelliptic : () -> Union(UP,"failed")
+ integral? : % -> Boolean
+ integral? : (%,F) -> Boolean         
+ integral? : (%,UP) -> Boolean
+ integralAtInfinity? : % -> Boolean
+ normalizeAtInfinity : Vector % -> Vector %
+ numberOfComponents : () -> NonNegativeInteger
+ primitivePart : % -> %
+ rationalPoint? : (F,F) -> Boolean
+ rationalPoints : () -> List List F if F has FINITE
+ reduceBasisAtInfinity : Vector % -> Vector %
+ represents : (Vector UP,UP) -> %     
+ yCoordinates : % -> Record(num: Vector UP,den: UP)
+\end{verbatim}
+
+These exports come from \refto{MonogenicAlgebra}(RF, UPUP)\\
+where RF:Fraction UP, UP:UnivariatePolynomialCategory F\\
+F:UniqueFactorizationDomain, and\\
+UPUP:UnivariatePolynomialCategory Fraction UP
 \begin{verbatim}
  0 : () -> %
  1 : () -> %                          
@@ -33165,58 +34825,6 @@ TPDHERE:
  ?rem? : (%,%) -> % if Fraction UP has FIELD
 \end{verbatim}
 
-These are directly exported but not implemented:
-\begin{verbatim}
- branchPointAtInfinity? : () -> Boolean
- branchPoint? : UP -> Boolean         
- branchPoint? : F -> Boolean
- integralBasis : () -> Vector %       
- integralBasisAtInfinity : () -> Vector %
- ramifiedAtInfinity? : () -> Boolean
- ramified? : UP -> Boolean            
- ramified? : F -> Boolean
- singularAtInfinity? : () -> Boolean
- singular? : F -> Boolean             
- singular? : UP -> Boolean
-\end{verbatim}
-
-These are implemented by this category:
-\begin{verbatim}
- absolutelyIrreducible? : () -> Boolean
- algSplitSimple : (%,(UP -> UP)) ->
-      Record(num: %,den: UP,derivden: UP,gd: UP)
- complementaryBasis : Vector % -> Vector %
- differentiate : (%,(UP -> UP)) -> %
- elliptic : () -> Union(UP,"failed")
- elt : (%,F,F) -> F
- genus : () -> NonNegativeInteger
- hyperelliptic : () -> Union(UP,"failed")
- integral? : % -> Boolean
- integral? : (%,F) -> Boolean         
- integral? : (%,UP) -> Boolean
- integralAtInfinity? : % -> Boolean
- normalizeAtInfinity : Vector % -> Vector %
- numberOfComponents : () -> NonNegativeInteger
- primitivePart : % -> %
- rationalPoint? : (F,F) -> Boolean
- rationalPoints : () -> List List F if F has FINITE
- reduceBasisAtInfinity : Vector % -> Vector %
- represents : (Vector UP,UP) -> %     
- yCoordinates : % -> Record(num: Vector UP,den: UP)
-\end{verbatim}
-
-These exports come from \refto{Aggregate}:
-\begin{verbatim}
-\end{verbatim}
-
-These exports come from \refto{Evalable}(a:Type):
-\begin{verbatim}
-\end{verbatim}
-
-These exports come from \refto{SetCategory}:
-\begin{verbatim}
-\end{verbatim}
-
 <<category FFCAT FunctionFieldCategory>>=
 )abbrev category FFCAT FunctionFieldCategory
 ++ Function field of a curve
@@ -33651,12 +35259,12 @@ digraph pic {
  node [shape=box, color=white, style=filled];
 
 "FunctionFieldCategory(a:UFD,b:UPOLYC(a),c:UPOLYC(Fraction(b)))"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=FFCAT"];
+ [color=lightblue];
 "FunctionFieldCategory(a:UFD,b:UPOLYC(a),c:UPOLYC(Fraction(b)))"
    -> "MonogenicAlgebra(a:FRAC(UPOLYC(UFD)),b:UPOLYC(FRAC(UPOLYC(UFD))))"
 
 "MonogenicAlgebra(a:FRAC(UPOLYC(UFD)),b:UPOLYC(FRAC(UPOLYC(UFD))))"
- [color=seagreen,href="bookvol10.2.pdf#nameddest=MONOGEN"];
+ [color=seagreen];
 "MonogenicAlgebra(a:FRAC(UPOLYC(UFD)),b:UPOLYC(FRAC(UPOLYC(UFD))))" ->
     "MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
 
@@ -33681,918 +35289,7 @@ digraph pic {
 }
 
 @
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\pagehead{FramedAlgebra}{FRAMALG}
-\pagepic{ps/v102framedalgebra.ps}{FRAMALG}{0.45}
-
-{\bf See:}\\
-\pageto{MonogenicAlgebra}{MONOGEN}
-\pagefrom{FiniteRankAlgebra}{FINRALG}
-
-{\bf Exports:}\\
-\begin{tabular}{lllll}
-\cross{FRAMALG}{0} &
-\cross{FRAMALG}{1} &
-\cross{FRAMALG}{basis} \\
-\cross{FRAMALG}{characteristic} &
-\cross{FRAMALG}{characteristicPolynomial} &
-\cross{FRAMALG}{charthRoot} \\
-\cross{FRAMALG}{coerce} &
-\cross{FRAMALG}{convert} &
-\cross{FRAMALG}{coordinates} \\
-\cross{FRAMALG}{discriminant} &
-\cross{FRAMALG}{hash} &
-\cross{FRAMALG}{latex} \\
-\cross{FRAMALG}{minimalPolynomial} &
-\cross{FRAMALG}{norm} &
-\cross{FRAMALG}{one?} \\
-\cross{FRAMALG}{rank} &
-\cross{FRAMALG}{recip} &
-\cross{FRAMALG}{regularRepresentation} \\
-\cross{FRAMALG}{represents} &
-\cross{FRAMALG}{sample} &
-\cross{FRAMALG}{subtractIfCan} \\
-\cross{FRAMALG}{trace} &
-\cross{FRAMALG}{traceMatrix} &
-\cross{FRAMALG}{zero?} \\
-\cross{FRAMALG}{?*?} &
-\cross{FRAMALG}{?**?} &
-\cross{FRAMALG}{?+?} \\
-\cross{FRAMALG}{?-?} &
-\cross{FRAMALG}{-?} &
-\cross{FRAMALG}{?=?} \\
-\cross{FRAMALG}{?\^{}?} &
-\cross{FRAMALG}{?\~{}=?} &
-\end{tabular}
-
-{\bf Attributes Exported:}
-\begin{itemize}
-\item {\bf \cross{FRAMALG}{unitsKnown}}
-is true if a monoid (a multiplicative semigroup with a 1) has 
-unitsKnown means that  the operation {\tt recip} can only return 
-``failed'' if its argument is not a unit.
-\item {\bf \cross{FRAMALG}{leftUnitary}}
-is true if $1 * x = x$ for all x.
-\item {\bf \cross{FRAMALG}{rightUnitary}}
-is true if $x * 1 = x$ for all x.
-\end{itemize}
-
-These are directly exported but not implemented:
-\begin{verbatim}
- basis : () -> Vector %
- represents : Vector R -> %           
-\end{verbatim}
-
-These are implemented by this category:
-\begin{verbatim}
- convert : Vector R -> %
- convert : % -> Vector R              
- coordinates : Vector % -> Matrix R
- coordinates : % -> Vector R
- discriminant : () -> R               
- regularRepresentation : % -> Matrix R
- traceMatrix : () -> Matrix R
-\end{verbatim}
-
-These exports come from \refto{FiniteRankAlgebra}(R, UP)\\
-where R:CommutativeRing and UP:UnivariatePolynomialCategory R):
-\begin{verbatim}
- 0 : () -> %
- 1 : () -> %                          
- characteristic : () -> NonNegativeInteger
- characteristicPolynomial : % -> UP
- charthRoot : % -> Union(%,"failed") if R has CHARNZ
- coerce : R -> %                      
- coerce : Integer -> %
- coerce : % -> OutputForm             
- coordinates : (%,Vector %) -> Vector R
- coordinates : (Vector %,Vector %) -> Matrix R
- discriminant : Vector % -> R
- hash : % -> SingleInteger            
- latex : % -> String
- minimalPolynomial : % -> UP if R has FIELD
- norm : % -> R                        
- one? : % -> Boolean
- rank : () -> PositiveInteger         
- recip : % -> Union(%,"failed")
- regularRepresentation : (%,Vector %) -> Matrix R
- represents : (Vector R,Vector %) -> %
- sample : () -> %
- subtractIfCan : (%,%) -> Union(%,"failed")
- trace : % -> R                       
- traceMatrix : Vector % -> Matrix R
- zero? : % -> Boolean                 
- ?+? : (%,%) -> %                     
- ?=? : (%,%) -> Boolean
- ?~=? : (%,%) -> Boolean
- ?*? : (%,%) -> %                     
- ?*? : (Integer,%) -> %
- ?*? : (PositiveInteger,%) -> %       
- ?*? : (NonNegativeInteger,%) -> %
- ?*? : (R,%) -> %                     
- ?*? : (%,R) -> %
- ?-? : (%,%) -> %
- -? : % -> %                          
- ?**? : (%,PositiveInteger) -> %
- ?**? : (%,NonNegativeInteger) -> %
- ?^? : (%,PositiveInteger) -> %       
- ?^? : (%,NonNegativeInteger) -> %
-\end{verbatim}
-
-<<category FRAMALG FramedAlgebra>>=
-)abbrev category FRAMALG FramedAlgebra
-++ Author: Barry Trager
-++ Date Created:
-++ Date Last Updated:
-++ Basic Functions:
-++ Related Constructors:
-++ Also See:
-++ AMS Classifications:
-++ Keywords:
-++ References:
-++ Description:
-++ A \spadtype{FramedAlgebra} is a \spadtype{FiniteRankAlgebra} together
-++ with a fixed R-module basis.
-
-FramedAlgebra(R:CommutativeRing, UP:UnivariatePolynomialCategory R):
- Category == FiniteRankAlgebra(R, UP) with
-      basis                 : () -> Vector %
-        ++ basis() returns the fixed R-module basis.
-      coordinates           : % -> Vector R
-        ++ coordinates(a) returns the coordinates of \spad{a} with 
-        ++ respect to the fixed R-module basis.
-      coordinates           : Vector % -> Matrix R
-        ++ coordinates([v1,...,vm]) returns the coordinates of the
-        ++ vi's with to the fixed basis.  The coordinates of vi are
-        ++ contained in the ith row of the matrix returned by this
-        ++ function.
-      represents            : Vector R -> %
-        ++ represents([a1,..,an]) returns \spad{a1*v1 + ... + an*vn}, where
-        ++ v1, ..., vn are the elements of the fixed basis.
-      convert               : % -> Vector R
-        ++ convert(a) returns the coordinates of \spad{a} with respect to the
-        ++ fixed R-module basis.
-      convert               : Vector R -> %
-        ++ convert([a1,..,an]) returns \spad{a1*v1 + ... + an*vn}, where
-        ++ v1, ..., vn are the elements of the fixed basis.
-      traceMatrix           : () -> Matrix R
-        ++ traceMatrix() is the n-by-n matrix ( \spad{Tr(vi * vj)} ), where
-        ++ v1, ..., vn are the elements of the fixed basis.
-      discriminant          : () -> R
-        ++ discriminant() = determinant(traceMatrix()).
-      regularRepresentation : % -> Matrix R
-        ++ regularRepresentation(a) returns the matrix of the linear
-        ++ map defined by left multiplication by \spad{a} with respect
-        ++ to the fixed basis.
-    --attributes
-      --separable <=> discriminant() ^= 0
-  add
-   convert(x:%):Vector(R)  == coordinates(x)
-   convert(v:Vector R):%   == represents(v)
-   traceMatrix()           == traceMatrix basis()
-   discriminant()          == discriminant basis()
-   regularRepresentation x == regularRepresentation(x, basis())
-   coordinates x           == coordinates(x, basis())
-   represents x            == represents(x, basis())
-
-   coordinates(v:Vector %) ==
-     m := new(#v, rank(), 0)$Matrix(R)
-     for i in minIndex v .. maxIndex v for j in minRowIndex m .. repeat
-       setRow_!(m, j, coordinates qelt(v, i))
-     m
-
-   regularRepresentation x ==
-     m := new(n := rank(), n, 0)$Matrix(R)
-     b := basis()
-     for i in minIndex b .. maxIndex b for j in minRowIndex m .. repeat
-       setRow_!(m, j, coordinates(x * qelt(b, i)))
-     m
-
-   characteristicPolynomial x ==
-      mat00 := (regularRepresentation x)
-      mat0 := map(#1 :: UP,mat00)$MatrixCategoryFunctions2(R, Vector R,
-                  Vector R, Matrix R, UP, Vector UP,Vector UP, Matrix UP)
-      mat1 : Matrix UP := scalarMatrix(rank(),monomial(1,1)$UP)
-      determinant(mat1 - mat0)
-
-   if R has Field then
-    -- depends on the ordering of results from nullSpace, also see FFP
-      minimalPolynomial(x:%):UP ==
-        y:%:=1
-        n:=rank()
-        m:Matrix R:=zero(n,n+1)
-        for i in 1..n+1 repeat
-          setColumn_!(m,i,coordinates(y))
-          y:=y*x
-        v:=first nullSpace(m)
-        +/[monomial(v.(i+1),i) for i in 0..#v-1]
-
-@
-<<FRAMALG.dotabb>>=
-"FRAMALG"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=FRAMALG"];
-"FRAMALG" -> "FINRALG"
-
-@
-<<FRAMALG.dotfull>>=
-"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=FRAMALG"];
-"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-   "FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
-
-@
-<<FRAMALG.dotpic>>=
-digraph pic {
- fontsize=10;
- bgcolor="#FFFF66";
- node [shape=box, color=white, style=filled];
-
-"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
- [color=lightblue];
-"FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-   "FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
-
-"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
- [color=lightblue];
-"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "Algebra(a:CommutativeRing)"
-"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "Field()"
-"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "CharacteristicNonZero()"
-"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))" ->
-    "CharacteristicZero()"
-
-"Algebra(a:CommutativeRing)" [color=lightblue];
-"Algebra(a:CommutativeRing)" -> "RING..."
-"Algebra(a:CommutativeRing)" -> "MODULE..."
-
-"Field()" [color=lightblue];
-"Field()" -> "EUCDOM..."
-"Field()" -> "UFD..."
-"Field()" -> "DIVRING..."
-
-"CharacteristicNonZero()" [color=lightblue];
-"CharacteristicNonZero()" -> "RING..."
-
-"CharacteristicZero()" [color=lightblue];
-"CharacteristicZero()" -> "RING..."
-
-"EUCDOM..." [color=lightblue];
-"UFD..." [color=lightblue];
-"DIVRING..." [color=lightblue];
-"RING..." [color=lightblue];
-"MODULE..." [color=lightblue];
-}
-
-@
-\chapter{Category Layer 19}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\pagehead{FiniteAlgebraicExtensionField}{FAXF}
-\pagepic{ps/v102finitealgebraicextensionfield.ps}{FAXF}{0.75}
 
-{\bf See:}\\
-\pagefrom{ExtensionField}{XF}
-\pagefrom{RetractableTo}{RETRACT}
-
-{\bf Exports:}\\
-\begin{tabular}{lllll}
-\cross{FAXF}{0} &
-\cross{FAXF}{1} &
-\cross{FAXF}{algebraic?} \\
-\cross{FAXF}{associates?} &
-\cross{FAXF}{basis} &
-\cross{FAXF}{characteristic} \\
-\cross{FAXF}{charthRoot} &
-\cross{FAXF}{coerce} &
-\cross{FAXF}{conditionP} \\
-\cross{FAXF}{coordinates} &
-\cross{FAXF}{createNormalElement} &
-\cross{FAXF}{createPrimitiveElement} \\
-\cross{FAXF}{D} &
-\cross{FAXF}{definingPolynomial} &
-\cross{FAXF}{degree} \\
-\cross{FAXF}{differentiate} &
-\cross{FAXF}{dimension} &
-\cross{FAXF}{discreteLog} \\
-\cross{FAXF}{divide} &
-\cross{FAXF}{euclideanSize} &
-\cross{FAXF}{expressIdealMember} \\
-\cross{FAXF}{exquo} &
-\cross{FAXF}{extendedEuclidean} &
-\cross{FAXF}{extensionDegree} \\
-\cross{FAXF}{factor} &
-\cross{FAXF}{factorsOfCyclicGroupSize} &
-\cross{FAXF}{Frobenius} \\
-\cross{FAXF}{gcd} &
-\cross{FAXF}{gcdPolynomial} &
-\cross{FAXF}{generator} \\
-\cross{FAXF}{hash} &
-\cross{FAXF}{index} &
-\cross{FAXF}{inGroundField?} \\
-\cross{FAXF}{init} &
-\cross{FAXF}{inv} &
-\cross{FAXF}{latex} \\
-\cross{FAXF}{lcm} &
-\cross{FAXF}{linearAssociatedExp} &
-\cross{FAXF}{linearAssociatedLog} \\
-\cross{FAXF}{linearAssociatedOrder} &
-\cross{FAXF}{lookup} &
-\cross{FAXF}{minimalPolynomial} \\
-\cross{FAXF}{multiEuclidean} &
-\cross{FAXF}{nextItem} &
-\cross{FAXF}{norm} \\
-\cross{FAXF}{normal?} &
-\cross{FAXF}{normalElement} &
-\cross{FAXF}{one?} \\
-\cross{FAXF}{order} &
-\cross{FAXF}{prime?} &
-\cross{FAXF}{primeFrobenius} \\
-\cross{FAXF}{primitive?} &
-\cross{FAXF}{primitiveElement} &
-\cross{FAXF}{principalIdeal} \\
-\cross{FAXF}{random} &
-\cross{FAXF}{recip} &
-\cross{FAXF}{representationType} \\
-\cross{FAXF}{represents} &
-\cross{FAXF}{retract} &
-\cross{FAXF}{retractIfCan} \\
-\cross{FAXF}{sample} &
-\cross{FAXF}{size} &
-\cross{FAXF}{sizeLess?} \\
-\cross{FAXF}{squareFree} &
-\cross{FAXF}{squareFreePart} &
-\cross{FAXF}{subtractIfCan} \\
-\cross{FAXF}{tableForDiscreteLogarithm} &
-\cross{FAXF}{trace} &
-\cross{FAXF}{transcendenceDegree} \\
-\cross{FAXF}{transcendent?} &
-\cross{FAXF}{unit?} &
-\cross{FAXF}{unitCanonical} \\
-\cross{FAXF}{unitNormal} &
-\cross{FAXF}{zero?} &
-\cross{FAXF}{?*?} \\
-\cross{FAXF}{?**?} &
-\cross{FAXF}{?+?} &
-\cross{FAXF}{?-?} \\
-\cross{FAXF}{-?} &
-\cross{FAXF}{?/?} &
-\cross{FAXF}{?/?} \\
-\cross{FAXF}{?=?} &
-\cross{FAXF}{?\^{}?} &
-\cross{FAXF}{?quo?} \\
-\cross{FAXF}{?rem?} &
-\cross{FAXF}{?\~{}=?} &
-\end{tabular}
-
-{\bf Attributes Exported:}
-\begin{itemize}
-\item {\bf \cross{FAXF}{canonicalUnitNormal}}
-is true if we can choose a canonical representative for each class 
-of associate elements, that is {\tt associates?(a,b)} returns true 
-if and only if {\tt unitCanonical(a) = unitCanonical(b)}.
-\item {\bf \cross{FAXF}{canonicalsClosed}}
-is true if\\
-{\tt unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
-\item {\bf \cross{FAXF}{noZeroDivisors}}
-is true if $x * y \ne 0$ implies both x and y are non-zero.
-\item {\bf \cross{FAXF}{commutative("*")}}
-is true if it has an operation $"*": (D,D) -> D$
-which is commutative.
-\item {\bf \cross{FAXF}{unitsKnown}}
-is true if a monoid (a multiplicative semigroup with a 1) has 
-unitsKnown means that  the operation {\tt recip} can only return 
-``failed'' if its argument is not a unit.
-\item {\bf \cross{FAXF}{leftUnitary}}
-is true if $1 * x = x$ for all x.
-\item {\bf \cross{FAXF}{rightUnitary}}
-is true if $x * 1 = x$ for all x.
-\end{itemize}
-
-These are directly exported but not implemented:
-\begin{verbatim}
- basis : () -> Vector %               
- basis : PositiveInteger -> Vector %
- coordinates : % -> Vector F          
- definingPolynomial : () -> SparseUnivariatePolynomial F
- generator : () -> % if F has FINITE
- minimalPolynomial : (%,PositiveInteger) ->
-    SparseUnivariatePolynomial % 
-      if F has FINITE
- normalElement : () -> % if F has FINITE
-\end{verbatim}
-
-These are implemented by this category:
-\begin{verbatim}
- algebraic? : % -> Boolean            
- charthRoot : % -> Union(%,"failed") 
-     if F has CHARNZ or F has FINITE
- coordinates : Vector % -> Matrix F
- createNormalElement : () -> % if F has FINITE
- degree : % -> PositiveInteger
- dimension : () -> CardinalNumber     
- extensionDegree : () -> PositiveInteger
- linearAssociatedExp : (%,SparseUnivariatePolynomial F) -> % 
-     if F has FINITE
- linearAssociatedLog : (%,%) ->
-    Union(SparseUnivariatePolynomial F,"failed") 
-      if F has FINITE
- linearAssociatedLog : % -> SparseUnivariatePolynomial F 
-     if F has FINITE
- linearAssociatedOrder : % -> SparseUnivariatePolynomial F 
-     if F has FINITE
- minimalPolynomial : % -> SparseUnivariatePolynomial F
- norm : % -> F                        
- norm : (%,PositiveInteger) -> % if F has FINITE
- normal? : % -> Boolean if F has FINITE
- represents : Vector F -> %           
- size : () -> NonNegativeInteger if F has FINITE
- trace : % -> F                       
- trace : (%,PositiveInteger) -> % if F has FINITE
- transcendenceDegree : () -> NonNegativeInteger
- transcendent? : % -> Boolean
-\end{verbatim}
-
-These exports come from \refto{ExtensionField}(F:Field):
-\begin{verbatim}
- 0 : () -> %
- 1 : () -> %                          
- associates? : (%,%) -> Boolean
- characteristic : () -> NonNegativeInteger
- coerce : F -> %
- coerce : % -> %
- coerce : Integer -> %                
- coerce : % -> OutputForm
- coerce : Fraction Integer -> %       
- discreteLog : (%,%) ->
-    Union(NonNegativeInteger,"failed")
-      if F has CHARNZ or F has FINITE
- divide : (%,%) -> Record(quotient: %,remainder: %)
- euclideanSize : % -> NonNegativeInteger
- expressIdealMember : (List %,%) -> Union(List %,"failed")
- exquo : (%,%) -> Union(%,"failed")
- extendedEuclidean : (%,%,%) ->
-    Union(Record(coef1: %,coef2: %),"failed")
- extendedEuclidean : (%,%) ->
-    Record(coef1: %,coef2: %,generator: %)
- factor : % -> Factored %
- Frobenius : (%,NonNegativeInteger) -> % if F has FINITE
- Frobenius : % -> % if F has FINITE
- gcd : List % -> %                    
- gcd : (%,%) -> %
- gcdPolynomial : (SparseUnivariatePolynomial %,
-                  SparseUnivariatePolynomial %) ->
-                     SparseUnivariatePolynomial %
- hash : % -> SingleInteger            
- inGroundField? : % -> Boolean
- inv : % -> %                         
- latex : % -> String
- lcm : List % -> %                    
- lcm : (%,%) -> %
- multiEuclidean : (List %,%) -> Union(List %,"failed")
- one? : % -> Boolean
- order : % -> OnePointCompletion PositiveInteger
-      if F has CHARNZ or F has FINITE
- prime? : % -> Boolean                
- primeFrobenius : % -> % 
-     if F has CHARNZ or F has FINITE
- primeFrobenius : (%,NonNegativeInteger) -> % 
-     if F has CHARNZ or F has FINITE
- principalIdeal : List % -> Record(coef: List %,generator: %)
- recip : % -> Union(%,"failed")       
- retract : % -> F
- retractIfCan : % -> Union(F,"failed")
- sample : () -> %                     
- squareFree : % -> Factored %         
- squareFreePart : % -> %
- sizeLess? : (%,%) -> Boolean
- subtractIfCan : (%,%) -> Union(%,"failed")
- unit? : % -> Boolean                 
- unitCanonical : % -> %
- unitNormal : % -> Record(unit: %,canonical: %,associate: %)
- zero? : % -> Boolean                 
- ?/? : (%,%) -> %
- ?+? : (%,%) -> %
- ?=? : (%,%) -> Boolean               
- ?~=? : (%,%) -> Boolean
- ?*? : (%,%) -> %                     
- ?*? : (Integer,%) -> %
- ?*? : (PositiveInteger,%) -> %       
- ?*? : (NonNegativeInteger,%) -> %
- ?*? : (Fraction Integer,%) -> %      
- ?*? : (%,Fraction Integer) -> %
- ?*? : (F,%) -> %                     
- ?*? : (%,F) -> %
- ?-? : (%,%) -> %                     
- -? : % -> %
- ?**? : (%,NonNegativeInteger) -> %
- ?**? : (%,PositiveInteger) -> %      
- ?**? : (%,Integer) -> %
- ?^? : (%,Integer) -> %               
- ?^? : (%,PositiveInteger) -> %
- ?^? : (%,NonNegativeInteger) -> %
- ?quo? : (%,%) -> %
- ?rem? : (%,%) -> %
- ?/? : (%,F) -> %                     
-\end{verbatim}
-
-These exports come from \refto{RetractableTo}(F:Field):
-\begin{verbatim}
-\end{verbatim}
-
-These exports come from \refto{FiniteFieldCategory}():
-\begin{verbatim}
- charthRoot : % -> % if F has FINITE
- conditionP : Matrix % -> Union(Vector %,"failed") 
-     if F has FINITE
- createPrimitiveElement : () -> % if F has FINITE
- D : % -> % if F has FINITE
- D : (%,NonNegativeInteger) -> % if F has FINITE
- differentiate : % -> % if F has FINITE
- differentiate : (%,NonNegativeInteger) -> % 
-     if F has FINITE
- discreteLog : % -> NonNegativeInteger if F has FINITE
- factorsOfCyclicGroupSize : () ->
-    List Record(factor: Integer,exponent: Integer) 
-      if F has FINITE
- index : PositiveInteger -> % if F has FINITE
- init : () -> % if F has FINITE
- lookup : % -> PositiveInteger if F has FINITE
- nextItem : % -> Union(%,"failed") if F has FINITE
- order : % -> PositiveInteger if F has FINITE
- primitive? : % -> Boolean if F has FINITE
- primitiveElement : () -> % if F has FINITE
- random : () -> % if F has FINITE
- representationType : () ->
-    Union("prime",polynomial,normal,cyclic) 
-      if F has FINITE
- tableForDiscreteLogarithm : Integer ->
-    Table(PositiveInteger,NonNegativeInteger) 
-      if F has FINITE
-\end{verbatim}
-
-
-<<category FAXF FiniteAlgebraicExtensionField>>=
-)abbrev category FAXF FiniteAlgebraicExtensionField
-++ Author: J. Grabmeier, A. Scheerhorn
-++ Date Created: 11 March 1991
-++ Date Last Updated: 31 March 1991
-++ Basic Operations: _+, _*, extensionDegree,
-++ Related Constructors:
-++ Also See:
-++ AMS Classifications:
-++ Keywords: field, extension field, algebraic extension, finite extension
-++ References:
-++  R.Lidl, H.Niederreiter: Finite Field, Encycoldia of Mathematics and
-++  Its Applications, Vol. 20, Cambridge Univ. Press, 1983, 
-++  ISBN 0 521 30240 4 J. Grabmeier, A. Scheerhorn: Finite Fields in AXIOM.
-++  AXIOM Technical Report Series, ATR/5 NP2522.
-++ Description:
-++  FiniteAlgebraicExtensionField {\em F} is the category of fields
-++  which are finite algebraic extensions of the field {\em F}.
-++  If {\em F} is finite then any finite algebraic extension of {\em F} 
-++  is finite, too. Let {\em K} be a finite algebraic extension of the 
-++  finite field {\em F}. The exponentiation of elements of {\em K} 
-++  defines a Z-module structure on the multiplicative group of {\em K}. 
-++  The additive group of {\em K} becomes a module over the ring of 
-++  polynomials over {\em F} via the operation 
-++  \spadfun{linearAssociatedExp}(a:K,f:SparseUnivariatePolynomial F)
-++  which is linear over {\em F}, i.e. for elements {\em a} from {\em K},
-++  {\em c,d} from {\em F} and {\em f,g} univariate polynomials over {\em F}
-++  we have \spadfun{linearAssociatedExp}(a,cf+dg) equals {\em c} times
-++  \spadfun{linearAssociatedExp}(a,f) plus {\em d} times
-++  \spadfun{linearAssociatedExp}(a,g).
-++  Therefore \spadfun{linearAssociatedExp} is defined completely by
-++  its action on  monomials from {\em F[X]}:
-++  \spadfun{linearAssociatedExp}(a,monomial(1,k)\$SUP(F)) is defined to be
-++  \spadfun{Frobenius}(a,k) which is {\em a**(q**k)} where {\em q=size()\$F}.
-++  The operations order and discreteLog associated with the multiplicative
-++  exponentiation have additive analogues associated to the operation
-++  \spadfun{linearAssociatedExp}. These are the functions
-++  \spadfun{linearAssociatedOrder} and \spadfun{linearAssociatedLog},
-++  respectively.
-
-FiniteAlgebraicExtensionField(F : Field) : Category == _
-  Join(ExtensionField F, RetractableTo F) with
-  -- should be unified with algebras
-  -- Join(ExtensionField F, FramedAlgebra F, RetractableTo F) with
-    basis : () -> Vector $
-      ++ basis() returns a fixed basis of \$ as \spad{F}-vectorspace.
-    basis : PositiveInteger -> Vector $
-      ++ basis(n) returns a fixed basis of a subfield of \$ as
-      ++ \spad{F}-vectorspace.
-    coordinates : $ -> Vector F
-      ++ coordinates(a) returns the coordinates of \spad{a} with respect
-      ++ to the fixed \spad{F}-vectorspace basis.
-    coordinates : Vector $ -> Matrix F
-      ++ coordinates([v1,...,vm]) returns the coordinates of the
-      ++ vi's with to the fixed basis.  The coordinates of vi are
-      ++ contained in the ith row of the matrix returned by this
-      ++ function.
-    represents:  Vector F -> $
-      ++ represents([a1,..,an]) returns \spad{a1*v1 + ... + an*vn}, where
-      ++ v1,...,vn are the elements of the fixed basis.
-    minimalPolynomial: $ -> SparseUnivariatePolynomial F
-      ++ minimalPolynomial(a) returns the minimal polynomial of an
-      ++ element \spad{a} over the ground field F.
-    definingPolynomial: () -> SparseUnivariatePolynomial F
-      ++ definingPolynomial() returns the polynomial used to define
-      ++ the field extension.
-    extensionDegree : () ->  PositiveInteger
-      ++ extensionDegree() returns the degree of field extension.
-    degree : $ -> PositiveInteger
-      ++ degree(a) returns the degree of the minimal polynomial of an
-      ++ element \spad{a} over the ground field F.
-    norm: $  -> F
-      ++ norm(a) computes the norm of \spad{a} with respect to the
-      ++ field considered as an algebra with 1 over the ground field F.
-    trace: $ -> F
-      ++ trace(a) computes the trace of \spad{a} with respect to
-      ++ the field considered as an algebra with 1 over the ground field F.
-    if F has Finite then
-      FiniteFieldCategory
-      minimalPolynomial: ($,PositiveInteger) -> SparseUnivariatePolynomial $
-        ++ minimalPolynomial(x,n) computes the minimal polynomial of x over
-        ++ the field of extension degree n over the ground field F.
-      norm: ($,PositiveInteger)  -> $
-        ++ norm(a,d) computes the norm of \spad{a} with respect to the field
-        ++ of extension degree d over the ground field of size.
-        ++ Error: if d does not divide the extension degree of \spad{a}.
-        ++ Note: norm(a,d) = reduce(*,[a**(q**(d*i)) for i in 0..n/d])
-      trace: ($,PositiveInteger)   -> $
-        ++ trace(a,d) computes the trace of \spad{a} with respect to the
-        ++ field of extension degree d over the ground field of size q.
-        ++ Error: if d does not divide the extension degree of \spad{a}.
-        ++ Note: \spad{trace(a,d)=reduce(+,[a**(q**(d*i)) for i in 0..n/d])}.
-      createNormalElement: () -> $
-        ++ createNormalElement() computes a normal element over the ground
-        ++ field F, that is,
-        ++ \spad{a**(q**i), 0 <= i < extensionDegree()} is an F-basis,
-        ++ where \spad{q = size()\$F}.
-        ++ Reference: Such an element exists Lidl/Niederreiter: Theorem 2.35.
-      normalElement: () -> $
-        ++ normalElement() returns a element, normal over the ground field F,
-        ++ i.e. \spad{a**(q**i), 0 <= i < extensionDegree()} is an F-basis,
-        ++ where \spad{q = size()\$F}.
-        ++ At the first call, the element is computed by
-        ++ \spadfunFrom{createNormalElement}{FiniteAlgebraicExtensionField}
-        ++ then cached in a global variable.
-        ++ On subsequent calls, the element is retrieved by referencing the
-        ++ global variable.
-      normal?: $ -> Boolean
-        ++ normal?(a) tests whether the element \spad{a} is normal over the
-        ++ ground field F, i.e.
-        ++ \spad{a**(q**i), 0 <= i <= extensionDegree()-1} is an F-basis,
-        ++ where \spad{q = size()\$F}.
-        ++ Implementation according to Lidl/Niederreiter: Theorem 2.39.
-      generator: () -> $
-        ++ generator() returns a root of the defining polynomial.
-        ++ This element generates the field as an algebra over the ground
-        ++ field.
-      linearAssociatedExp:($,SparseUnivariatePolynomial F) -> $
-        ++ linearAssociatedExp(a,f) is linear over {\em F}, i.e.
-        ++ for elements {\em a} from {\em \$}, {\em c,d} form {\em F} and
-        ++ {\em f,g} univariate polynomials over {\em F} we have
-        ++ \spadfun{linearAssociatedExp}(a,cf+dg) equals {\em c} times
-        ++ \spadfun{linearAssociatedExp}(a,f) plus {\em d} times
-        ++ \spadfun{linearAssociatedExp}(a,g). Therefore
-        ++ \spadfun{linearAssociatedExp} is defined completely by its 
-        ++ action on monomials from {\em F[X]}:
-        ++ \spadfun{linearAssociatedExp}(a,monomial(1,k)\$SUP(F)) is 
-        ++ defined to be \spadfun{Frobenius}(a,k) which is {\em a**(q**k)},
-        ++ where {\em q=size()\$F}.
-      linearAssociatedOrder: $ -> SparseUnivariatePolynomial F
-        ++ linearAssociatedOrder(a) retruns the monic polynomial {\em g} of
-        ++ least degree, such that \spadfun{linearAssociatedExp}(a,g) is 0.
-      linearAssociatedLog: $ -> SparseUnivariatePolynomial F
-        ++ linearAssociatedLog(a) returns a polynomial {\em g}, such that
-        ++ \spadfun{linearAssociatedExp}(normalElement(),g) equals {\em a}.
-      linearAssociatedLog: ($,$) -> _
-        Union(SparseUnivariatePolynomial F,"failed")
-        ++ linearAssociatedLog(b,a) returns a polynomial {\em g}, such 
-        ++ that the \spadfun{linearAssociatedExp}(b,g) equals {\em a}.
-        ++ If there is no such polynomial {\em g}, then
-        ++ \spadfun{linearAssociatedLog} fails.
-  add
-    I   ==> Integer
-    PI  ==> PositiveInteger
-    NNI ==> NonNegativeInteger
-    SUP ==> SparseUnivariatePolynomial
-    DLP ==> DiscreteLogarithmPackage
-
-    represents(v) ==
-      a:$:=0
-      b:=basis()
-      for i in 1..extensionDegree()@PI repeat
-        a:=a+(v.i)*(b.i)
-      a
-
-    transcendenceDegree() == 0$NNI
-
-    dimension() == (#basis()) ::NonNegativeInteger::CardinalNumber
-
-    coordinates(v:Vector $) ==
-      m := new(#v, extensionDegree(), 0)$Matrix(F)
-      for i in minIndex v .. maxIndex v for j in minRowIndex m .. repeat
-        setRow_!(m, j, coordinates qelt(v, i))
-      m
-
-    algebraic? a == true
-
-    transcendent? a == false
-
--- This definition is a duplicate and has been removed
---    extensionDegree():OnePointCompletion(PositiveInteger) ==
---      (#basis()) :: PositiveInteger::OnePointCompletion(PositiveInteger)
-
-    extensionDegree() == (#basis()) :: PositiveInteger
-
--- These definitions are duplicates and have been removed
---    degree(a):OnePointCompletion(PositiveInteger) ==
---      degree(a)@PI::OnePointCompletion(PositiveInteger)
-
-    -- degree a == degree(minimalPolynomial a)$SUP(F) :: PI
-
-    trace a ==
-      b := basis()
-      abs : F := 0
-      for i in 1..#b repeat
-        abs := abs + coordinates(a*b.i).i
-      abs
-
-    norm a ==
-      b := basis()
-      m := new(#b,#b, 0)$Matrix(F)
-      for i in 1..#b repeat
-        setRow_!(m,i, coordinates(a*b.i))
-      determinant(m)
-
-    if F has Finite then
-      linearAssociatedExp(x,f) ==
-        erg:$:=0
-        y:=x
-        for i in 0..degree(f) repeat
-          erg:=erg + coefficient(f,i) * y
-          y:=Frobenius(y)
-        erg
-
-      linearAssociatedLog(b,x) ==
-        x=0 => 0
-        l:List List F:=[entries coordinates b]
-        a:$:=b
-        extdeg:NNI:=extensionDegree()@PI
-        for i in 2..extdeg repeat
-          a:=Frobenius(a)
-          l:=concat(l,entries coordinates a)$(List List F)
-        l:=concat(l,entries coordinates x)$(List List F)
-        m1:=rowEchelon transpose matrix(l)$(Matrix F)
-        v:=zero(extdeg)$(Vector F)
-        rown:I:=1
-        for i in 1..extdeg repeat
-          if qelt(m1,rown,i) = 1$F then
-            v.i:=qelt(m1,rown,extdeg+1)
-            rown:=rown+1
-        p:=+/[monomial(v.(i+1),i::NNI) for i in 0..(#v-1)]
-        p=0 =>
-         messagePrint("linearAssociatedLog: second argument not in_
-                       group generated by first argument")$OutputForm
-         "failed"
-        p
-
-      linearAssociatedLog(x) == linearAssociatedLog(normalElement(),x) ::
-                              SparseUnivariatePolynomial(F)
-
-      linearAssociatedOrder(x) ==
-        x=0 => 0
-        l:List List F:=[entries coordinates x]
-        a:$:=x
-        for i in 1..extensionDegree()@PI repeat
-          a:=Frobenius(a)
-          l:=concat(l,entries coordinates a)$(List List F)
-        v:=first nullSpace transpose matrix(l)$(Matrix F)
-        +/[monomial(v.(i+1),i::NNI) for i in 0..(#v-1)]
-
-      charthRoot(x):Union($,"failed") ==
-        (charthRoot(x)@$)::Union($,"failed")
-      -- norm(e) == norm(e,1) pretend F
-      -- trace(e) == trace(e,1) pretend F
-
-      minimalPolynomial(a,n) ==
-        extensionDegree()@PI rem n ^= 0 =>
-          error "minimalPolynomial: 2. argument must divide extension degree"
-        f:SUP $:=monomial(1,1)$(SUP $) - monomial(a,0)$(SUP $)
-        u:$:=Frobenius(a,n)
-        while not(u = a) repeat
-          f:=f * (monomial(1,1)$(SUP $) - monomial(u,0)$(SUP $))
-          u:=Frobenius(u,n)
-        f
-
-      norm(e,s) ==
-        qr := divide(extensionDegree(), s)
-        zero?(qr.remainder) =>
-          pow := (size()-1) quo (size()$F ** s - 1)
-          e ** (pow::NonNegativeInteger)
-        error "norm: second argument must divide degree of extension"
-
-      trace(e,s) ==
-        qr:=divide(extensionDegree(),s)
-        q:=size()$F
-        zero?(qr.remainder) =>
-          a:$:=0
-          for i in 0..qr.quotient-1 repeat
-            a:=a + e**(q**(s*i))
-          a
-        error "trace: second argument must divide degree of extension"
-
-      size() == size()$F ** extensionDegree()
-
-      createNormalElement() ==
-        characteristic() = size() => 1
-        res : $
-        for i in 1.. repeat
-          res := index(i :: PI)
-          not inGroundField? res =>
-            normal? res => return res
-        -- theorem: there exists a normal element, this theorem is
-        -- unknown to the compiler
-        res
-
-      normal?(x:$) ==
-        p:SUP $:=(monomial(1,extensionDegree()) - monomial(1,0))@(SUP $)
-        f:SUP $:= +/[monomial(Frobenius(x,i),i)$(SUP $) _
-                   for i in 0..extensionDegree()-1]
-        gcd(p,f) = 1 => true
-        false
-
-      degree a ==
-        y:$:=Frobenius a
-        deg:PI:=1
-        while y^=a repeat
-          y := Frobenius(y)
-          deg:=deg+1
-        deg
-
-@
-<<FAXF.dotabb>>=
-"FAXF"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=FAXF"];
-"FAXF" -> "XF"
-"FAXF" -> "RETRACT"
-
-@
-<<FAXF.dotfull>>=
-"FiniteAlgebraicExtensionField(a:Field)"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=FAXF"];
-"FiniteAlgebraicExtensionField(a:Field)" -> "ExtensionField(a:Field)"
-"FiniteAlgebraicExtensionField(a:Field)" -> "RetractableTo(a:Field)"
-
-@
-<<FAXF.dotpic>>=
-digraph pic {
- fontsize=10;
- bgcolor="#FFFF66";
- node [shape=box, color=white, style=filled];
-
-"FiniteAlgebraicExtensionField(a:Field)"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=FAXF"];
-"FiniteAlgebraicExtensionField(a:Field)" -> "ExtensionField(a:Field)"
-"FiniteAlgebraicExtensionField(a:Field)" -> "RetractableTo(Field)"
-
-"ExtensionField(a:Field)" [color=lightblue];
-"ExtensionField(a:Field)" -> "Field()"
-"ExtensionField(a:Field)" -> "RetractableTo(Field)"
-"ExtensionField(a:Field)" -> "VectorSpace(a:Field)"
-
-"Field()" [color=lightblue];
-"Field()" -> "EuclideanDomain()"
-"Field()" -> "UniqueFactorizationDomain()"
-"Field()" -> "DIVRING..."
-
-"EuclideanDomain()" [color=lightblue];
-"EuclideanDomain()" -> "PrincipalIdealDomain()"
-
-"UniqueFactorizationDomain()" [color=lightblue];
-"UniqueFactorizationDomain()" -> "GCDDOM..."
-
-"PrincipalIdealDomain()" [color=lightblue];
-"PrincipalIdealDomain()" -> "GCDDOM..."
-
-"RetractableTo(Field)" [color=seagreen];
-"RetractableTo(Field)" -> "RetractableTo(a:Type)"
-
-"RetractableTo(a:Type)" [color=lightblue];
-"RetractableTo(a:Type)" -> "Category"
-
-"VectorSpace(a:Field)" [color=lightblue];
-"VectorSpace(a:Field)" -> "MODULE..."
-
-"MODULE..." [color=lightblue];
-"DIVRING..." [color=lightblue];
-"GCDDOM..." [color=lightblue];
-"Category" [color=lightblue];
-}
-
-@
 \chapter{The bootstrap code}
 \section{ABELGRP.lsp BOOTSTRAP} 
 {\bf ABELGRP} depends on a chain of
@@ -44779,6 +45476,7 @@ Note that this code is not included in the generated catdef.spad file.
 <<category ABELGRP AbelianGroup>>
 <<category ABELMON AbelianMonoid>>
 <<category ABELSG AbelianSemiGroup>>
+<<category ACF AlgebraicallyClosedField>>
 <<category AGG Aggregate>>
 <<category AHYP ArcHyperbolicFunctionCategory>>
 <<category ALAGG AssociationListAggregate>>
@@ -44939,6 +45637,7 @@ digraph dotabb {
 <<ABELGRP.dotabb>>
 <<ABELMON.dotabb>>
 <<ABELSG.dotabb>>
+<<ACF.dotabb>>
 <<AGG.dotabb>>
 <<AHYP.dotabb>>
 <<ALAGG.dotabb>>
@@ -45100,6 +45799,7 @@ digraph dotfull {
 <<ABELGRP.dotfull>>
 <<ABELMON.dotfull>>
 <<ABELSG.dotfull>>
+<<ACF.dotfull>>
 <<AGG.dotfull>>
 <<AHYP.dotfull>>
 <<ALAGG.dotfull>>
diff --git a/books/ps/v102algebraicallyclosedfield.ps b/books/ps/v102algebraicallyclosedfield.ps
new file mode 100644
index 0000000..426104f
--- /dev/null
+++ b/books/ps/v102algebraicallyclosedfield.ps
@@ -0,0 +1,632 @@
+%!PS-Adobe-2.0
+%%Creator: dot version 2.8 (Thu Sep 14 20:34:11 UTC 2006)
+%%For: (root) root
+%%Title: pic
+%%Pages: (atend)
+%%BoundingBox: 36 36 490 368
+%%EndComments
+save
+%%BeginProlog
+/DotDict 200 dict def
+DotDict begin
+
+/setupLatin1 {
+mark
+/EncodingVector 256 array def
+ EncodingVector 0
+
+ISOLatin1Encoding 0 255 getinterval putinterval
+EncodingVector 45 /hyphen put
+
+% Set up ISO Latin 1 character encoding
+/starnetISO {
+        dup dup findfont dup length dict begin
+        { 1 index /FID ne { def }{ pop pop } ifelse
+        } forall
+        /Encoding EncodingVector def
+        currentdict end definefont
+} def
+/Times-Roman starnetISO def
+/Times-Italic starnetISO def
+/Times-Bold starnetISO def
+/Times-BoldItalic starnetISO def
+/Helvetica starnetISO def
+/Helvetica-Oblique starnetISO def
+/Helvetica-Bold starnetISO def
+/Helvetica-BoldOblique starnetISO def
+/Courier starnetISO def
+/Courier-Oblique starnetISO def
+/Courier-Bold starnetISO def
+/Courier-BoldOblique starnetISO def
+cleartomark
+} bind def
+
+%%BeginResource: procset graphviz 0 0
+/coord-font-family /Times-Roman def
+/default-font-family /Times-Roman def
+/coordfont coord-font-family findfont 8 scalefont def
+
+/InvScaleFactor 1.0 def
+/set_scale {
+	dup 1 exch div /InvScaleFactor exch def
+	dup scale
+} bind def
+
+% styles
+/solid { [] 0 setdash } bind def
+/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def
+/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def
+/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def
+/bold { 2 setlinewidth } bind def
+/filled { } bind def
+/unfilled { } bind def
+/rounded { } bind def
+/diagonals { } bind def
+
+% hooks for setting color 
+/nodecolor { sethsbcolor } bind def
+/edgecolor { sethsbcolor } bind def
+/graphcolor { sethsbcolor } bind def
+/nopcolor {pop pop pop} bind def
+
+/beginpage {	% i j npages
+	/npages exch def
+	/j exch def
+	/i exch def
+	/str 10 string def
+	npages 1 gt {
+		gsave
+			coordfont setfont
+			0 0 moveto
+			(\() show i str cvs show (,) show j str cvs show (\)) show
+		grestore
+	} if
+} bind def
+
+/set_font {
+	findfont exch
+	scalefont setfont
+} def
+
+% draw aligned label in bounding box aligned to current point
+/alignedtext {			% width adj text
+	/text exch def
+	/adj exch def
+	/width exch def
+	gsave
+		width 0 gt {
+			text stringwidth pop adj mul 0 rmoveto
+		} if
+		[] 0 setdash
+		text show
+	grestore
+} def
+
+/boxprim {				% xcorner ycorner xsize ysize
+		4 2 roll
+		moveto
+		2 copy
+		exch 0 rlineto
+		0 exch rlineto
+		pop neg 0 rlineto
+		closepath
+} bind def
+
+/ellipse_path {
+	/ry exch def
+	/rx exch def
+	/y exch def
+	/x exch def
+	matrix currentmatrix
+	newpath
+	x y translate
+	rx ry scale
+	0 0 1 0 360 arc
+	setmatrix
+} bind def
+
+/endpage { showpage } bind def
+/showpage { } def
+
+/layercolorseq
+	[	% layer color sequence - darkest to lightest
+		[0 0 0]
+		[.2 .8 .8]
+		[.4 .8 .8]
+		[.6 .8 .8]
+		[.8 .8 .8]
+	]
+def
+
+/layerlen layercolorseq length def
+
+/setlayer {/maxlayer exch def /curlayer exch def
+	layercolorseq curlayer 1 sub layerlen mod get
+	aload pop sethsbcolor
+	/nodecolor {nopcolor} def
+	/edgecolor {nopcolor} def
+	/graphcolor {nopcolor} def
+} bind def
+
+/onlayer { curlayer ne {invis} if } def
+
+/onlayers {
+	/myupper exch def
+	/mylower exch def
+	curlayer mylower lt
+	curlayer myupper gt
+	or
+	{invis} if
+} def
+
+/curlayer 0 def
+
+%%EndResource
+%%EndProlog
+%%BeginSetup
+14 default-font-family set_font
+1 setmiterlimit
+% /arrowlength 10 def
+% /arrowwidth 5 def
+
+% make sure pdfmark is harmless for PS-interpreters other than Distiller
+/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse
+% make '<<' and '>>' safe on PS Level 1 devices
+/languagelevel where {pop languagelevel}{1} ifelse
+2 lt {
+    userdict (<<) cvn ([) cvn load put
+    userdict (>>) cvn ([) cvn load put
+} if
+
+%%EndSetup
+%%Page: 1 1
+%%PageBoundingBox: 36 36 490 368
+%%PageOrientation: Portrait
+gsave
+36 36 454 332 boxprim clip newpath
+36 36 translate
+0 0 1 beginpage
+1.0000 set_scale
+4 4 translate 0 rotate
+0.167 0.600 1.000 graphcolor
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 330 lineto
+452 330 lineto
+452 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 330 lineto
+452 330 lineto
+452 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% AlgebraicallyClosedField()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 403 324 moveto
+233 324 lineto
+233 288 lineto
+403 288 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 403 324 moveto
+233 324 lineto
+233 288 lineto
+403 288 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+241 301 moveto
+(AlgebraicallyClosedField\(\))
+[10.08 3.84 6.72 6.24 6.96 4.8 6.24 3.84 6.24 6.24 3.84 3.6 6.96 9.36 3.84 6.96 5.52 6.24 6.96 7.44 3.84 6.24 3.84 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% Field()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 278 252 moveto
+224 252 lineto
+224 216 lineto
+278 216 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 278 252 moveto
+224 252 lineto
+224 216 lineto
+278 216 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+232 229 moveto
+(Field\(\))
+[7.44 3.84 6.24 3.84 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% AlgebraicallyClosedField()->Field()
+newpath 301 288 moveto
+293 279 284 269 275 260 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 277 257 moveto
+268 252 lineto
+272 262 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 277 257 moveto
+268 252 lineto
+272 262 lineto
+closepath
+stroke
+end grestore
+% RadicalCategory()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 446 252 moveto
+326 252 lineto
+326 216 lineto
+446 216 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 446 252 moveto
+326 252 lineto
+326 216 lineto
+446 216 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+334 229 moveto
+(RadicalCategory\(\))
+[9.36 6.24 6.96 3.84 6.24 6.24 3.84 9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% AlgebraicallyClosedField()->RadicalCategory()
+newpath 335 288 moveto
+343 279 353 269 362 260 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 365 262 moveto
+369 252 lineto
+360 257 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 365 262 moveto
+369 252 lineto
+360 257 lineto
+closepath
+stroke
+end grestore
+% EuclideanDomain()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 161 180 moveto
+35 180 lineto
+35 144 lineto
+161 144 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 161 180 moveto
+35 180 lineto
+35 144 lineto
+161 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+42 157 moveto
+(EuclideanDomain\(\))
+[8.64 6.96 6.24 3.84 3.84 6.96 6.24 6.24 6.96 10.08 6.96 10.8 6.24 3.84 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% Field()->EuclideanDomain()
+newpath 224 221 moveto
+203 211 171 197 145 184 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 147 181 moveto
+136 180 lineto
+144 187 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 147 181 moveto
+136 180 lineto
+144 187 lineto
+closepath
+stroke
+end grestore
+% UniqueFactorizationDomain()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 352 108 moveto
+168 108 lineto
+168 72 lineto
+352 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 352 108 moveto
+168 108 lineto
+168 72 lineto
+352 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+175 85 moveto
+(UniqueFactorizationDomain\(\))
+[9.6 6.96 3.84 6.72 6.96 6.24 7.2 6.24 6.24 3.84 6.96 5.04 3.84 6.24 6.24 3.84 3.84 6.96 6.96 10.08 6.96 10.8 6.24 3.84 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% Field()->UniqueFactorizationDomain()
+newpath 252 216 moveto
+252 197 254 168 255 144 curveto
+256 136 256 126 257 118 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 260 118 moveto
+258 108 lineto
+254 118 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 260 118 moveto
+258 108 lineto
+254 118 lineto
+closepath
+stroke
+end grestore
+% DIVRING...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 350 180 moveto
+264 180 lineto
+264 144 lineto
+350 144 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 350 180 moveto
+264 180 lineto
+264 144 lineto
+350 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+271 157 moveto
+(DIVRING...)
+[10.08 4.56 10.08 9.36 4.56 9.84 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Field()->DIVRING...
+newpath 265 216 moveto
+272 208 280 197 287 188 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 290 190 moveto
+293 180 lineto
+284 186 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 290 190 moveto
+293 180 lineto
+284 186 lineto
+closepath
+stroke
+end grestore
+% Category
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 436 180 moveto
+368 180 lineto
+368 144 lineto
+436 144 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 436 180 moveto
+368 180 lineto
+368 144 lineto
+436 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+376 157 moveto
+(Category)
+[9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96]
+xshow
+end grestore
+end grestore
+% RadicalCategory()->Category
+newpath 390 216 moveto
+392 208 394 199 396 190 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 399 190 moveto
+398 180 lineto
+393 189 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 399 190 moveto
+398 180 lineto
+393 189 lineto
+closepath
+stroke
+end grestore
+% PrincipalIdealDomain()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 150 108 moveto
+0 108 lineto
+0 72 lineto
+150 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 150 108 moveto
+0 108 lineto
+0 72 lineto
+150 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+8 85 moveto
+(PrincipalIdealDomain\(\))
+[7.68 5.04 3.84 6.96 6.24 3.84 6.96 6.24 3.84 4.56 6.96 6.24 6.24 3.84 10.08 6.96 10.8 6.24 3.84 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% EuclideanDomain()->PrincipalIdealDomain()
+newpath 92 144 moveto
+89 136 86 127 84 118 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 87 117 moveto
+81 108 lineto
+81 119 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 87 117 moveto
+81 108 lineto
+81 119 lineto
+closepath
+stroke
+end grestore
+% GCDDOM...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 212 36 moveto
+122 36 lineto
+122 0 lineto
+212 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 212 36 moveto
+122 36 lineto
+122 0 lineto
+212 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+130 13 moveto
+(GCDDOM...)
+[10.08 9.36 10.08 10.08 10.08 12.48 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% UniqueFactorizationDomain()->GCDDOM...
+newpath 237 72 moveto
+226 63 211 52 198 42 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 200 39 moveto
+190 36 lineto
+196 45 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 200 39 moveto
+190 36 lineto
+196 45 lineto
+closepath
+stroke
+end grestore
+% PrincipalIdealDomain()->GCDDOM...
+newpath 98 72 moveto
+109 63 124 52 136 42 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 138 45 moveto
+144 36 lineto
+134 39 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 138 45 moveto
+144 36 lineto
+134 39 lineto
+closepath
+stroke
+end grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
diff --git a/books/ps/v102monogenicalgebra.ps b/books/ps/v102monogenicalgebra.ps
index ceed5d3..960f362 100644
--- a/books/ps/v102monogenicalgebra.ps
+++ b/books/ps/v102monogenicalgebra.ps
@@ -3,7 +3,7 @@
 %%For: (root) root
 %%Title: pic
 %%Pages: (atend)
-%%BoundingBox: 36 36 564 152
+%%BoundingBox: 36 36 934 152
 %%EndComments
 save
 %%BeginProlog
@@ -180,10 +180,10 @@ def
 
 %%EndSetup
 %%Page: 1 1
-%%PageBoundingBox: 36 36 564 152
+%%PageBoundingBox: 36 36 934 152
 %%PageOrientation: Portrait
 gsave
-36 36 528 116 boxprim clip newpath
+36 36 898 116 boxprim clip newpath
 36 36 translate
 0 0 1 beginpage
 1.0000 set_scale
@@ -192,15 +192,15 @@ gsave
 0.167 0.600 1.000 graphcolor
 newpath -6 -6 moveto
 -6 114 lineto
-526 114 lineto
-526 -6 lineto
+896 114 lineto
+896 -6 lineto
 closepath
 fill
 0.167 0.600 1.000 graphcolor
 newpath -6 -6 moveto
 -6 114 lineto
-526 114 lineto
-526 -6 lineto
+896 114 lineto
+896 -6 lineto
 closepath
 stroke
 0.000 0.000 0.000 graphcolor
@@ -210,22 +210,22 @@ gsave 10 dict begin
 filled
 0.537 0.247 0.902 nodecolor
 0.537 0.247 0.902 nodecolor
-newpath 495 108 moveto
-45 108 lineto
-45 72 lineto
-495 72 lineto
+newpath 704 108 moveto
+254 108 lineto
+254 72 lineto
+704 72 lineto
 closepath
 fill
 0.537 0.247 0.902 nodecolor
-newpath 495 108 moveto
-45 108 lineto
-45 72 lineto
-495 72 lineto
+newpath 704 108 moveto
+254 108 lineto
+254 72 lineto
+704 72 lineto
 closepath
 stroke
 gsave 10 dict begin
 0.000 0.000 0.000 nodecolor
-52 85 moveto
+261 85 moveto
 (MonogenicAlgebra\(a:CommutativeRing,b:UnivariatePolynomialCategory\(a\)\))
 [12.48 6.96 6.96 6.96 6.72 6.24 6.96 3.84 6.24 10.08 3.84 6.72 6.24 6.96 4.8 6.24 4.56 6.24 3.84 9.36 6.96 10.8 10.8 6.96 4.08 6.24 3.84 3.84 6.48 6.24 9.36 3.84 6.96 6.96 3.6 6.96 3.84 9.6 6.96 3.84 6.72 6.24 5.04 3.84 6.24 3.84 6.24 7.44 6.96 3.6 6.96 6.96 6.96 10.8 3.84 6.24 3.84 9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96 4.56 6.24 4.56 4.56]
 xshow
@@ -258,22 +258,22 @@ xshow
 end grestore
 end grestore
 % MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FRAMALG...
-newpath 214 72 moveto
-181 61 139 48 106 37 curveto
+newpath 315 72 moveto
+252 63 180 52 106 36 curveto
 stroke
 gsave 10 dict begin
 solid
 1 setlinewidth
 0.000 0.000 0.000 edgecolor
-newpath 107 34 moveto
+newpath 106 33 moveto
 96 34 lineto
-105 40 lineto
+105 39 lineto
 closepath
 fill
 0.000 0.000 0.000 edgecolor
-newpath 107 34 moveto
+newpath 106 33 moveto
 96 34 lineto
-105 40 lineto
+105 39 lineto
 closepath
 stroke
 end grestore
@@ -304,22 +304,22 @@ xshow
 end grestore
 end grestore
 % MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->COMRING...
-newpath 242 72 moveto
-228 63 211 52 196 42 curveto
+newpath 378 72 moveto
+332 63 275 51 216 36 curveto
 stroke
 gsave 10 dict begin
 solid
 1 setlinewidth
 0.000 0.000 0.000 edgecolor
-newpath 197 39 moveto
-187 36 lineto
-193 44 lineto
+newpath 217 33 moveto
+206 33 lineto
+215 39 lineto
 closepath
 fill
 0.000 0.000 0.000 edgecolor
-newpath 197 39 moveto
-187 36 lineto
-193 44 lineto
+newpath 217 33 moveto
+206 33 lineto
+215 39 lineto
 closepath
 stroke
 end grestore
@@ -350,22 +350,22 @@ xshow
 end grestore
 end grestore
 % MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->KONVERT...
-newpath 270 72 moveto
-270 64 270 55 270 46 curveto
+newpath 427 72 moveto
+396 61 357 48 326 37 curveto
 stroke
 gsave 10 dict begin
 solid
 1 setlinewidth
 0.000 0.000 0.000 edgecolor
-newpath 274 46 moveto
-270 36 lineto
-267 46 lineto
+newpath 327 34 moveto
+316 34 lineto
+325 40 lineto
 closepath
 fill
 0.000 0.000 0.000 edgecolor
-newpath 274 46 moveto
-270 36 lineto
-267 46 lineto
+newpath 327 34 moveto
+316 34 lineto
+325 40 lineto
 closepath
 stroke
 end grestore
@@ -396,22 +396,22 @@ xshow
 end grestore
 end grestore
 % MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FRETRCT...
-newpath 297 72 moveto
-311 63 327 52 341 42 curveto
+newpath 453 72 moveto
+441 63 425 52 411 42 curveto
 stroke
 gsave 10 dict begin
 solid
 1 setlinewidth
 0.000 0.000 0.000 edgecolor
-newpath 344 44 moveto
-350 36 lineto
-340 39 lineto
+newpath 412 39 moveto
+402 36 lineto
+408 44 lineto
 closepath
 fill
 0.000 0.000 0.000 edgecolor
-newpath 344 44 moveto
-350 36 lineto
-340 39 lineto
+newpath 412 39 moveto
+402 36 lineto
+408 44 lineto
 closepath
 stroke
 end grestore
@@ -442,22 +442,206 @@ xshow
 end grestore
 end grestore
 % MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FLINEXP...
-newpath 323 72 moveto
-352 63 388 50 429 36 curveto
+newpath 479 72 moveto
+479 64 479 55 479 46 curveto
 stroke
 gsave 10 dict begin
 solid
 1 setlinewidth
 0.000 0.000 0.000 edgecolor
-newpath 430 39 moveto
-438 33 lineto
-427 33 lineto
+newpath 483 46 moveto
+479 36 lineto
+476 46 lineto
 closepath
 fill
 0.000 0.000 0.000 edgecolor
-newpath 430 39 moveto
-438 33 lineto
-427 33 lineto
+newpath 483 46 moveto
+479 36 lineto
+476 46 lineto
+closepath
+stroke
+end grestore
+% FINITE...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 610 36 moveto
+538 36 lineto
+538 0 lineto
+610 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 610 36 moveto
+538 36 lineto
+538 0 lineto
+610 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+546 13 moveto
+(FINITE...)
+[7.68 4.56 10.08 4.56 8.64 8.64 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FINITE...
+newpath 503 72 moveto
+514 63 529 52 542 42 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 544 45 moveto
+550 36 lineto
+540 39 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 544 45 moveto
+550 36 lineto
+540 39 lineto
+closepath
+stroke
+end grestore
+% FIELD...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 694 36 moveto
+628 36 lineto
+628 0 lineto
+694 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 694 36 moveto
+628 36 lineto
+628 0 lineto
+694 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+635 13 moveto
+(FIELD...)
+[7.68 4.56 8.64 8.64 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FIELD...
+newpath 527 72 moveto
+552 63 582 50 618 36 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 620 39 moveto
+628 32 lineto
+617 32 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 620 39 moveto
+628 32 lineto
+617 32 lineto
+closepath
+stroke
+end grestore
+% DIFEXT...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 788 36 moveto
+712 36 lineto
+712 0 lineto
+788 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 788 36 moveto
+712 36 lineto
+712 0 lineto
+788 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+719 13 moveto
+(DIFEXT...)
+[10.08 4.56 7.68 8.64 10.08 7.44 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->DIFEXT...
+newpath 564 72 moveto
+603 63 652 51 702 36 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 703 39 moveto
+712 33 lineto
+701 33 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 703 39 moveto
+712 33 lineto
+701 33 lineto
+closepath
+stroke
+end grestore
+% FFIELDC...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 890 36 moveto
+806 36 lineto
+806 0 lineto
+890 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 890 36 moveto
+806 36 lineto
+806 0 lineto
+890 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+814 13 moveto
+(FFIELDC...)
+[7.68 7.68 4.56 8.64 8.64 10.08 9.36 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FFIELDC...
+newpath 613 72 moveto
+667 63 731 52 796 35 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 797 38 moveto
+806 33 lineto
+796 32 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 797 38 moveto
+806 33 lineto
+796 32 lineto
 closepath
 stroke
 end grestore
diff --git a/changelog b/changelog
index 6cd36af..8ac1b44 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,7 @@
+20081008 tpd books/bookvol10.2 add ACF, cleanup MONOGEN, FFCAT
+20081008 tpd books/ps/v102algebraicallyclosedfield.ps added
+20081008 tpd src/algebra/algfunc.spad move ACF to bookvol10.2
+20081008 tpd books/ps/v102monogenicalgebra.ps updated
 20081007 tpd books/bookvol10.2 add categories, update ATTREG
 20081007 tpd books/ps/v102xpolynomialscat.ps added
 20081007 tpd books/ps/v102xfreealgebra.ps added
diff --git a/src/algebra/algfunc.spad.pamphlet b/src/algebra/algfunc.spad.pamphlet
index 163734e..75dcfa0 100644
--- a/src/algebra/algfunc.spad.pamphlet
+++ b/src/algebra/algfunc.spad.pamphlet
@@ -9,151 +9,6 @@
 \eject
 \tableofcontents
 \eject
-\section{category ACF AlgebraicallyClosedField}
-<<category ACF AlgebraicallyClosedField>>=
-)abbrev category ACF AlgebraicallyClosedField
-++ Author: Manuel Bronstein
-++ Date Created: 22 Mar 1988
-++ Date Last Updated: 27 November 1991
-++ Description:
-++   Model for algebraically closed fields.
-++ Keywords: algebraic, closure, field.
-
-AlgebraicallyClosedField(): Category == Join(Field,RadicalCategory) with
-    rootOf: Polynomial $ -> $
-      ++ rootOf(p) returns y such that \spad{p(y) = 0}.
-      ++ Error: if p has more than one variable y.
-    rootOf: SparseUnivariatePolynomial $ -> $
-      ++ rootOf(p) returns y such that \spad{p(y) = 0}.
-    rootOf: (SparseUnivariatePolynomial $, Symbol) -> $
-      ++ rootOf(p, y) returns y such that \spad{p(y) = 0}.
-      ++ The object returned displays as \spad{'y}.
-    rootsOf: Polynomial $ -> List $
-      ++ rootsOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
-      ++ Note: the returned symbols y1,...,yn are bound in the
-      ++ interpreter to respective root values.
-      ++ Error: if p has more than one variable y.
-    rootsOf: SparseUnivariatePolynomial $ -> List $
-      ++ rootsOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
-      ++ Note: the returned symbols y1,...,yn are bound in the interpreter
-      ++ to respective root values.
-    rootsOf: (SparseUnivariatePolynomial $, Symbol) -> List $
-      ++ rootsOf(p, y) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0};
-      ++ The returned roots display as \spad{'y1},...,\spad{'yn}.
-      ++ Note: the returned symbols y1,...,yn are bound in the interpreter
-      ++ to respective root values.
-    zeroOf: Polynomial $ -> $
-      ++ zeroOf(p) returns y such that \spad{p(y) = 0}.
-      ++ If possible, y is expressed in terms of radicals.
-      ++ Otherwise it is an implicit algebraic quantity.
-      ++ Error: if p has more than one variable y.
-    zeroOf: SparseUnivariatePolynomial $ -> $
-      ++ zeroOf(p) returns y such that \spad{p(y) = 0};
-      ++ if possible, y is expressed in terms of radicals.
-      ++ Otherwise it is an implicit algebraic quantity.
-    zeroOf: (SparseUnivariatePolynomial $, Symbol) -> $
-      ++ zeroOf(p, y) returns y such that \spad{p(y) = 0};
-      ++ if possible, y is expressed in terms of radicals.
-      ++ Otherwise it is an implicit algebraic quantity which
-      ++ displays as \spad{'y}.
-    zerosOf: Polynomial $ -> List $
-      ++ zerosOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
-      ++ The yi's are expressed in radicals if possible.
-      ++ Otherwise they are implicit algebraic quantities.
-      ++ The returned symbols y1,...,yn are bound in the interpreter
-      ++ to respective root values.
-      ++ Error: if p has more than one variable y.
-    zerosOf: SparseUnivariatePolynomial $ -> List $
-      ++ zerosOf(p) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
-      ++ The yi's are expressed in radicals if possible, and otherwise
-      ++ as implicit algebraic quantities.
-      ++ The returned symbols y1,...,yn are bound in the interpreter
-      ++ to respective root values.
-    zerosOf: (SparseUnivariatePolynomial $, Symbol) -> List $
-      ++ zerosOf(p, y) returns \spad{[y1,...,yn]} such that \spad{p(yi) = 0}.
-      ++ The yi's are expressed in radicals if possible, and otherwise
-      ++ as implicit algebraic quantities
-      ++ which display as \spad{'yi}.
-      ++ The returned symbols y1,...,yn are bound in the interpreter
-      ++ to respective root values.
- add
-    SUP ==> SparseUnivariatePolynomial $
-
-    assign  : (Symbol, $) -> $
-    allroots: (SUP, Symbol, (SUP, Symbol) -> $) -> List $
-    binomialRoots: (SUP, Symbol, (SUP, Symbol) -> $) -> List $
-
-    zeroOf(p:SUP)            == assign(x := new(), zeroOf(p, x))
-    rootOf(p:SUP)            == assign(x := new(), rootOf(p, x))
-    zerosOf(p:SUP)           == zerosOf(p, new())
-    rootsOf(p:SUP)           == rootsOf(p, new())
-    rootsOf(p:SUP, y:Symbol) == allroots(p, y, rootOf)
-    zerosOf(p:SUP, y:Symbol) == allroots(p, y, zeroOf)
-    assign(x, f)             == (assignSymbol(x, f, $)$Lisp; f)
-
-    zeroOf(p:Polynomial $) ==
-      empty?(l := variables p) => error "zeroOf: constant polynomial"
-      zeroOf(univariate p, first l)
-
-    rootOf(p:Polynomial $) ==
-      empty?(l := variables p) => error "rootOf: constant polynomial"
-      rootOf(univariate p, first l)
-
-    zerosOf(p:Polynomial $) ==
-      empty?(l := variables p) => error "zerosOf: constant polynomial"
-      zerosOf(univariate p, first l)
-
-    rootsOf(p:Polynomial $) ==
-      empty?(l := variables p) => error "rootsOf: constant polynomial"
-      rootsOf(univariate p, first l)
-
-    zeroOf(p:SUP, y:Symbol) ==
-      zero?(d := degree p) => error "zeroOf: constant polynomial"
-      zero? coefficient(p, 0) => 0
-      a := leadingCoefficient p
-      d = 2 =>
-        b := coefficient(p, 1)
-        (sqrt(b**2 - 4 * a * coefficient(p, 0)) - b) / (2 * a)
-      (r := retractIfCan(reductum p)@Union($,"failed")) case "failed" =>
-        rootOf(p, y)
-      nthRoot(- (r::$ / a), d)
-
-    binomialRoots(p, y, fn) ==
-     -- p = a * x**n + b
-      alpha := assign(x := new(y)$Symbol, fn(p, x))
---      one?(n := degree p) =>  [ alpha ]
-      ((n := degree p) = 1) =>  [ alpha ]
-      cyclo := cyclotomic(n, monomial(1,1)$SUP)$NumberTheoreticPolynomialFunctions(SUP)
-      beta := assign(x := new(y)$Symbol, fn(cyclo, x))
-      [alpha*beta**i for i in 0..(n-1)::NonNegativeInteger]
-
-    import PolynomialDecomposition(SUP,$)
-
-    allroots(p, y, fn) ==
-      zero? p => error "allroots: polynomial must be nonzero"
-      zero? coefficient(p,0) =>
-         concat(0, allroots(p quo monomial(1,1), y, fn))
-      zero?(p1:=reductum p) => empty()
-      zero? reductum p1 => binomialRoots(p, y, fn)
-      decompList := decompose(p)
-      # decompList > 1 =>
-          h := last decompList
-          g := leftFactor(p,h) :: SUP
-          groots := allroots(g, y, fn)
-          "append"/[allroots(h-r::SUP, y, fn) for r in groots]
-      ans := nil()$List($)
-      while not ground? p repeat
-        alpha := assign(x := new(y)$Symbol, fn(p, x))
-        q     := monomial(1, 1)$SUP - alpha::SUP
-        if not zero?(p alpha) then
-          p   := p quo q
-          ans := concat(alpha, ans)
-        else while zero?(p alpha) repeat
-          p   := (p exquo q)::SUP
-          ans := concat(alpha, ans)
-      reverse_! ans
-
-@
 \section{category ACFS AlgebraicallyClosedFunctionSpace}
 <<category ACFS AlgebraicallyClosedFunctionSpace>>=
 )abbrev category ACFS AlgebraicallyClosedFunctionSpace
@@ -287,6 +142,12 @@ test and give $$1/(-2)^(1/n) \ne (-1/2)^(1/n)$$
         kernel(oproot, [x, n::F])
 
 @
+<<dot>>=
+"AF" [color=orange,style=filled];
+"AlgebraicFunction(a:Join(ORDSET,INTDOM),b:FS(a))" [color=orange,style=filled];
+"AF" -> "PACKAGE"
+"AlgebraicFunction(a:Join(ORDSET,INTDOM),b:FS(a))" -> "Package"
+@
 <<package AF AlgebraicFunction>>=
 )abbrev package AF AlgebraicFunction
 ++ Author: Manuel Bronstein
@@ -566,7 +427,6 @@ AlgebraicFunction(R, F): Exports == Implementation where
 --
 --   op  kl  fspace ALGFUNC expr
 
-<<category ACF AlgebraicallyClosedField>>
 <<category ACFS AlgebraicallyClosedFunctionSpace>>
 <<package AF AlgebraicFunction>>
 @
