diff --git a/books/bookvol10.2.pamphlet b/books/bookvol10.2.pamphlet
index e6ea693..60be62e 100644
--- a/books/bookvol10.2.pamphlet
+++ b/books/bookvol10.2.pamphlet
@@ -279,7 +279,10 @@ correspond to the signature of an existing category. The system
 can infer that this ``subsumption node'' matches the category.
 A ``yellow'' color indicates a domain.
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{Category}{CATEGORY}
+\pagepic{ps/v102category.ps}{CATEGORY}{1.00}
+
 This is the root of the category hierarchy and is not represented by code.
 
 {\bf See:}\\
@@ -292,6 +295,189 @@ This is the root of the category hierarchy and is not represented by code.
 \pageto{RetractableTo}{RETRACT}
 \pageto{Type}{TYPE}
 
+<<CATEGORY.dotabb>>=
+"CATEGORY"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=CATEGORY"];
+
+@
+<<CATEGORY.dotfull>>=
+"Category"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=CATEGORY"];
+
+@
+<<CATEGORY.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"Category" [color=lightblue];
+}
+
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{AttributeRegistry}{ATTREG}
+\pagepic{ps/v102attributeregistry.ps}{ATTREG}{1.00}
+
+{\bf See:}\\
+\pagefrom{Category}{CATEGORY}
+
+{\bf Exports:} Nothing
+
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{ATTREG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\item {\bf \cross{ATTREG}{commutative("*")}}
+is true if it has an operation $"*": (D,D) -> D$
+which is commutative.
+\item {\bf \cross{ATTREG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\item {\bf \cross{ATTREG}{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{ATTREG}{leftUnitary}}
+is true if $1 * x = x$ for all x.
+\item {\bf \cross{ATTREG}{rightUnitary}}
+is true if $x * 1 = x$ for all x.
+\item {\bf \cross{ATTREG}{noZeroDivisors}}
+is true if $x * y ~= 0$ implies both x and y are non-zero.
+\item {\bf \cross{ATTREG}{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{ATTREG}{canonicalsClosed}}
+is true if\\
+{\tt unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
+\item {\bf \cross{ATTREG}{arbitraryPrecision}}
+means the user can set the precision for subsequent calculations.
+\item {\bf \cross{ATTREG}{partiallyOrderedSet}}
+is true if a set with $<$ which is transitive, but 
+not($a < b$ or $a = b$) does not necessarily imply $b<a$.
+\item {\bf \cross{ATTREG}{central}}
+is true if, given an algebra over a ring R, the image of R is the center
+of the algebra, i.e. the set of members of the algebra which commute
+with all others is precisely the image of R in the algebra.
+\item {\bf \cross{ATTREG}{noetherian}}
+is true if all of its ideals are finitely generated.
+\item {\bf \cross{ATTREG}{additiveValuation}}
+implies\\
+{\tt euclideanSize(a*b)=euclideanSize(a)+euclideanSize(b)}.
+\item {\bf \cross{ATTREG}{multiplicativeValuation}}
+implies\\
+{\tt euclideanSize(a*b)=euclideanSize(a)*euclideanSize(b)}.
+\item {\bf \cross{ATTREG}{NullSquare}}
+means that $[x,x] = 0$ holds. See {\tt LieAlgebra}.
+\item {\bf \cross{ATTREG}{JacobiIdentity}}
+means that $[x,[y,z]]+[y,[z,x]]+[z,[x,y]] = 0$ holds.
+See {\tt LieAlgebra}.
+\item {\bf \cross{ATTREG}{canonical}}
+is true if and only if distinct elements have distinct data structures. 
+For example, a domain of mathematical objects which has the 
+{\tt canonical} attribute means that two objects are mathematically 
+equal if and only if their data structures are equal.
+\end{itemize}
+
+<<category ATTREG AttributeRegistry>>=
+)abbrev category ATTREG AttributeRegistry
+
+++ This category exports the attributes in the AXIOM Library
+AttributeRegistry(): Category == with
+  finiteAggregate
+    ++ \spad{finiteAggregate} is true if it is an aggregate with a 
+    ++ finite number of elements.
+  commutative("*")
+    ++ \spad{commutative("*")} is true if it has an operation
+    ++ \spad{"*": (D,D) -> D} which is commutative.
+  shallowlyMutable
+    ++ \spad{shallowlyMutable} is true if its values
+    ++ have immediate components that are updateable (mutable).
+    ++ Note: the properties of any component domain are irrevelant to the
+    ++ \spad{shallowlyMutable} proper.
+  unitsKnown
+    ++ \spad{unitsKnown} is true if a monoid (a multiplicative semigroup 
+    ++ with a 1) has \spad{unitsKnown} means that
+    ++ the operation \spadfun{recip} can only return "failed" 
+    ++ if its argument is not a unit.
+  leftUnitary
+    ++ \spad{leftUnitary} is true if \spad{1 * x = x} for all x.
+  rightUnitary
+    ++ \spad{rightUnitary} is true if \spad{x * 1 = x} for all x.
+  noZeroDivisors
+    ++ \spad{noZeroDivisors} is true if \spad{x * y \~~= 0} implies 
+    ++ both x and y are non-zero.
+  canonicalUnitNormal
+    ++ \spad{canonicalUnitNormal} is true if we can choose a canonical
+    ++ representative for each class of associate elements, that is
+    ++ \spad{associates?(a,b)} returns true if and only if 
+    ++ \spad{unitCanonical(a) = unitCanonical(b)}.
+  canonicalsClosed
+    ++ \spad{canonicalsClosed} is true if 
+    ++ \spad{unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
+  arbitraryPrecision
+    ++ \spad{arbitraryPrecision} means the user can set the 
+    ++ precision for subsequent calculations.
+  partiallyOrderedSet
+    ++ \spad{partiallyOrderedSet} is true if
+    ++ a set with \spadop{<} which is transitive, 
+    ++ but \spad{not(a < b or a = b)}
+    ++ does not necessarily imply \spad{b<a}.
+  central
+    ++ \spad{central} is true if, given an algebra over a ring R,
+    ++ the image of R is the center
+    ++ of the algebra, i.e. the set of members of the algebra which commute
+    ++ with all others is precisely the image of R in the algebra.
+  noetherian
+    ++ \spad{noetherian} is true if all of its ideals are finitely generated.
+  additiveValuation
+    ++ \spad{additiveValuation} implies
+    ++ \spad{euclideanSize(a*b)=euclideanSize(a)+euclideanSize(b)}.
+  multiplicativeValuation
+    ++ \spad{multiplicativeValuation} implies
+    ++ \spad{euclideanSize(a*b)=euclideanSize(a)*euclideanSize(b)}.
+  NullSquare
+    ++ \axiom{NullSquare} means that \axiom{[x,x] = 0} holds.
+    ++ See \axiomType{LieAlgebra}.
+  JacobiIdentity
+    ++ \axiom{JacobiIdentity} means that 
+    ++ \axiom{[x,[y,z]]+[y,[z,x]]+[z,[x,y]] = 0} holds.
+    ++ See \axiomType{LieAlgebra}.
+  canonical
+    ++ \spad{canonical} is true if and only if distinct elements have 
+    ++ distinct data structures. For example, a domain of mathematical 
+    ++ objects  which has the \spad{canonical} attribute means that two 
+    ++ objects are mathematically equal if and only if their data 
+    ++ structures are equal.
+
+@
+<<ATTREG.dotabb>>=
+"ATTREG"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=ATTREG"];
+"ATTREG" -> "CATEGORY"
+
+@
+<<ATTREG.dotabb>>=
+"AttributeRegistry()"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=ATTREG"];
+"AttributeRegistry()" -> "Category"
+
+@
+<<ATTREG.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"AttributeRegistry()" [color=lightblue];
+"AttributeRegistry()" -> "Category"
+
+"Category" [color=lightblue];
+}
+
+@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{BasicType}{BASTYPE}
 \pagepic{ps/v102basictype.ps}{BASTYPE}{1.00}
@@ -429,6 +615,7 @@ digraph pic {
 
 {\bf See:}\\
 \pageto{Collection}{CLAGG}
+\pageto{MonogenicAlgebra}{MONOGEN}
 \pagefrom{Category}{CATEGORY}
 
 {\bf Exports:}\\
@@ -525,6 +712,7 @@ ConvertibleTo(S:Type): Category == with
  [color=seagreen,href="bookvol10.2.pdf#nameddest=KONVERT"];
 "ConvertibleTo(UnivariatePolynomialCategory(CommutativeRing))" ->
     "ConvertibleTo(a:Type)"
+
 @
 <<KONVERT.dotpic>>=
 digraph pic {
@@ -700,6 +888,7 @@ digraph pic {
 \pagepic{ps/v102retractableto.ps}{RETRACT}{1.00}
 
 {\bf See:}\\
+\pageto{FullyRetractableTo}{FRETRCT}
 \pagefrom{Category}{CATEGORY}
 
 {\bf Exports:}\\
@@ -860,6 +1049,12 @@ digraph pic {
 \cross{AGG}{size?}
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{AGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are implemented by this category:
 \begin{verbatim}
  empty? : % -> Boolean
@@ -969,6 +1164,14 @@ digraph pic {
 \cross{ELTAGG}{?.?}
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{ELTAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are part of this category's direct exports:
 \begin{verbatim}
  elt : (%,Dom,Im) -> Im                
@@ -1159,6 +1362,116 @@ digraph pic {
 
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{FullyRetractableTo}{FRETRCT}
+\pagepic{ps/v102fullyretractableto.ps}{FRETRCT}{1.00}
+
+{\bf See:}\\
+\pageto{MonogenicAlgebra}{MONOGEN}
+\pagefrom{RetractableTo}{RETRACT}
+
+{\bf Exports:}\\
+\begin{tabular}{lll}
+\cross{FRETRCT}{coerce} &
+\cross{FRETRCT}{retract} &
+\cross{FRETRCT}{retractIfCan} 
+\end{tabular}
+
+These are implemented by this category:
+\begin{verbatim}
+ coerce : Integer -> % 
+     if S has RETRACT INT
+ coerce : Fraction Integer -> % 
+     if S has RETRACT FRAC INT
+ retract : % -> Integer 
+     if S has RETRACT INT
+ retract : % -> Fraction Integer 
+     if S has RETRACT FRAC INT
+ retractIfCan : % -> Union(Integer,"failed") 
+     if S has RETRACT INT
+ retractIfCan : % -> Union(Fraction Integer,"failed") 
+     if S has RETRACT FRAC INT
+\end{verbatim}
+
+These exports come from RetractableTo(S:Type):
+\begin{verbatim}
+ coerce : S -> %                       
+ retract : % -> S
+ retractIfCan : % -> Union(S,"failed")
+\end{verbatim}
+
+<<category FRETRCT FullyRetractableTo>>=
+)abbrev category FRETRCT FullyRetractableTo
+++ Author: Manuel Bronstein
+++ Description:
+++   A is fully retractable to B means that A is retractable to B, and,
+++   in addition, if B is retractable to the integers or rational
+++   numbers then so is A.
+++   In particular, what we are asserting is that there are no integers
+++   (rationals) in A which don't retract into B.
+++ Date Created: March 1990
+++ Date Last Updated: 9 April 1991
+FullyRetractableTo(S: Type): Category == RetractableTo(S) with
+    if (S has RetractableTo Integer) then RetractableTo Integer
+    if (S has RetractableTo Fraction Integer) then
+              RetractableTo Fraction Integer
+  add
+    if not(S is Integer) then
+      if (S has RetractableTo Integer) then    -- induction
+        coerce(n:Integer):%  == n::S::%
+        retract(r:%):Integer == retract(retract(r)@S)
+ 
+        retractIfCan(r:%):Union(Integer, "failed") ==
+          (u:= retractIfCan(r)@Union(S,"failed")) case "failed"=> "failed"
+          retractIfCan(u::S)
+ 
+    if not(S is Fraction Integer) then
+      if (S has RetractableTo Fraction Integer) then   -- induction
+        coerce(n:Fraction Integer):%  == n::S::%
+        retract(r:%):Fraction(Integer) == retract(retract(r)@S)
+ 
+        retractIfCan(r:%):Union(Fraction Integer, "failed") ==
+          (u:=retractIfCan(r)@Union(S,"failed")) case "failed"=>"failed"
+          retractIfCan(u::S)
+
+@
+<<FRETRCT.dotabb>>=
+"FRETRCT"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FRETRCT"];
+"FRETRCT" -> "RETRACT"
+
+@
+<<FRETRCT.dotfull>>=
+"FullyRetractableTo(a:Type)"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FRETRCT"];
+"FullyRetractableTo(a:Type)" -> "RetractableTo(a:Type)"
+
+ [color=seagreen,href="bookvol10.2.pdf#nameddest=FRETRCT"];
+"FullyRetractableTo(a:Ring)" -> "FullyRetractableTo(a:Type)"
+
+ [color=seagreen,href="bookvol10.2.pdf#nameddest=FRETRCT"];
+"FullyRetractableTo(a:CommutativeRing)" -> "FullyRetractableTo(a:Type)"
+
+ [color=seagreen,href="bookvol10.2.pdf#nameddest=FRETRCT"];
+"FullyRetractableTo(a:SetCategory)" -> "FullyRetractableTo(a:Type)"
+
+@
+<<FRETRCT.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"FullyRetractableTo(a:Type)" [color=lightblue];
+"FullyRetractableTo(a:Type)" -> "RetractableTo(a:Type)"
+
+"RetractableTo(a:Type)" [color=lightblue];
+"RetractableTo(a:Type)" -> "Category"
+
+"Category" [color=lightblue];
+}
+
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{Logic}{LOGIC}
 \pagepic{ps/v102logic.ps}{LOGIC}{1.00}
 
@@ -1303,7 +1616,6 @@ These exports come from CoercibleTo(OutputForm):
 ++ Conditional Attributes:
 ++    canonical\tab{15}data structure equality is the same as \spadop{=}
 SetCategory(): Category == Join(BasicType,CoercibleTo OutputForm) with
-    --operations
       hash: % -> SingleInteger  ++ hash(s) calculates a hash code for s.
       latex: % -> String       ++ latex(s) returns a LaTeX-printable output
                                ++ representation of s.
@@ -1408,7 +1720,6 @@ These exports come from SetCategory():
 ++   \spad{associative("+":(%,%)->%)}\tab{30}\spad{ (x+y)+z = x+(y+z) }
 ++   \spad{commutative("+":(%,%)->%)}\tab{30}\spad{ x+y = y+x }
 AbelianSemiGroup(): Category == SetCategory with
-    --operations
       "+": (%,%) -> %                  ++ x+y computes the sum of x and y.
       "*": (PositiveInteger,%) -> %
         ++ n*x computes the left-multiplication of x by the positive 
@@ -1430,7 +1741,7 @@ AbelianSemiGroup(): Category == SetCategory with
 "AbelianSemiGroup()"
  [color=lightblue,href="bookvol10.2.pdf#nameddest=ABELSG"];
 "AbelianSemiGroup()" -> "SetCategory()"
-"AbelianSemiGroup()" -> "RepeatedDoubling(SetCategory)"
+"AbelianSemiGroup()" -> "RepeatedDoubling(a:SetCategory)"
 
 <<ABELSG.dotpic>>=
 digraph pic {
@@ -1528,7 +1839,6 @@ These exports come from SetCategory():
 ++   \spad{index(lookup(s)) = s}
 
 Finite(): Category == SetCategory with
-    --operations
       size: () ->  NonNegativeInteger
         ++ size() returns the number of elements in the set.
       index: PositiveInteger -> %
@@ -1592,6 +1902,7 @@ digraph pic {
 \pageto{Collection}{CLAGG}
 \pageto{IndexedAggregate}{IXAGG}
 \pageto{RecursiveAggregate}{RCAGG}
+\pageto{TwoDimensionalArrayCategory}{ARR2CAT}
 \pagefrom{Aggregate}{AGG}
 \pagefrom{Evalable}{EVALAB}
 \pagefrom{SetCategory}{SETCAT}
@@ -1623,6 +1934,16 @@ digraph pic {
 \cross{HOAGG}{?\~{}=?} &&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{HOAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\item {\bf \cross{HOAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  map : ((S -> S),%) -> %              
@@ -1869,7 +2190,6 @@ These exports come from SetCategory():
 ++ exactly one of the following relations holds \spad{a<b or a=b or b<a}
 ++ and the relation is transitive, i.e.  \spad{a<b and b<c => a<c}.
 OrderedSet(): Category == SetCategory with
-  --operations
     "<": (%,%) -> Boolean
       ++ x < y is a strict total ordering on the elements of the set.
     ">":         (%, %) -> Boolean
@@ -1878,15 +2198,12 @@ OrderedSet(): Category == SetCategory with
       ++ x >= y is a greater than or equal test.
     "<=":        (%, %) -> Boolean
       ++ x <= y is a less than or equal test.
-
     max: (%,%) -> %
       ++ max(x,y) returns the maximum of x and y relative to "<".
     min: (%,%) -> %
       ++ min(x,y) returns the minimum of x and y relative to "<".
   add
-  --declarations
     x,y: %
-  --definitions
   -- These really ought to become some sort of macro
     max(x,y) ==
       x > y => x
@@ -2007,7 +2324,6 @@ These exports come from SetCategory():
 ++ Conditional attributes:
 ++    \spad{commutative("*":(%,%)->%)}\tab{30}\spad{ x*y = y*x }
 SemiGroup(): Category == SetCategory with
-    --operations
       "*": (%,%) -> %                  ++ x*y returns the product of x and y.
       "**": (%,PositiveInteger) -> %   ++ x**n returns the repeated product
                                        ++ of x n times, i.e. exponentiation.
@@ -2029,7 +2345,7 @@ SemiGroup(): Category == SetCategory with
 "SemiGroup()"
  [color=lightblue,href="bookvol10.2.pdf#nameddest=SGROUP"];
 "SemiGroup()" -> "SetCategory()"
-"SemiGroup()" -> "RepeatedSquaring(SemiGroup)"
+"SemiGroup()" -> "RepeatedSquaring(a:SemiGroup)"
 
 @
 <<SGROUP.dotpic>>=
@@ -2040,7 +2356,7 @@ digraph pic {
 
 "SemiGroup()" [color=lightblue];
 "SemiGroup()" -> "SetCategory()"
-"SemiGroup()" -> "RepeatedSquaring(SemiGroup)"
+"SemiGroup()" -> "RepeatedSquaring(a:SemiGroup)"
 
 "SetCategory()" [color=lightblue];
 "SetCategory()" -> "BasicType()"
@@ -2055,8 +2371,8 @@ digraph pic {
 "CoercibleTo(a:Type)" [color=lightblue];
 "CoercibleTo(a:Type)" -> "Category"
 
-"RepeatedSquaring(SemiGroup)" [color="#00EE00"];
-"RepeatedSquaring(SemiGroup)" -> "RepeatedSquaring(a:SetCategory)"
+"RepeatedSquaring(a:SemiGroup)" [color="#00EE00"];
+"RepeatedSquaring(a:SemiGroup)" -> "RepeatedSquaring(a:SetCategory)"
 
 "RepeatedSquaring(a:SetCategory)" [color="#00EE00"];
 "RepeatedSquaring(a:SetCategory)" -> "Package"
@@ -2125,11 +2441,11 @@ These exports come from SetCategory():
 ++ Conditional attributes:
 ++   infinite\tab{15}repeated \spad{nextItem}'s are never "failed".
 StepThrough(): Category == SetCategory with
-    --operations
       init: constant -> %
         ++ init() chooses an initial object for stepping.
       nextItem: % -> Union(%,"failed")
-        ++ nextItem(x) returns the next item, or "failed" if domain is exhausted.
+        ++ nextItem(x) returns the next item, or "failed" 
+        ++ if domain is exhausted.
 
 @
 <<STEP.dotabb>>=
@@ -2239,7 +2555,6 @@ These exports come from AbelianSemiGroup():
 -- following domain must be compiled with subsumption disabled
 -- define SourceLevelSubset to be EQUAL
 AbelianMonoid(): Category == AbelianSemiGroup with
-    --operations
       0: constant -> % 
 	++ 0 is the additive identity element.
       sample: constant -> %
@@ -2311,6 +2626,552 @@ digraph pic {
 
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{TwoDimensionalArrayCategory}{ARR2CAT}
+\pagepic{ps/v102twodimensionalarraycategory.ps}{ARR2CAT}{0.60}
+
+TwoDimensionalArrayCategory is a general array category which
+allows different representations and indexing schemes.
+Rows and columns may be extracted with rows returned as objects
+of type Row and columns returned as objects of type Col.
+The index of the 'first' row may be obtained by calling the
+function 'minRowIndex'.  The index of the 'first' column may
+be obtained by calling the function 'minColIndex'.  The index of
+the first element of a 'Row' is the same as the index of the
+first column in an array and vice versa.
+
+{\bf See:}\\
+\pagefrom{HomogeneousAggregate}{HOAGG}
+
+{\bf Exports:}\\
+\begin{tabular}{lllll}
+\cross{ARR2CAT}{any?} &
+\cross{ARR2CAT}{column} &
+\cross{ARR2CAT}{coerce} &
+\cross{ARR2CAT}{copy} &
+\cross{ARR2CAT}{count} \\
+\cross{ARR2CAT}{elt} &
+\cross{ARR2CAT}{empty} &
+\cross{ARR2CAT}{empty?} &
+\cross{ARR2CAT}{eq?} &
+\cross{ARR2CAT}{eval} \\
+\cross{ARR2CAT}{every?} &
+\cross{ARR2CAT}{fill!} &
+\cross{ARR2CAT}{hash} &
+\cross{ARR2CAT}{latex} &
+\cross{ARR2CAT}{less?} \\
+\cross{ARR2CAT}{map} &
+\cross{ARR2CAT}{map!} &
+\cross{ARR2CAT}{maxColIndex} &
+\cross{ARR2CAT}{maxRowIndex} &
+\cross{ARR2CAT}{member?} \\
+\cross{ARR2CAT}{members} &
+\cross{ARR2CAT}{minColIndex} &
+\cross{ARR2CAT}{minRowIndex} &
+\cross{ARR2CAT}{more?} &
+\cross{ARR2CAT}{ncols} \\
+\cross{ARR2CAT}{new} &
+\cross{ARR2CAT}{nrows} &
+\cross{ARR2CAT}{parts} &
+\cross{ARR2CAT}{qelt} &
+\cross{ARR2CAT}{qsetelt!} \\
+\cross{ARR2CAT}{row} &
+\cross{ARR2CAT}{sample} &
+\cross{ARR2CAT}{setColumn!} &
+\cross{ARR2CAT}{setRow!} &
+\cross{ARR2CAT}{setelt} \\
+\cross{ARR2CAT}{size?} &
+\cross{ARR2CAT}{\#?} &
+\cross{ARR2CAT}{?=?} &
+\cross{ARR2CAT}{?\~{}=?} &
+\end{tabular}
+
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{ARR2CAT}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\item {\bf \cross{ARR2CAT}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{ARR2CAT}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
+These are directly exported but not implemented:
+\begin{verbatim}
+ elt : (%,Integer,Integer) -> R
+ maxColIndex : % -> Integer           
+ maxRowIndex : % -> Integer
+ minColIndex : % -> Integer           
+ minRowIndex : % -> Integer
+ new : (NonNegativeInteger,NonNegativeInteger,R) -> %
+ ncols : % -> NonNegativeInteger      
+ nrows : % -> NonNegativeInteger
+ qelt : (%,Integer,Integer) -> R
+ qsetelt! : (%,Integer,Integer,R) -> R
+ setelt : (%,Integer,Integer,R) -> R
+\end{verbatim}
+
+These are implemented by this category:
+\begin{verbatim}
+ any? : ((R -> Boolean),%) -> Boolean if $ has finiteAggregate
+ copy : % -> %
+ coerce : % -> OutputForm if R has SETCAT
+ column : (%,Integer) -> Col          
+ count : ((R -> Boolean),%) -> NonNegativeInteger if $ has finiteAggregate
+ count : (R,%) -> NonNegativeInteger if R has SETCAT and $ has finiteAggregate
+ elt : (%,Integer,Integer,R) -> R     
+ every? : ((R -> Boolean),%) -> Boolean if $ has finiteAggregate
+ fill! : (%,R) -> %
+ less? : (%,NonNegativeInteger) -> Boolean
+ map : ((R -> R),%) -> %              
+ map : (((R,R) -> R),%,%) -> %
+ map : (((R,R) -> R),%,%,R) -> %      
+ map! : ((R -> R),%) -> %
+ member? : (R,%) -> Boolean if R has SETCAT and $ has finiteAggregate
+ more? : (%,NonNegativeInteger) -> Boolean
+ parts : % -> List R                  
+ row : (%,Integer) -> Row             
+ setColumn! : (%,Integer,Col) -> %
+ setRow! : (%,Integer,Row) -> %       
+ size? : (%,NonNegativeInteger) -> Boolean
+ #? : % -> NonNegativeInteger if $ has finiteAggregate
+ ?=? : (%,%) -> Boolean if R has SETCAT
+\end{verbatim}
+
+These exports come from HomogeneousAggregate(R:Type)
+\begin{verbatim}
+ empty : () -> %                      
+ empty? : % -> Boolean
+ eq? : (%,%) -> Boolean               
+ eval : (%,List R,List R) -> % if R has EVALAB R and R has SETCAT
+ eval : (%,R,R) -> % if R has EVALAB R and R has SETCAT
+ eval : (%,Equation R) -> % if R has EVALAB R and R has SETCAT
+ eval : (%,List Equation R) -> % if R has EVALAB R and R has SETCAT
+ hash : % -> SingleInteger if R has SETCAT
+ latex : % -> String if R has SETCAT
+ members : % -> List R if $ has finiteAggregate
+ sample : () -> %
+ ?~=? : (%,%) -> Boolean if R has SETCAT
+\end{verbatim}
+
+<<category ARR2CAT TwoDimensionalArrayCategory>>=
+)abbrev category ARR2CAT TwoDimensionalArrayCategory
+++ Two dimensional array categories and domains
+++ Author:
+++ Date Created: 27 October 1989
+++ Date Last Updated: 27 June 1990
+++ Keywords: array, data structure
+++ Examples:
+++ References:
+TwoDimensionalArrayCategory(R,Row,Col): Category == Definition where
+ R   : Type
+ Row : FiniteLinearAggregate R
+ Col : FiniteLinearAggregate R
+
+ Definition == HomogeneousAggregate(R) with
+
+   shallowlyMutable
+    ++ one may destructively alter arrays
+
+   finiteAggregate
+    ++ two-dimensional arrays are finite
+
+--% Array creation
+
+   new: (NonNegativeInteger,NonNegativeInteger,R) -> %
+    ++ new(m,n,r) is an m-by-n array all of whose entries are r
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,0)
+    
+   fill_!: (%,R) -> %
+    ++ fill!(m,r) fills m with r's
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,0)
+    ++X fill!(arr,10)
+
+--% Size inquiries
+
+   minRowIndex : % -> Integer
+    ++ minRowIndex(m) returns the index of the 'first' row of the array m
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X minRowIndex(arr)
+
+   maxRowIndex : % -> Integer
+    ++ maxRowIndex(m) returns the index of the 'last' row of the array m
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X maxRowIndex(arr)
+
+   minColIndex : % -> Integer
+    ++ minColIndex(m) returns the index of the 'first' column of the array m
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X minColIndex(arr)
+
+   maxColIndex : % -> Integer
+    ++ maxColIndex(m) returns the index of the 'last' column of the array m
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X maxColIndex(arr)
+
+   nrows : % -> NonNegativeInteger
+    ++ nrows(m) returns the number of rows in the array m
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X nrows(arr)
+
+   ncols : % -> NonNegativeInteger
+    ++ ncols(m) returns the number of columns in the array m
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X ncols(arr)
+
+--% Part extractions
+
+   elt: (%,Integer,Integer) -> R
+    ++ elt(m,i,j) returns the element in the ith row and jth
+    ++ column of the array m
+    ++ error check to determine if indices are in proper ranges
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X elt(arr,1,1)
+
+   qelt: (%,Integer,Integer) -> R
+    ++ qelt(m,i,j) returns the element in the ith row and jth
+    ++ column of the array m
+    ++ NO error check to determine if indices are in proper ranges
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X qelt(arr,1,1)
+
+   elt: (%,Integer,Integer,R) -> R
+    ++ elt(m,i,j,r) returns the element in the ith row and jth
+    ++ column of the array m, if m has an ith row and a jth column,
+    ++ and returns r otherwise
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X elt(arr,1,1,6)
+    ++X elt(arr,1,10,6)
+
+   row: (%,Integer) -> Row
+    ++ row(m,i) returns the ith row of m
+    ++ error check to determine if index is in proper ranges
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X row(arr,1)
+
+   column: (%,Integer) -> Col
+    ++ column(m,j) returns the jth column of m
+    ++ error check to determine if index is in proper ranges
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X column(arr,1)
+
+   parts: % -> List R
+    ++ parts(m) returns a list of the elements of m in row major order
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X parts(arr)
+
+--% Part assignments
+
+   setelt: (%,Integer,Integer,R) -> R
+    -- will become setelt_!
+    ++ setelt(m,i,j,r) sets the element in the ith row and jth
+    ++ column of m to r
+    ++ error check to determine if indices are in proper ranges
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,0)
+    ++X setelt(arr,1,1,17)
+
+   qsetelt_!: (%,Integer,Integer,R) -> R
+    ++ qsetelt!(m,i,j,r) sets the element in the ith row and jth
+    ++ column of m to r
+    ++ NO error check to determine if indices are in proper ranges
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,0)
+    ++X qsetelt!(arr,1,1,17)
+
+   setRow_!: (%,Integer,Row) -> %
+    ++ setRow!(m,i,v) sets to ith row of m to v
+    ++
+    ++X T1:=TwoDimensionalArray Integer
+    ++X arr:T1:= new(5,4,0)
+    ++X T2:=OneDimensionalArray Integer
+    ++X arow:=construct([1,2,3,4]::List(INT))$T2
+    ++X setRow!(arr,1,arow)$T1
+
+   setColumn_!: (%,Integer,Col) -> %
+    ++ setColumn!(m,j,v) sets to jth column of m to v
+    ++
+    ++X T1:=TwoDimensionalArray Integer
+    ++X arr:T1:= new(5,4,0)
+    ++X T2:=OneDimensionalArray Integer
+    ++X acol:=construct([1,2,3,4,5]::List(INT))$T2
+    ++X setColumn!(arr,1,acol)$T1
+
+--% Map and Zip
+
+   map: (R -> R,%) -> %
+    ++ map(f,a) returns \spad{b}, where \spad{b(i,j) = f(a(i,j))} 
+    ++ for all \spad{i, j}
+    ++
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X map(-,arr)
+    ++X map((x +-> x + x),arr)
+
+   map_!: (R -> R,%) -> %
+    ++ map!(f,a)  assign \spad{a(i,j)} to \spad{f(a(i,j))} 
+    ++ for all \spad{i, j}
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X map!(-,arr)
+
+   map:((R,R) -> R,%,%) -> %
+    ++ map(f,a,b) returns \spad{c}, where \spad{c(i,j) = f(a(i,j),b(i,j))}
+    ++ for all \spad{i, j}
+    ++
+    ++X adder(a:Integer,b:Integer):Integer == a+b
+    ++X arr : ARRAY2 INT := new(5,4,10)
+    ++X map(adder,arr,arr)
+
+   map:((R,R) -> R,%,%,R) -> %
+    ++ map(f,a,b,r) returns \spad{c}, where \spad{c(i,j) = f(a(i,j),b(i,j))}
+    ++ when both \spad{a(i,j)} and \spad{b(i,j)} exist;
+    ++ else \spad{c(i,j) = f(r, b(i,j))} when \spad{a(i,j)} does not exist;
+    ++ else \spad{c(i,j) = f(a(i,j),r)} when \spad{b(i,j)} does not exist;
+    ++ otherwise \spad{c(i,j) = f(r,r)}.
+    ++
+    ++X adder(a:Integer,b:Integer):Integer == a+b
+    ++X arr1 : ARRAY2 INT := new(5,4,10)
+    ++X arr2 : ARRAY2 INT := new(3,3,10)
+    ++X map(adder,arr1,arr2,17)
+
+  add
+
+--% Predicates
+
+    any?(f,m) ==
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          f(qelt(m,i,j)) => return true
+      false
+
+    every?(f,m) ==
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          not f(qelt(m,i,j)) => return false
+      true
+
+    size?(m,n) == nrows(m) * ncols(m) = n
+    less?(m,n) == nrows(m) * ncols(m) < n
+    more?(m,n) == nrows(m) * ncols(m) > n
+
+--% Size inquiries
+
+    # m == nrows(m) * ncols(m)
+
+--% Part extractions
+
+    elt(m,i,j,r) ==
+      i < minRowIndex(m) or i > maxRowIndex(m) => r
+      j < minColIndex(m) or j > maxColIndex(m) => r
+      qelt(m,i,j)
+
+    count(f:R -> Boolean,m:%) ==
+      num : NonNegativeInteger := 0
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          if f(qelt(m,i,j)) then num := num + 1
+      num
+
+    parts m ==
+      entryList : List R := nil()
+      for i in maxRowIndex(m)..minRowIndex(m) by -1 repeat
+        for j in maxColIndex(m)..minColIndex(m) by -1 repeat
+          entryList := concat(qelt(m,i,j),entryList)
+      entryList
+
+--% Creation
+
+    copy m ==
+      ans := new(nrows m,ncols m,NIL$Lisp)
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          qsetelt_!(ans,i,j,qelt(m,i,j))
+      ans
+
+    fill_!(m,r) ==
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          qsetelt_!(m,i,j,r)
+      m
+
+    map(f,m) ==
+      ans := new(nrows m,ncols m,NIL$Lisp)
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          qsetelt_!(ans,i,j,f(qelt(m,i,j)))
+      ans
+
+    map_!(f,m) ==
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          qsetelt_!(m,i,j,f(qelt(m,i,j)))
+      m
+
+    map(f,m,n) ==
+      (nrows(m) ^= nrows(n)) or (ncols(m) ^= ncols(n)) =>
+        error "map: arguments must have same dimensions"
+      ans := new(nrows m,ncols m,NIL$Lisp)
+      for i in minRowIndex(m)..maxRowIndex(m) repeat
+        for j in minColIndex(m)..maxColIndex(m) repeat
+          qsetelt_!(ans,i,j,f(qelt(m,i,j),qelt(n,i,j)))
+      ans
+
+    map(f,m,n,r) ==
+      maxRow := max(maxRowIndex m,maxRowIndex n)
+      maxCol := max(maxColIndex m,maxColIndex n)
+      ans := new(max(nrows m,nrows n),max(ncols m,ncols n),NIL$Lisp)
+      for i in minRowIndex(m)..maxRow repeat
+        for j in minColIndex(m)..maxCol repeat
+          qsetelt_!(ans,i,j,f(elt(m,i,j,r),elt(n,i,j,r)))
+      ans
+
+    setRow_!(m,i,v) ==
+      i < minRowIndex(m) or i > maxRowIndex(m) =>
+        error "setRow!: index out of range"
+      for j in minColIndex(m)..maxColIndex(m) _
+        for k in minIndex(v)..maxIndex(v) repeat
+          qsetelt_!(m,i,j,v.k)
+      m
+
+    setColumn_!(m,j,v) ==
+      j < minColIndex(m) or j > maxColIndex(m) =>
+        error "setColumn!: index out of range"
+      for i in minRowIndex(m)..maxRowIndex(m) _
+        for k in minIndex(v)..maxIndex(v) repeat
+          qsetelt_!(m,i,j,v.k)
+      m
+
+    if R has _= : (R,R) -> Boolean then
+
+      m = n ==
+        eq?(m,n) => true
+        (nrows(m) ^= nrows(n)) or (ncols(m) ^= ncols(n)) => false
+        for i in minRowIndex(m)..maxRowIndex(m) repeat
+          for j in minColIndex(m)..maxColIndex(m) repeat
+            not (qelt(m,i,j) = qelt(n,i,j)) => return false
+        true
+
+      member?(r,m) ==
+        for i in minRowIndex(m)..maxRowIndex(m) repeat
+          for j in minColIndex(m)..maxColIndex(m) repeat
+            qelt(m,i,j) = r => return true
+        false
+
+      count(r:R,m:%) == count(#1 = r,m)
+
+    if Row has shallowlyMutable then
+
+      row(m,i) ==
+        i < minRowIndex(m) or i > maxRowIndex(m) =>
+          error "row: index out of range"
+        v : Row := new(ncols m,NIL$Lisp)
+        for j in minColIndex(m)..maxColIndex(m) _
+          for k in minIndex(v)..maxIndex(v) repeat
+            qsetelt_!(v,k,qelt(m,i,j))
+        v
+
+    if Col has shallowlyMutable then
+
+      column(m,j) ==
+        j < minColIndex(m) or j > maxColIndex(m) =>
+          error "column: index out of range"
+        v : Col := new(nrows m,NIL$Lisp)
+        for i in minRowIndex(m)..maxRowIndex(m) _
+          for k in minIndex(v)..maxIndex(v) repeat
+            qsetelt_!(v,k,qelt(m,i,j))
+        v
+
+    if R has CoercibleTo(OutputForm) then
+
+      coerce(m:%) ==
+        l : List List OutputForm
+        l := [[qelt(m,i,j) :: OutputForm _
+                  for j in minColIndex(m)..maxColIndex(m)] _
+                  for i in minRowIndex(m)..maxRowIndex(m)]
+        matrix l
+
+@
+<<ARR2CAT.dotabb>>=
+"ARR2CAT"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=ARR2CAT"];
+"ARR2CAT" -> "HOAGG"
+
+@
+<<ARR2CAT.dotfull>>=
+"TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=ARR2CAT"];
+"TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))"
+    -> "HomogeneousAggregate(a:Type)"
+
+"TwoDimensionalArrayCategory(a:Type,d:IndexedOneDimensionalArray(a,b),e:IndexedOneDimensionalArray(a,c))"
+ [color=seagreen,href="bookvol10.2.pdf#nameddest=ARR2CAT"];
+"TwoDimensionalArrayCategory(a:Type,d:IndexedOneDimensionalArray(a,b),e:IndexedOneDimensionalArray(a,c))"
+-> "TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))"
+
+@
+<<ARR2CAT.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))"
+ [color=lightblue];
+"TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))"
+    -> "HomogeneousAggregate(a:Type)"
+
+"HomogeneousAggregate(a:Type)" [color=lightblue];
+"HomogeneousAggregate(a:Type)" -> "Aggregate()"
+"HomogeneousAggregate(a:Type)" -> "Evalable(a:Type)"
+"HomogeneousAggregate(a:Type)" -> "SetCategory()"
+
+"Evalable(a:Type)" [color="#00EE00"];
+
+"SetCategory()" [color=lightblue];
+"SetCategory()" -> "BasicType()"
+"SetCategory()" -> "CoercibleTo(OutputForm)"
+
+"BasicType()" [color=lightblue];
+"BasicType()" -> "Category"
+
+"CoercibleTo(OutputForm)" [color=seagreen];
+"CoercibleTo(OutputForm)" -> "CoercibleTo(a:Type)"
+
+"CoercibleTo(a:Type)" [color=lightblue];
+"CoercibleTo(a:Type)" -> "Category"
+
+"Aggregate()" [color=lightblue];
+"Aggregate()" -> "Type()"
+
+"Type()" [color=lightblue];
+"Type()" -> "Category"
+
+"Category" [color=lightblue];
+
+}
+
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \pagehead{BagAggregate}{BGAGG}
 \pagepic{ps/v102bagaggregate.ps}{BGAGG}{1.00}
 
@@ -2352,6 +3213,14 @@ digraph pic {
 \cross{BGAGG}{?\~{}=?} &&&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{BGAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  extract! : % -> S
@@ -2520,6 +3389,12 @@ digraph pic {
 \cross{CLAGG}{?\~{}=?} \\
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{CLAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  construct: List S -> %
@@ -2769,6 +3644,16 @@ digraph pic {
 \cross{IXAGG}{?=?} &&&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{IXAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\item {\bf \cross{IXAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  index? : (Index,%) -> Boolean
@@ -3107,7 +3992,7 @@ digraph pic {
 
 "SemiGroup()" [color=lightblue];
 "SemiGroup()" -> "SetCategory()"
-"SemiGroup()" -> "RepeatedSquaring(SemiGroup)"
+"SemiGroup()" -> "RepeatedSquaring(a:SemiGroup)"
 
 "SetCategory()" [color=lightblue];
 "SetCategory()" -> "BasicType()"
@@ -3122,8 +4007,8 @@ digraph pic {
 "CoercibleTo(a:Type)" [color=lightblue];
 "CoercibleTo(a:Type)" -> "Category"
 
-"RepeatedSquaring(SemiGroup)" [color="#00EE00"];
-"RepeatedSquaring(SemiGroup)" -> "RepeatedSquaring(a:SetCategory)"
+"RepeatedSquaring(a:SemiGroup)" [color="#00EE00"];
+"RepeatedSquaring(a:SemiGroup)" -> "RepeatedSquaring(a:SetCategory)"
 
 "RepeatedSquaring(a:SetCategory)" [color="#00EE00"];
 "RepeatedSquaring(a:SetCategory)" -> "Package"
@@ -3299,6 +4184,14 @@ digraph pic {
 \cross{RCAGG}{?=?} &&&&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{RCAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  children : % -> List %
@@ -3510,6 +4403,16 @@ digraph pic {
 \cross{BRAGG}{?.value} &&&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{BRAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\item {\bf \cross{BRAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  left : % -> %             
@@ -3902,6 +4805,12 @@ digraph pic {
 \cross{DIOPS}{?\~{}=?} &&&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{DIOPS}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  dictionary : List S -> %
@@ -4130,6 +5039,14 @@ digraph pic {
 \cross{DLAGG}{?.value} &&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{DLAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  concat! : (%,%) -> % if $ has shallowlyMutable
@@ -4305,6 +5222,14 @@ digraph pic {
 \cross{GROUP}{?\^{}?} &&&&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{GROUP}{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.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  inv : % -> %                         
@@ -4515,6 +5440,16 @@ digraph pic {
 \cross{LNAGG}{?.?} &&&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{LNAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\item {\bf \cross{LNAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  concat : (%,%) -> %
@@ -5057,6 +5992,12 @@ digraph pic {
 \cross{PRQAGG}{?\~{}=?} \\
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{PRQAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  max : % -> S
@@ -5224,6 +6165,12 @@ digraph pic {
 \cross{QUAGG}{?\~{}=?} &&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{QUAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are implemented by this category:
 \begin{verbatim}
  back : % -> S                        
@@ -5408,6 +6355,13 @@ digraph pic {
 \cross{SETAGG}{?\~{}=?} &&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{SETAGG}{partiallyOrderedSet}}
+is true if a set with $<$ which is transitive, but 
+not($a < b$ or $a = b$) does not necessarily imply $b<a$.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  brace : List S -> %
@@ -5678,6 +6632,12 @@ digraph pic {
 \cross{SKAGG}{?\~{}=?} &&&&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{SKAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  depth : % -> NonNegativeInteger       
@@ -5868,6 +6828,16 @@ digraph pic {
 \cross{URAGG}{?\~{}=?} \\
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{URAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\item {\bf \cross{URAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  concat : (S,%) -> %
@@ -6448,6 +7418,12 @@ digraph pic {
 \cross{DIAGG}{?=?} &&&
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{DIAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are implemented by this category:
 \begin{verbatim}
  dictionary : List S -> %
@@ -6899,6 +7875,14 @@ digraph pic {
 \cross{ELAGG}{?\~{}=? } \\
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{ELAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  concat! : (%,S) -> %
@@ -7195,6 +8179,20 @@ digraph pic {
 \cross{FLAGG}{?\~{}=?} &&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{FLAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{FLAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  copyInto! : (%,%,Integer) -> % 
@@ -7846,6 +8844,14 @@ digraph pic {
 \cross{STAGG}{?\~{}=?} &
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{STAGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are implemented by this category:
 \begin{verbatim}
  concat : (%,%) -> %                  
@@ -8211,6 +9217,14 @@ digraph pic {
 \cross{A1AGG}{?$>=$?} &&&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{A1AGG}{shallowlyMutable}}
+is true if its values have immediate components that are 
+updateable (mutable). Note: the properties of any component 
+domain are irrevelant to the shallowlyMutable proper.
+\end{itemize}
+
 These are implemented by this category:
 \begin{verbatim}
  any? : ((S -> Boolean),%) -> Boolean 
@@ -8686,6 +9700,12 @@ digraph pic {
 \cross{FSAGG}{?\~{}=?} \\
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{FSAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are implemented by this category:
 \begin{verbatim}
  brace : List S -> %                  
@@ -8984,6 +10004,12 @@ digraph pic {
 \cross{KDAGG}{?\~{}=?} \\
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{KDAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  remove! : (Key,%) -> Union(Entry,"failed")
@@ -10712,20 +11738,18 @@ StringAggregate: Category == OneDimensionalArrayAggregate Character with
       ++ replace(s,i..j,t) replaces the substring \axiom{s(i..j)} 
       ++ of s by string t.
     position	    : (%, %, Integer) -> Integer
-      ++ position(s,t,i) returns the position j of the substring s in string t,
-      ++ where \axiom{j >= i} is required.
+      ++ position(s,t,i) returns the position j of the substring s in 
+      ++ string t, where \axiom{j >= i} is required.
     position	    : (CharacterClass, %, Integer) -> Integer
       ++ position(cc,t,i) returns the position \axiom{j >= i} in t of
       ++ the first character belonging to cc.
     coerce	    : Character -> %
       ++ coerce(c) returns c as a string s with the character c.
-
     split: (%, Character) -> List %
       ++ split(s,c) returns a list of substrings delimited by character c.
     split: (%, CharacterClass) -> List %
       ++ split(s,cc) returns a list of substrings delimited by 
       ++ characters in cc.
-
     trim: (%, Character) -> %
       ++ trim(s,c) returns s with all characters c deleted from right
       ++ and left ends.
@@ -10759,7 +11783,6 @@ StringAggregate: Category == OneDimensionalArrayAggregate Character with
  add
    trim(s: %, c:  Character)	  == leftTrim(rightTrim(s, c),	c)
    trim(s: %, cc: CharacterClass) == leftTrim(rightTrim(s, cc), cc)
-
    lowerCase s		 == lowerCase_! copy s
    upperCase s		 == upperCase_! copy s
    prefix?(s, t)	 == substring?(s, t, minIndex t)
@@ -10877,6 +11900,12 @@ digraph pic {
 \cross{TBAGG}{?\~{}=?} \\
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{TBAGG}{finiteAggregate}}
+is true if it is an aggregate with a finite number of elements.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  setelt : (%,Key,Entry) -> Entry
@@ -11068,7 +12097,6 @@ TableAggregate(Key:SetCategory, Entry:SetCategory): Category ==
      ++E Data:=Record(age:Integer,gender:String)
      ++E a1:AssociationList(String,Data):=table()
      ++E a1."tim":=[55,"male"]$Data
-
    table: List Record(key:Key,entry:Entry) -> %
      ++ table([x,y,...,z]) creates a table consisting of entries
      ++ \axiom{x,y,...,z}.
@@ -11776,6 +12804,14 @@ digraph pic {
 \cross{BMODULE}{?=?} &&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{BMODULE}{leftUnitary}}
+is true if $1 * x = x$ for all x.
+\item {\bf \cross{BMODULE}{rightUnitary}}
+is true if $x * 1 = x$ for all x.
+\end{itemize}
+
 These exports come from LeftModule(R:Ring):
 \begin{verbatim}
  0 : () -> %                          
@@ -12756,6 +13792,14 @@ digraph pic {
 \cross{RING}{?=?} &&&&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{RING}{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.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  characteristic : () -> NonNegativeInteger
@@ -12894,6 +13938,7 @@ digraph pic {
 \pagepic{ps/v102characteristicnonzero.ps}{CHARNZ}{0.90}
 
 {\bf See:}\\
+\pageto{FiniteRankAlgebra}{FINRALG}
 \pagefrom{Ring}{RING}
 
 {\bf Exports:}\\
@@ -13032,6 +14077,7 @@ digraph pic {
 \pagepic{ps/v102characteristiczero.ps}{CHARZ}{0.90}
 
 {\bf See:}\\
+\pageto{FiniteRankAlgebra}{FINRALG}
 \pagefrom{Ring}{RING}
 
 {\bf Exports:}\\
@@ -13109,9 +14155,9 @@ CharacteristicZero():Category == Ring
 
 @
 <<CHARZ.dotfull>>=
-"CharacteristicNonZero()"
+"CharacteristicZero()"
  [color=lightblue,href="bookvol10.2.pdf#nameddest=CHARZ"];
-"CharacteristicNonZero()" -> "Ring()"
+"CharacteristicZero()" -> "Ring()"
 
 @
 <<CHARZ.dotpic>>=
@@ -13162,6 +14208,7 @@ digraph pic {
 
 {\bf See:}\\
 \pageto{IntegralDomain}{INTDOM}
+\pageto{MonogenicAlgebra}{MONOGEN}
 \pagefrom{BiModule}{BMODULE}
 \pagefrom{Ring}{RING}
 
@@ -13188,6 +14235,13 @@ digraph pic {
 \cross{COMRING}{?=?} &
 \end{tabular}
 
+{\bf Attributes:}
+\begin{itemize}
+\item {\bf \cross{COMRING}{commutative("*")}}
+is true if it has an operation $"*": (D,D) -> D$
+which is commutative.
+\end{itemize}
+
 
 These exports come from Ring():
 \begin{verbatim}
@@ -13509,6 +14563,12 @@ digraph pic {
 \cross{ENTIRER}{?=?} \\
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{ENTIRER}{noZeroDivisors}}
+is true if $x * y ~= 0$ implies both x and y are non-zero.
+\end{itemize}
+
 These exports come from Ring():
 \begin{verbatim}
  0 : () -> %
@@ -13633,6 +14693,7 @@ digraph pic {
 
 {\bf See:}\\
 \pageto{FullyLinearlyExplicitRingOver}{FLINEXP}
+\pageto{MonogenicAlgebra}{MONOGEN}
 \pagefrom{Ring}{RING}
 
 {\bf Exports:}\\
@@ -14700,6 +15761,7 @@ digraph pic {
 
 {\bf See:}\\
 \pageto{DivisionRing}{DIVRING}
+\pageto{FiniteRankAlgebra}{FINRALG}
 \pageto{IntegralDomain}{INTDOM}
 \pagefrom{Module}{MODULE}
 \pagefrom{Ring}{RING}
@@ -15230,6 +16292,14 @@ digraph pic {
 \cross{INTDOM}{?=?} &
 \end{tabular}
 
+{\bf Attributes Used:}
+\begin{itemize}
+\item {\bf \cross{INTDOM}{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)}.
+\end{itemize}
+
 These are directly exported but not implemented:
 \begin{verbatim}
  exquo : (%,%) -> Union(%,"failed")
@@ -16708,6 +17778,7 @@ digraph pic {
 \pagepic{ps/v102field.ps}{FIELD}{1.00}
 
 {\bf See:}\\
+\pageto{FiniteRankAlgebra}{FINRALG}
 \pagefrom{DivisionRing}{DIVRING}
 \pagefrom{EuclideanDomain}{EUCDOM}
 \pagefrom{UniqueFactorizationDomain}{UFD}
@@ -16758,6 +17829,17 @@ digraph pic {
 \cross{FIELD}{?\~{}=?} &&&
 \end{tabular}
 
+{\bf Attributes Exported:}
+\begin{itemize}
+\item {\bf \cross{FIELD}{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{FIELD}{canonicalsClosed}}
+is true if\\
+{\tt unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
+\end{itemize}
+
 These are implemented by this category:
 \begin{verbatim}
  associates? : (%,%) -> Boolean       
@@ -16920,14 +18002,652 @@ digraph pic {
 }
 
 @
-\chapter{Temporary Placeholders}
-\pagehead{Evalable}{EVALAB}
-\pageto{HomogeneousAggregate}{HOAGG}
-<<EVALAB.dotfull>>=
-"Evalable(a:Type)"
- [color="#00EE00",href="bookvol10.2.pdf#nameddest=EVALAB"];
+\chapter{Category Layer 17}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{FiniteRankAlgebra}{FINRALG}
+\pagepic{ps/v102finiterankalgebra.ps}{FINRALG}{0.45}
+
+{\bf See:}\\
+\pageto{FramedAlgebra}{FRAMALG}
+\pagefrom{Algebra}{ALGEBRA}
+\pagefrom{CharacteristicNonZero}{CHARNZ}
+\pagefrom{CharacteristicZero}{CHARZ}
+\pagefrom{Field}{FIELD}
+
+{\bf Exports:}\\
+\begin{tabular}{lll}
+\cross{FINRALG}{0} &
+\cross{FINRALG}{1} &
+\cross{FINRALG}{characteristic} \\
+\cross{FINRALG}{characteristicPolynomial} &
+\cross{FINRALG}{charthRoot} &
+\cross{FINRALG}{coerce} \\
+\cross{FINRALG}{coordinates} &
+\cross{FINRALG}{discriminant} &
+\cross{FINRALG}{hash} \\
+\cross{FINRALG}{latex} &
+\cross{FINRALG}{minimalPolynomial} &
+\cross{FINRALG}{norm} \\
+\cross{FINRALG}{one?} &
+\cross{FINRALG}{rank} &
+\cross{FINRALG}{recip} \\
+\cross{FINRALG}{regularRepresentation} &
+\cross{FINRALG}{represents} &
+\cross{FINRALG}{sample} \\
+\cross{FINRALG}{subtractIfCan} &
+\cross{FINRALG}{trace} &
+\cross{FINRALG}{traceMatrix} \\
+\cross{FINRALG}{zero?} &
+\cross{FINRALG}{?*?} &
+\cross{FINRALG}{?**?} \\
+\cross{FINRALG}{?+?} &
+\cross{FINRALG}{?-?} &
+\cross{FINRALG}{-?} \\
+\cross{FINRALG}{?=?} &
+\cross{FINRALG}{?\^{}?} &
+\cross{FINRALG}{?\~{}=?} \\
+\end{tabular}
+
+These are directly exported but not implemented:
+\begin{verbatim}
+ characteristicPolynomial : % -> UP
+ coordinates : (%,Vector %) -> Vector R
+ minimalPolynomial : % -> UP if R has FIELD
+ norm : % -> R
+ rank : () -> PositiveInteger
+ trace : % -> R                       
+\end{verbatim}
+
+These are implemented by this category:
+\begin{verbatim}
+ coordinates : (Vector %,Vector %) -> Matrix R
+ discriminant : Vector % -> R         
+ regularRepresentation : (%,Vector %) -> Matrix R
+ represents : (Vector R,Vector %) -> %
+ traceMatrix : Vector % -> Matrix R
+\end{verbatim}
+
+These exports come from Algebra(R:CommutativeRing):
+\begin{verbatim}
+ 0 : () -> %
+ 1 : () -> %                          
+ characteristic : () -> NonNegativeInteger
+ coerce : Integer -> %                
+ coerce : % -> OutputForm
+ hash : % -> SingleInteger
+ latex : % -> String                  
+ one? : % -> Boolean                  
+ recip : % -> Union(%,"failed")       
+ sample : () -> %
+ subtractIfCan : (%,%) -> Union(%,"failed")
+ zero? : % -> Boolean
+ ?+? : (%,%) -> %                     
+ ?=? : (%,%) -> Boolean
+ ?~=? : (%,%) -> Boolean              
+ ?*? : (%,%) -> %                     
+ ?*? : (Integer,%) -> %
+ ?*? : (PositiveInteger,%) -> %       
+ ?*? : (NonNegativeInteger,%) -> %
+ ?-? : (%,%) -> %
+ -? : % -> %                          
+ ?**? : (%,PositiveInteger) -> %
+ ?**? : (%,NonNegativeInteger) -> %
+ ?^? : (%,PositiveInteger) -> %       
+ ?^? : (%,NonNegativeInteger) -> %
+\end{verbatim}
+
+These exports come from Field():
+\begin{verbatim}
+ ?*? : (R,%) -> %                     
+ ?*? : (%,R) -> %
+ coerce : R -> %
+\end{verbatim}
+
+These exports come from CharacteristicNonZero():
+\begin{verbatim}
+ charthRoot : % -> Union(%,"failed") if R has CHARNZ
+\end{verbatim}
+
+These exports come from CharacteristicZero():
+\begin{verbatim}
+\end{verbatim}
+
+<<category FINRALG FiniteRankAlgebra>>=
+)abbrev category FINRALG FiniteRankAlgebra
+++ Author: Barry Trager
+++ Date Created:
+++ Date Last Updated:
+++ Basic Functions:
+++ Related Constructors:
+++ Also See:
+++ AMS Classifications:
+++ Keywords:
+++ References:
+++ Description:
+++ A FiniteRankAlgebra is an algebra over a commutative ring R which
+++ is a free R-module of finite rank.
+
+FiniteRankAlgebra(R:CommutativeRing, UP:UnivariatePolynomialCategory R):
+ Category == Algebra R with
+    rank                    : () -> PositiveInteger
+      ++ rank() returns the rank of the algebra.
+    regularRepresentation   : (% , Vector %) -> Matrix R
+      ++ regularRepresentation(a,basis) returns the matrix of the
+      ++ linear map defined by left multiplication by \spad{a} with respect
+      ++ to the basis \spad{basis}.
+    trace                   : %  -> R
+      ++ trace(a) returns the trace of the regular representation
+      ++ of \spad{a} with respect to any basis.
+    norm                    : %  -> R
+      ++ norm(a) returns the determinant of the regular representation
+      ++ of \spad{a} with respect to any basis.
+    coordinates             : (%, Vector %) -> Vector R
+      ++ coordinates(a,basis) returns the coordinates of \spad{a} with
+      ++ respect to the basis \spad{basis}.
+    coordinates             : (Vector %, Vector %) -> Matrix R
+      ++ coordinates([v1,...,vm], basis) returns the coordinates of the
+      ++ vi's with to the basis \spad{basis}.  The coordinates of vi are
+      ++ contained in the ith row of the matrix returned by this
+      ++ function.
+    represents              : (Vector R, Vector %) -> %
+      ++ represents([a1,..,an],[v1,..,vn]) returns \spad{a1*v1+...+an*vn}.
+    discriminant            : Vector % -> R
+      ++ discriminant([v1,..,vn]) returns
+      ++ \spad{determinant(traceMatrix([v1,..,vn]))}.
+    traceMatrix             : Vector % -> Matrix R
+      ++ traceMatrix([v1,..,vn]) is the n-by-n matrix ( Tr(vi * vj) )
+    characteristicPolynomial: % -> UP
+      ++ characteristicPolynomial(a) returns the characteristic
+      ++ polynomial of the regular representation of \spad{a} with respect
+      ++ to any basis.
+    if R has Field then minimalPolynomial : % -> UP
+      ++ minimalPolynomial(a) returns the minimal polynomial of \spad{a}.
+    if R has CharacteristicZero then CharacteristicZero
+    if R has CharacteristicNonZero then CharacteristicNonZero
+
+  add
+
+    discriminant v == determinant traceMatrix v
+
+    coordinates(v:Vector %, b:Vector %) ==
+      m := new(#v, #b, 0)$Matrix(R)
+      for i in minIndex v .. maxIndex v for j in minRowIndex m .. repeat
+        setRow_!(m, j, coordinates(qelt(v, i), b))
+      m
+
+    represents(v, b) ==
+      m := minIndex v - 1
+      _+/[v(i+m) * b(i+m) for i in 1..rank()]
+
+    traceMatrix v ==
+      matrix [[trace(v.i*v.j) for j in minIndex v..maxIndex v]$List(R)
+               for i in minIndex v .. maxIndex v]$List(List R)
+
+    regularRepresentation(x, b) ==
+      m := minIndex b - 1
+      matrix
+       [parts coordinates(x*b(i+m),b) for i in 1..rank()]$List(List R)
+
+@
+<<FINRALG.dotabb>>=
+"FINRALG"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FINRALG"];
+"FINRALG" -> "ALGEBRA"
+"FINRALG" -> "FIELD"
+"FINRALG" -> "CHARNZ"
+"FINRALG" -> "CHARZ"
+
+@
+<<FINRALG.dotfull>>=
+"FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))"
+ [color=lightblue,href="bookvol10.2.pdf#nameddest=FINRALG"];
+"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()"
+
+@
+<<FINRALG.dotpic>>=
+digraph pic {
+ fontsize=10;
+ bgcolor="#FFFF66";
+ node [shape=box, color=white, style=filled];
+
+"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];
+}
+
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\pagehead{MonogenicAlgebra}{MONOGEN}
+\pagepic{ps/v102monogenicalgebra.ps}{MONOGEN}{0.70}
+
+{\bf See:}\\
+\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];
+}
+@
+\chapter{Category Layer 18}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\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}
+
+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 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{The bootstrap code}
 \section{ABELGRP.lsp BOOTSTRAP} 
 {\bf ABELGRP} depends on a chain of
@@ -22862,6 +24582,8 @@ Note that this code is not included in the generated catdef.spad file.
 <<category AGG Aggregate>>
 <<category ALAGG AssociationListAggregate>>
 <<category ALGEBRA Algebra>>
+<<category ARR2CAT TwoDimensionalArrayCategory>>
+<<category ATTREG AttributeRegistry>>
 <<category A1AGG OneDimensionalArrayAggregate>>
 <<category BASTYPE BasicType>>
 <<category BGAGG BagAggregate>>
@@ -22888,8 +24610,11 @@ Note that this code is not included in the generated catdef.spad file.
 <<category EVALAB Evalable>>
 <<category FIELD Field>>
 <<category FINITE Finite>>
+<<category FINRALG FiniteRankAlgebra>>
 <<category FLAGG FiniteLinearAggregate>>
 <<category FLINEXP FullyLinearlyExplicitRingOver>>
+<<category FRAMALG FramedAlgebra>>
+<<category FRETRCT FullyRetractableTo>>
 <<category FSAGG FiniteSetAggregate>>
 <<category GCDDOM GcdDomain>>
 <<category GROUP Group>>
@@ -22907,6 +24632,7 @@ Note that this code is not included in the generated catdef.spad file.
 <<category LSAGG ListAggregate>>
 <<category MODULE Module>>
 <<category MONOID Monoid>>
+<<category MONOGEN MonogenicAlgebra>>
 <<category MDAGG MultiDictionary>>
 <<category MSETAGG MultisetAggregate>>
 <<category OAGROUP OrderedAbelianGroup>>
@@ -22949,15 +24675,15 @@ digraph dotabb {
  bgcolor="#FFFF66";
  node [shape=box, color=white, style=filled];
 
-"CATEGORY"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=CATEGORY"];
-
+<<CATEGORY.dotabb>>
 <<ABELGRP.dotabb>>
 <<ABELMON.dotabb>>
 <<ABELSG.dotabb>>
 <<AGG.dotabb>>
 <<ALAGG.dotabb>>
 <<ALGEBRA.dotabb>>
+<<ARR2CAT.dotabb>>
+<<ATTREG.dotabb>>
 <<A1AGG.dotabb>>
 <<BASTYPE.dotabb>>
 <<BGAGG.dotabb>>
@@ -22983,8 +24709,11 @@ digraph dotabb {
 <<EVALAB.dotabb>>
 <<FIELD.dotabb>>
 <<FINITE.dotabb>>
+<<FINRALG.dotabb>>
 <<FLAGG.dotabb>>
 <<FLINEXP.dotabb>>
+<<FRAMALG.dotabb>>
+<<FRETRCT.dotabb>>
 <<FSAGG.dotabb>>
 <<GCDDOM.dotabb>>
 <<HOAGG.dotabb>>
@@ -23002,6 +24731,7 @@ digraph dotabb {
 <<MODULE.dotabb>>
 <<MDAGG.dotabb>>
 <<MONOID.dotabb>>
+<<MONOGEN.dotabb>>
 <<MSETAGG.dotabb>>
 <<OAGROUP.dotabb>>
 <<OAMON.dotabb>>
@@ -23046,15 +24776,15 @@ digraph dotfull {
  bgcolor="#FFFF66";
  node [shape=box, color=white, style=filled];
 
-"Category"
- [color=lightblue,href="bookvol10.2.pdf#nameddest=CATEGORY"];
-
+<<CATEGORY.dotfull>>
 <<ABELGRP.dotfull>>
 <<ABELMON.dotfull>>
 <<ABELSG.dotfull>>
 <<AGG.dotfull>>
 <<ALAGG.dotfull>>
 <<ALGEBRA.dotfull>>
+<<ARR2CAT.dotfull>>
+<<ATTREG.dotfull>>
 <<A1AGG.dotfull>>
 <<BASTYPE.dotfull>>
 <<BGAGG.dotfull>>
@@ -23080,8 +24810,11 @@ digraph dotfull {
 <<EVALAB.dotfull>>
 <<FIELD.dotfull>>
 <<FINITE.dotfull>>
+<<FINRALG.dotfull>>
 <<FLAGG.dotfull>>
 <<FLINEXP.dotfull>>
+<<FRAMALG.dotfull>>
+<<FRETRCT.dotfull>>
 <<FSAGG.dotfull>>
 <<GCDDOM.dotfull>>
 <<HOAGG.dotfull>>
@@ -23099,6 +24832,7 @@ digraph dotfull {
 <<MODULE.dotfull>>
 <<MDAGG.dotfull>>
 <<MONOID.dotfull>>
+<<MONOGEN.dotfull>>
 <<MSETAGG.dotfull>>
 <<OAGROUP.dotfull>>
 <<OAMON.dotfull>>
diff --git a/books/ps/v102attributeregistry.ps b/books/ps/v102attributeregistry.ps
new file mode 100644
index 0000000..3521cbf
--- /dev/null
+++ b/books/ps/v102attributeregistry.ps
@@ -0,0 +1,289 @@
+%!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 168 152
+%%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 168 152
+%%PageOrientation: Portrait
+gsave
+36 36 132 116 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 114 lineto
+130 114 lineto
+130 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 114 lineto
+130 114 lineto
+130 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% AttributeRegistry()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 124 108 moveto
+0 108 lineto
+0 72 lineto
+124 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 124 108 moveto
+0 108 lineto
+0 72 lineto
+124 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+8 85 moveto
+(AttributeRegistry\(\))
+[9.84 3.84 3.84 5.04 3.84 6.96 6.96 3.84 6.24 9.12 6.24 6.96 3.84 5.28 3.84 5.04 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% Category
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 96 36 moveto
+28 36 lineto
+28 0 lineto
+96 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 96 36 moveto
+28 36 lineto
+28 0 lineto
+96 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+36 13 moveto
+(Category)
+[9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96]
+xshow
+end grestore
+end grestore
+% AttributeRegistry()->Category
+newpath 62 72 moveto
+62 64 62 55 62 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 66 46 moveto
+62 36 lineto
+59 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 66 46 moveto
+62 36 lineto
+59 46 lineto
+closepath
+stroke
+end grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
diff --git a/books/ps/v102category.ps b/books/ps/v102category.ps
new file mode 100644
index 0000000..7027c8c
--- /dev/null
+++ b/books/ps/v102category.ps
@@ -0,0 +1,243 @@
+%!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 112 80
+%%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 112 80
+%%PageOrientation: Portrait
+gsave
+36 36 76 44 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 42 lineto
+74 42 lineto
+74 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 42 lineto
+74 42 lineto
+74 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% Category
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 68 36 moveto
+0 36 lineto
+0 0 lineto
+68 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 68 36 moveto
+0 36 lineto
+0 0 lineto
+68 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+8 13 moveto
+(Category)
+[9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96]
+xshow
+end grestore
+end grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
diff --git a/books/ps/v102finiterankalgebra.ps b/books/ps/v102finiterankalgebra.ps
new file mode 100644
index 0000000..869ea25
--- /dev/null
+++ b/books/ps/v102finiterankalgebra.ps
@@ -0,0 +1,702 @@
+%!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 725 224
+%%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 725 224
+%%PageOrientation: Portrait
+gsave
+36 36 689 188 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 186 lineto
+687 186 lineto
+687 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 186 lineto
+687 186 lineto
+687 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))
+[ /Rect [ 135 144 583 180 ]
+  /Border [ 0 0 0 ]
+  /Action << /Subtype /URI /URI (bookvol10.2.pdf#nameddest=FINRALG) >>
+  /Subtype /Link
+/ANN pdfmark
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 583 180 moveto
+135 180 lineto
+135 144 lineto
+583 144 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 583 180 moveto
+135 180 lineto
+135 144 lineto
+583 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+142 157 moveto
+(FiniteRankAlgebra\(a:CommutativeRing,b:UnivariatePolynomialCategory\(a\)\))
+[7.44 3.84 6.96 3.84 3.84 6.24 9.36 6.24 6.96 6.96 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
+end grestore
+end grestore
+% Algebra(a:CommutativeRing)
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 184 108 moveto
+0 108 lineto
+0 72 lineto
+184 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 184 108 moveto
+0 108 lineto
+0 72 lineto
+184 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+8 85 moveto
+(Algebra\(a:CommutativeRing\))
+[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 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->Algebra(a:CommutativeRing)
+newpath 292 144 moveto
+254 134 207 121 169 111 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 170 108 moveto
+159 108 lineto
+168 114 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 170 108 moveto
+159 108 lineto
+168 114 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 576 108 moveto
+522 108 lineto
+522 72 lineto
+576 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 576 108 moveto
+522 108 lineto
+522 72 lineto
+576 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+530 85 moveto
+(Field\(\))
+[7.44 3.84 6.24 3.84 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->Field()
+newpath 416 144 moveto
+443 135 475 123 512 108 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 514 111 moveto
+522 104 lineto
+511 104 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 514 111 moveto
+522 104 lineto
+511 104 lineto
+closepath
+stroke
+end grestore
+% CharacteristicNonZero()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 356 108 moveto
+202 108 lineto
+202 72 lineto
+356 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 356 108 moveto
+202 108 lineto
+202 72 lineto
+356 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+210 85 moveto
+(CharacteristicNonZero\(\))
+[9.36 6.96 6.24 4.8 6.24 6.24 3.84 6.24 5.04 3.84 5.28 3.84 3.84 6.24 9.84 6.96 6.96 8.64 6.24 4.8 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->CharacteristicNonZero()
+newpath 339 144 moveto
+329 135 317 124 306 115 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 309 113 moveto
+299 108 lineto
+304 118 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 309 113 moveto
+299 108 lineto
+304 118 lineto
+closepath
+stroke
+end grestore
+% CharacteristicZero()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 504 108 moveto
+374 108 lineto
+374 72 lineto
+504 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 504 108 moveto
+374 108 lineto
+374 72 lineto
+504 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+382 85 moveto
+(CharacteristicZero\(\))
+[9.36 6.96 6.24 4.8 6.24 6.24 3.84 6.24 5.04 3.84 5.28 3.84 3.84 6.24 8.64 6.24 4.8 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->CharacteristicZero()
+newpath 379 144 moveto
+389 135 401 124 412 115 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 414 118 moveto
+419 108 lineto
+409 113 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 414 118 moveto
+419 108 lineto
+409 113 lineto
+closepath
+stroke
+end grestore
+% RING...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 309 36 moveto
+249 36 lineto
+249 0 lineto
+309 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 309 36 moveto
+249 36 lineto
+249 0 lineto
+309 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+256 13 moveto
+(RING...)
+[9.36 4.56 9.84 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Algebra(a:CommutativeRing)->RING...
+newpath 139 72 moveto
+170 60 210 45 239 34 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 241 37 moveto
+249 30 lineto
+238 30 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 241 37 moveto
+249 30 lineto
+238 30 lineto
+closepath
+stroke
+end grestore
+% MODULE...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 136 36 moveto
+48 36 lineto
+48 0 lineto
+136 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 136 36 moveto
+48 36 lineto
+48 0 lineto
+136 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+56 13 moveto
+(MODULE...)
+[12.48 10.08 10.08 10.08 8.64 8.64 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Algebra(a:CommutativeRing)->MODULE...
+newpath 92 72 moveto
+92 64 92 55 92 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 96 46 moveto
+92 36 lineto
+89 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 96 46 moveto
+92 36 lineto
+89 46 lineto
+closepath
+stroke
+end grestore
+% EUCDOM...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 503 36 moveto
+415 36 lineto
+415 0 lineto
+503 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 503 36 moveto
+415 36 lineto
+415 0 lineto
+503 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+423 13 moveto
+(EUCDOM...)
+[8.64 10.08 9.36 10.08 10.08 12.48 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Field()->EUCDOM...
+newpath 526 72 moveto
+515 63 501 52 489 42 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 491 39 moveto
+481 36 lineto
+487 45 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 491 39 moveto
+481 36 lineto
+487 45 lineto
+closepath
+stroke
+end grestore
+% UFD...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 577 36 moveto
+521 36 lineto
+521 0 lineto
+577 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 577 36 moveto
+521 36 lineto
+521 0 lineto
+577 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+529 13 moveto
+(UFD...)
+[10.08 7.68 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Field()->UFD...
+newpath 549 72 moveto
+549 64 549 55 549 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 553 46 moveto
+549 36 lineto
+546 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 553 46 moveto
+549 36 lineto
+546 46 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 681 36 moveto
+595 36 lineto
+595 0 lineto
+681 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 681 36 moveto
+595 36 lineto
+595 0 lineto
+681 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+602 13 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 571 72 moveto
+582 63 596 52 608 42 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 610 45 moveto
+616 36 lineto
+606 39 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 610 45 moveto
+616 36 lineto
+606 39 lineto
+closepath
+stroke
+end grestore
+% CharacteristicNonZero()->RING...
+newpath 279 72 moveto
+279 64 279 55 279 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 283 46 moveto
+279 36 lineto
+276 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 283 46 moveto
+279 36 lineto
+276 46 lineto
+closepath
+stroke
+end grestore
+% CharacteristicZero()->RING...
+newpath 399 72 moveto
+374 61 343 47 318 36 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 320 33 moveto
+309 32 lineto
+317 39 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 320 33 moveto
+309 32 lineto
+317 39 lineto
+closepath
+stroke
+end grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
diff --git a/books/ps/v102framedalgebra.ps b/books/ps/v102framedalgebra.ps
new file mode 100644
index 0000000..5391e57
--- /dev/null
+++ b/books/ps/v102framedalgebra.ps
@@ -0,0 +1,748 @@
+%!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 725 296
+%%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 725 296
+%%PageOrientation: Portrait
+gsave
+36 36 689 260 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 258 lineto
+687 258 lineto
+687 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 258 lineto
+687 258 lineto
+687 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 573 252 moveto
+145 252 lineto
+145 216 lineto
+573 216 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 573 252 moveto
+145 252 lineto
+145 216 lineto
+573 216 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+152 229 moveto
+(FramedAlgebra\(a:CommutativeRing,b:UnivariatePolynomialCategory\(a\)\))
+[7.44 4.8 6.24 10.8 6.24 6.96 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
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))
+[ /Rect [ 135 144 583 180 ]
+  /Border [ 0 0 0 ]
+  /Action << /Subtype /URI /URI (bookvol10.2.pdf#nameddest=FINRALG) >>
+  /Subtype /Link
+/ANN pdfmark
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 583 180 moveto
+135 180 lineto
+135 144 lineto
+583 144 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 583 180 moveto
+135 180 lineto
+135 144 lineto
+583 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+142 157 moveto
+(FiniteRankAlgebra\(a:CommutativeRing,b:UnivariatePolynomialCategory\(a\)\))
+[7.44 3.84 6.96 3.84 3.84 6.24 9.36 6.24 6.96 6.96 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
+end grestore
+end grestore
+% FramedAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))
+newpath 359 216 moveto
+359 208 359 199 359 190 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 363 190 moveto
+359 180 lineto
+356 190 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 363 190 moveto
+359 180 lineto
+356 190 lineto
+closepath
+stroke
+end grestore
+% Algebra(a:CommutativeRing)
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 184 108 moveto
+0 108 lineto
+0 72 lineto
+184 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 184 108 moveto
+0 108 lineto
+0 72 lineto
+184 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+8 85 moveto
+(Algebra\(a:CommutativeRing\))
+[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 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->Algebra(a:CommutativeRing)
+newpath 292 144 moveto
+254 134 207 121 169 111 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 170 108 moveto
+159 108 lineto
+168 114 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 170 108 moveto
+159 108 lineto
+168 114 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 576 108 moveto
+522 108 lineto
+522 72 lineto
+576 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 576 108 moveto
+522 108 lineto
+522 72 lineto
+576 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+530 85 moveto
+(Field\(\))
+[7.44 3.84 6.24 3.84 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->Field()
+newpath 416 144 moveto
+443 135 475 123 512 108 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 514 111 moveto
+522 104 lineto
+511 104 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 514 111 moveto
+522 104 lineto
+511 104 lineto
+closepath
+stroke
+end grestore
+% CharacteristicNonZero()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 356 108 moveto
+202 108 lineto
+202 72 lineto
+356 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 356 108 moveto
+202 108 lineto
+202 72 lineto
+356 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+210 85 moveto
+(CharacteristicNonZero\(\))
+[9.36 6.96 6.24 4.8 6.24 6.24 3.84 6.24 5.04 3.84 5.28 3.84 3.84 6.24 9.84 6.96 6.96 8.64 6.24 4.8 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->CharacteristicNonZero()
+newpath 339 144 moveto
+329 135 317 124 306 115 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 309 113 moveto
+299 108 lineto
+304 118 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 309 113 moveto
+299 108 lineto
+304 118 lineto
+closepath
+stroke
+end grestore
+% CharacteristicZero()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 504 108 moveto
+374 108 lineto
+374 72 lineto
+504 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 504 108 moveto
+374 108 lineto
+374 72 lineto
+504 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+382 85 moveto
+(CharacteristicZero\(\))
+[9.36 6.96 6.24 4.8 6.24 6.24 3.84 6.24 5.04 3.84 5.28 3.84 3.84 6.24 8.64 6.24 4.8 6.96 4.56 4.56]
+xshow
+end grestore
+end grestore
+% FiniteRankAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->CharacteristicZero()
+newpath 379 144 moveto
+389 135 401 124 412 115 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 414 118 moveto
+419 108 lineto
+409 113 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 414 118 moveto
+419 108 lineto
+409 113 lineto
+closepath
+stroke
+end grestore
+% RING...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 309 36 moveto
+249 36 lineto
+249 0 lineto
+309 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 309 36 moveto
+249 36 lineto
+249 0 lineto
+309 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+256 13 moveto
+(RING...)
+[9.36 4.56 9.84 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Algebra(a:CommutativeRing)->RING...
+newpath 139 72 moveto
+170 60 210 45 239 34 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 241 37 moveto
+249 30 lineto
+238 30 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 241 37 moveto
+249 30 lineto
+238 30 lineto
+closepath
+stroke
+end grestore
+% MODULE...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 136 36 moveto
+48 36 lineto
+48 0 lineto
+136 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 136 36 moveto
+48 36 lineto
+48 0 lineto
+136 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+56 13 moveto
+(MODULE...)
+[12.48 10.08 10.08 10.08 8.64 8.64 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Algebra(a:CommutativeRing)->MODULE...
+newpath 92 72 moveto
+92 64 92 55 92 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 96 46 moveto
+92 36 lineto
+89 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 96 46 moveto
+92 36 lineto
+89 46 lineto
+closepath
+stroke
+end grestore
+% EUCDOM...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 503 36 moveto
+415 36 lineto
+415 0 lineto
+503 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 503 36 moveto
+415 36 lineto
+415 0 lineto
+503 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+423 13 moveto
+(EUCDOM...)
+[8.64 10.08 9.36 10.08 10.08 12.48 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Field()->EUCDOM...
+newpath 526 72 moveto
+515 63 501 52 489 42 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 491 39 moveto
+481 36 lineto
+487 45 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 491 39 moveto
+481 36 lineto
+487 45 lineto
+closepath
+stroke
+end grestore
+% UFD...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 577 36 moveto
+521 36 lineto
+521 0 lineto
+577 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 577 36 moveto
+521 36 lineto
+521 0 lineto
+577 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+529 13 moveto
+(UFD...)
+[10.08 7.68 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% Field()->UFD...
+newpath 549 72 moveto
+549 64 549 55 549 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 553 46 moveto
+549 36 lineto
+546 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 553 46 moveto
+549 36 lineto
+546 46 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 681 36 moveto
+595 36 lineto
+595 0 lineto
+681 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 681 36 moveto
+595 36 lineto
+595 0 lineto
+681 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+602 13 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 571 72 moveto
+582 63 596 52 608 42 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 610 45 moveto
+616 36 lineto
+606 39 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 610 45 moveto
+616 36 lineto
+606 39 lineto
+closepath
+stroke
+end grestore
+% CharacteristicNonZero()->RING...
+newpath 279 72 moveto
+279 64 279 55 279 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 283 46 moveto
+279 36 lineto
+276 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 283 46 moveto
+279 36 lineto
+276 46 lineto
+closepath
+stroke
+end grestore
+% CharacteristicZero()->RING...
+newpath 399 72 moveto
+374 61 343 47 318 36 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 320 33 moveto
+309 32 lineto
+317 39 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 320 33 moveto
+309 32 lineto
+317 39 lineto
+closepath
+stroke
+end grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
diff --git a/books/ps/v102fullyretractableto.ps b/books/ps/v102fullyretractableto.ps
new file mode 100644
index 0000000..6283575
--- /dev/null
+++ b/books/ps/v102fullyretractableto.ps
@@ -0,0 +1,335 @@
+%!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 214 224
+%%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 214 224
+%%PageOrientation: Portrait
+gsave
+36 36 178 188 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 186 lineto
+176 186 lineto
+176 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 186 lineto
+176 186 lineto
+176 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% FullyRetractableTo(a:Type)
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 170 180 moveto
+0 180 lineto
+0 144 lineto
+170 144 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 170 180 moveto
+0 180 lineto
+0 144 lineto
+170 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+8 157 moveto
+(FullyRetractableTo\(a:Type\))
+[7.44 6.96 3.84 3.6 6.96 9.12 6 3.84 4.8 6.24 6.24 4.08 6.24 6.96 3.84 6.24 7.44 6.96 4.56 6.24 3.84 7.2 6.96 6.96 6.24 4.56]
+xshow
+end grestore
+end grestore
+% RetractableTo(a:Type)
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 155 108 moveto
+15 108 lineto
+15 72 lineto
+155 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 155 108 moveto
+15 108 lineto
+15 72 lineto
+155 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+22 85 moveto
+(RetractableTo\(a:Type\))
+[9.12 6 3.84 4.8 6.24 6.24 4.08 6.24 6.96 3.84 6.24 7.44 6.96 4.56 6.24 3.84 7.2 6.96 6.96 6.24 4.56]
+xshow
+end grestore
+end grestore
+% FullyRetractableTo(a:Type)->RetractableTo(a:Type)
+newpath 85 144 moveto
+85 136 85 127 85 118 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 89 118 moveto
+85 108 lineto
+82 118 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 89 118 moveto
+85 108 lineto
+82 118 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 119 36 moveto
+51 36 lineto
+51 0 lineto
+119 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 119 36 moveto
+51 36 lineto
+51 0 lineto
+119 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+59 13 moveto
+(Category)
+[9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96]
+xshow
+end grestore
+end grestore
+% RetractableTo(a:Type)->Category
+newpath 85 72 moveto
+85 64 85 55 85 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 89 46 moveto
+85 36 lineto
+82 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 89 46 moveto
+85 36 lineto
+82 46 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
new file mode 100644
index 0000000..ceed5d3
--- /dev/null
+++ b/books/ps/v102monogenicalgebra.ps
@@ -0,0 +1,473 @@
+%!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 564 152
+%%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 564 152
+%%PageOrientation: Portrait
+gsave
+36 36 528 116 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 114 lineto
+526 114 lineto
+526 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 114 lineto
+526 114 lineto
+526 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))
+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
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 495 108 moveto
+45 108 lineto
+45 72 lineto
+495 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+52 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
+end grestore
+end grestore
+% FRAMALG...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 96 36 moveto
+0 36 lineto
+0 0 lineto
+96 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 96 36 moveto
+0 36 lineto
+0 0 lineto
+96 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+8 13 moveto
+(FRAMALG...)
+[7.68 9.36 10.08 12.48 10.08 8.64 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FRAMALG...
+newpath 214 72 moveto
+181 61 139 48 106 37 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 107 34 moveto
+96 34 lineto
+105 40 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 107 34 moveto
+96 34 lineto
+105 40 lineto
+closepath
+stroke
+end grestore
+% COMRING...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 206 36 moveto
+114 36 lineto
+114 0 lineto
+206 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 206 36 moveto
+114 36 lineto
+114 0 lineto
+206 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+121 13 moveto
+(COMRING...)
+[9.12 10.08 12.48 9.36 4.56 9.84 10.08 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->COMRING...
+newpath 242 72 moveto
+228 63 211 52 196 42 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
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 197 39 moveto
+187 36 lineto
+193 44 lineto
+closepath
+stroke
+end grestore
+% KONVERT...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 316 36 moveto
+224 36 lineto
+224 0 lineto
+316 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 316 36 moveto
+224 36 lineto
+224 0 lineto
+316 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+231 13 moveto
+(KONVERT...)
+[9.12 10.08 10.08 10.08 8.64 8.88 7.44 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->KONVERT...
+newpath 270 72 moveto
+270 64 270 55 270 46 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
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 274 46 moveto
+270 36 lineto
+267 46 lineto
+closepath
+stroke
+end grestore
+% FRETRCT...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 420 36 moveto
+334 36 lineto
+334 0 lineto
+420 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 420 36 moveto
+334 36 lineto
+334 0 lineto
+420 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+341 13 moveto
+(FRETRCT...)
+[7.68 9.36 8.64 8.64 8.88 9.36 7.44 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FRETRCT...
+newpath 297 72 moveto
+311 63 327 52 341 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
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 344 44 moveto
+350 36 lineto
+340 39 lineto
+closepath
+stroke
+end grestore
+% FLINEXP...
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 520 36 moveto
+438 36 lineto
+438 0 lineto
+520 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 520 36 moveto
+438 36 lineto
+438 0 lineto
+520 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+445 13 moveto
+(FLINEXP...)
+[7.68 8.64 4.56 10.08 8.64 10.08 6.24 3.6 3.6 3.6]
+xshow
+end grestore
+end grestore
+% MonogenicAlgebra(a:CommutativeRing,b:UnivariatePolynomialCategory(a))->FLINEXP...
+newpath 323 72 moveto
+352 63 388 50 429 36 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
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 430 39 moveto
+438 33 lineto
+427 33 lineto
+closepath
+stroke
+end grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
diff --git a/books/ps/v102twodimensionalarraycategory.ps b/books/ps/v102twodimensionalarraycategory.ps
new file mode 100644
index 0000000..d748f8e
--- /dev/null
+++ b/books/ps/v102twodimensionalarraycategory.ps
@@ -0,0 +1,697 @@
+%!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 598 440
+%%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 598 440
+%%PageOrientation: Portrait
+gsave
+36 36 562 404 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 402 lineto
+560 402 lineto
+560 -6 lineto
+closepath
+fill
+0.167 0.600 1.000 graphcolor
+newpath -6 -6 moveto
+-6 402 lineto
+560 402 lineto
+560 -6 lineto
+closepath
+stroke
+0.000 0.000 0.000 graphcolor
+14.00 /Times-Roman set_font
+% TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 554 396 moveto
+0 396 lineto
+0 360 lineto
+554 360 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 554 396 moveto
+0 396 lineto
+0 360 lineto
+554 360 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+7 373 moveto
+(TwoDimensionalArrayCategory\(a:Type,b:FiniteLinearAggregate\(a\),c:FiniteLinearAggregate\(a\)\))
+[7.2 9.6 6.96 10.08 3.84 10.8 6.24 6.96 5.52 3.84 6.96 6.96 6.24 3.84 10.08 5.28 4.8 5.76 6.96 9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96 4.56 6.24 3.84 7.2 6.96 6.96 6.24 3.6 6.96 3.84 7.44 3.84 6.96 3.84 3.84 6.24 8.64 3.84 6.96 6.24 6.24 4.8 9.84 6.96 7.2 4.8 6.24 6.72 6.24 3.84 6.24 4.56 6.24 4.56 3.6 6.24 3.84 7.44 3.84 6.96 3.84 3.84 6.24 8.64 3.84 6.96 6.24 6.24 4.8 9.84 6.96 7.2 4.8 6.24 6.72 6.24 3.84 6.24 4.56 6.24 4.56 4.56]
+xshow
+end grestore
+end grestore
+% HomogeneousAggregate(a:Type)
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 378 324 moveto
+176 324 lineto
+176 288 lineto
+378 288 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 378 324 moveto
+176 324 lineto
+176 288 lineto
+378 288 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+183 301 moveto
+(HomogeneousAggregate\(a:Type\))
+[10.08 6.96 10.8 6.96 6.72 6.24 6.96 6.24 6.96 6.96 5.52 9.84 6.96 7.2 4.8 6.24 6.72 6.24 3.84 6.24 4.56 6.24 3.84 7.2 6.96 6.96 6.24 4.56]
+xshow
+end grestore
+end grestore
+% TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))->HomogeneousAggregate(a:Type)
+newpath 277 360 moveto
+277 352 277 343 277 334 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 281 334 moveto
+277 324 lineto
+274 334 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 281 334 moveto
+277 324 lineto
+274 334 lineto
+closepath
+stroke
+end grestore
+% Aggregate()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 203 252 moveto
+119 252 lineto
+119 216 lineto
+203 216 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 203 252 moveto
+119 252 lineto
+119 216 lineto
+203 216 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+126 229 moveto
+(Aggregate\(\))
+[9.84 6.96 7.2 4.8 6.24 6.72 6.24 3.84 6.24 4.56 4.56]
+xshow
+end grestore
+end grestore
+% HomogeneousAggregate(a:Type)->Aggregate()
+newpath 248 288 moveto
+233 279 214 268 199 258 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 200 255 moveto
+190 252 lineto
+196 260 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 200 255 moveto
+190 252 lineto
+196 260 lineto
+closepath
+stroke
+end grestore
+% Evalable(a:Type)
+gsave 10 dict begin
+filled
+0.333 1.000 0.933 nodecolor
+0.333 1.000 0.933 nodecolor
+newpath 333 252 moveto
+221 252 lineto
+221 216 lineto
+333 216 lineto
+closepath
+fill
+0.333 1.000 0.933 nodecolor
+newpath 333 252 moveto
+221 252 lineto
+221 216 lineto
+333 216 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+229 229 moveto
+(Evalable\(a:Type\))
+[8.64 6.72 6.24 3.84 6.24 6.96 3.84 6.24 4.56 6.24 3.84 7.2 6.96 6.96 6.24 4.56]
+xshow
+end grestore
+end grestore
+% HomogeneousAggregate(a:Type)->Evalable(a:Type)
+newpath 277 288 moveto
+277 280 277 271 277 262 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 281 262 moveto
+277 252 lineto
+274 262 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 281 262 moveto
+277 252 lineto
+274 262 lineto
+closepath
+stroke
+end grestore
+% SetCategory()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 445 252 moveto
+351 252 lineto
+351 216 lineto
+445 216 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 445 252 moveto
+351 252 lineto
+351 216 lineto
+445 216 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+358 229 moveto
+(SetCategory\(\))
+[7.68 6 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
+% HomogeneousAggregate(a:Type)->SetCategory()
+newpath 308 288 moveto
+323 279 342 267 359 257 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 361 260 moveto
+368 252 lineto
+358 254 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 361 260 moveto
+368 252 lineto
+358 254 lineto
+closepath
+stroke
+end grestore
+% Type()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 218 108 moveto
+164 108 lineto
+164 72 lineto
+218 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 218 108 moveto
+164 108 lineto
+164 72 lineto
+218 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+172 85 moveto
+(Type\(\))
+[7.2 6.96 6.96 6.24 4.56 4.56]
+xshow
+end grestore
+end grestore
+% Aggregate()->Type()
+newpath 165 216 moveto
+170 191 180 147 185 118 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 188 118 moveto
+187 108 lineto
+182 117 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 188 118 moveto
+187 108 lineto
+182 117 lineto
+closepath
+stroke
+end grestore
+% BasicType()
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 298 180 moveto
+214 180 lineto
+214 144 lineto
+298 144 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 298 180 moveto
+214 180 lineto
+214 144 lineto
+298 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+221 157 moveto
+(BasicType\(\))
+[9.36 6.24 5.52 3.84 6.24 7.2 6.96 6.96 6.24 4.56 4.56]
+xshow
+end grestore
+end grestore
+% SetCategory()->BasicType()
+newpath 362 216 moveto
+343 206 320 195 300 185 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 301 182 moveto
+291 180 lineto
+298 188 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 301 182 moveto
+291 180 lineto
+298 188 lineto
+closepath
+stroke
+end grestore
+% CoercibleTo(OutputForm)
+gsave 10 dict begin
+filled
+0.404 0.667 0.545 nodecolor
+0.404 0.667 0.545 nodecolor
+newpath 480 180 moveto
+316 180 lineto
+316 144 lineto
+480 144 lineto
+closepath
+fill
+0.404 0.667 0.545 nodecolor
+newpath 480 180 moveto
+316 180 lineto
+316 144 lineto
+480 144 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+324 157 moveto
+(CoercibleTo\(OutputForm\))
+[9.36 6.96 6.24 4.8 6.24 3.84 6.96 3.84 6.24 7.44 6.96 4.56 10.08 6.96 3.84 6.96 6.96 3.84 7.44 6.96 5.04 10.8 4.56]
+xshow
+end grestore
+end grestore
+% SetCategory()->CoercibleTo(OutputForm)
+newpath 398 216 moveto
+398 208 398 199 398 190 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 402 190 moveto
+398 180 lineto
+395 190 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 402 190 moveto
+398 180 lineto
+395 190 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 290 36 moveto
+222 36 lineto
+222 0 lineto
+290 0 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 290 36 moveto
+222 36 lineto
+222 0 lineto
+290 0 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+230 13 moveto
+(Category)
+[9.36 6.24 3.84 6.24 6.96 6.96 5.04 6.96]
+xshow
+end grestore
+end grestore
+% BasicType()->Category
+newpath 256 144 moveto
+256 119 256 75 256 46 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 260 46 moveto
+256 36 lineto
+253 46 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 260 46 moveto
+256 36 lineto
+253 46 lineto
+closepath
+stroke
+end grestore
+% CoercibleTo(a:Type)
+gsave 10 dict begin
+filled
+0.537 0.247 0.902 nodecolor
+0.537 0.247 0.902 nodecolor
+newpath 440 108 moveto
+308 108 lineto
+308 72 lineto
+440 72 lineto
+closepath
+fill
+0.537 0.247 0.902 nodecolor
+newpath 440 108 moveto
+308 108 lineto
+308 72 lineto
+440 72 lineto
+closepath
+stroke
+gsave 10 dict begin
+0.000 0.000 0.000 nodecolor
+316 85 moveto
+(CoercibleTo\(a:Type\))
+[9.36 6.96 6.24 4.8 6.24 3.84 6.96 3.84 6.24 7.44 6.96 4.56 6.24 3.84 7.2 6.96 6.96 6.24 4.56]
+xshow
+end grestore
+end grestore
+% CoercibleTo(OutputForm)->CoercibleTo(a:Type)
+newpath 392 144 moveto
+389 136 386 126 383 118 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 386 117 moveto
+380 108 lineto
+380 119 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 386 117 moveto
+380 108 lineto
+380 119 lineto
+closepath
+stroke
+end grestore
+% CoercibleTo(a:Type)->Category
+newpath 344 72 moveto
+329 63 310 51 294 41 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 295 38 moveto
+285 36 lineto
+292 44 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 295 38 moveto
+285 36 lineto
+292 44 lineto
+closepath
+stroke
+end grestore
+% Type()->Category
+newpath 207 72 moveto
+215 63 224 53 233 44 curveto
+stroke
+gsave 10 dict begin
+solid
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 236 46 moveto
+240 36 lineto
+231 41 lineto
+closepath
+fill
+0.000 0.000 0.000 edgecolor
+newpath 236 46 moveto
+240 36 lineto
+231 41 lineto
+closepath
+stroke
+end grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+end
+restore
+%%EOF
diff --git a/changelog b/changelog
index 6c2a43d..e1e48d8 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,17 @@
+20080926 tpd books/bookvol10.2 add attributes
+20080926 tpd src/algebra/Makefile remove attreg
+20080926 tpd books/ps/v102twodimensionalarraycategory.ps added
+20080926 tpd books/ps/v102monogenicalgebra.ps added
+20080926 tpd books/ps/v102fullyretractableto.ps added
+20080926 tpd books/ps/v102framedalgebra.ps added
+20080926 tpd books/ps/v102finiterankalgebra.ps added
+20080926 tpd books/ps/v102category.ps added
+20080926 tpd books/ps/v102attributeregistry.ps added
+20080926 tpd books/bookvol10.2 add categories
+20080926 tpd src/algebra/attreg.spad deleted, absorbed by bookvol10.2
+20080926 tpd src/algebra/array2.spad move ARR2CAT to bookvol10.2
+20080926 tpd src/algebra/retract.spad move FRETRCT to bookvol10.2
+20080926 tpd src/algebra/algcat.spad move categories to bookvol10.2
 20080925 tpd books/ps/v102vectorspace.ps added
 20080925 tpd books/ps/v102uniquefactorizationdomain.ps added
 20080925 tpd books/ps/v102principalidealdomain.ps added
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index c28c491..81914f5 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -172,7 +172,6 @@ LAYER0COPY=\
 \subsection{Layer 0}
 \subsubsection{Completed spad files}
 \begin{verbatim}
-attreg.spad.pamphlet  (ATTREG)
 dhmatrix.spad.pamphlet (DHMATRIX)
 omcat.spad.pamphlet   (OM)
 print.spad.pamphlet   (PRINT)
@@ -1180,7 +1179,7 @@ SPADFILES= \
  ${OUTSRC}/algcat.spad ${OUTSRC}/algext.spad ${OUTSRC}/algfact.spad \
  ${OUTSRC}/algfunc.spad ${OUTSRC}/allfact.spad ${OUTSRC}/alql.spad \
  ${OUTSRC}/annacat.spad ${OUTSRC}/any.spad ${OUTSRC}/array1.spad \
- ${OUTSRC}/array2.spad ${OUTSRC}/asp.spad ${OUTSRC}/attreg.spad \
+ ${OUTSRC}/array2.spad ${OUTSRC}/asp.spad \
  ${OUTSRC}/axserver.spad \
  ${OUTSRC}/bags.spad ${OUTSRC}/bezout.spad ${OUTSRC}/boolean.spad \
  ${OUTSRC}/brill.spad \
@@ -1340,7 +1339,7 @@ DOCFILES= \
  ${DOC}/algcat.spad.dvi ${DOC}/algext.spad.dvi ${DOC}/algfact.spad.dvi \
  ${DOC}/algfunc.spad.dvi ${DOC}/allfact.spad.dvi ${DOC}/alql.spad.dvi \
  ${DOC}/annacat.spad.dvi ${DOC}/any.spad.dvi ${DOC}/array1.spad.dvi \
- ${DOC}/array2.spad.dvi ${DOC}/asp.spad.dvi ${DOC}/attreg.spad.dvi \
+ ${DOC}/array2.spad.dvi ${DOC}/asp.spad.dvi \
  ${DOC}/axserver.spad.dvi ${DOC}/axtimer.as.dvi \
  ${DOC}/bags.spad.dvi ${DOC}/bezout.spad.dvi ${DOC}/boolean.spad.dvi \
  ${DOC}/brill.spad.dvi \
diff --git a/src/algebra/array2.spad.pamphlet b/src/algebra/array2.spad.pamphlet
index 831a89e..bc45d6e 100644
--- a/src/algebra/array2.spad.pamphlet
+++ b/src/algebra/array2.spad.pamphlet
@@ -9,373 +9,6 @@
 \eject
 \tableofcontents
 \eject
-\section{category ARR2CAT TwoDimensionalArrayCategory}
-TwoDimensionalArrayCategory is a general array category which
-allows different representations and indexing schemes.
-Rows and columns may be extracted with rows returned as objects
-of type Row and columns returned as objects of type Col.
-The index of the 'first' row may be obtained by calling the
-function 'minRowIndex'.  The index of the 'first' column may
-be obtained by calling the function 'minColIndex'.  The index of
-the first element of a 'Row' is the same as the index of the
-first column in an array and vice versa.
-<<dot>>=
-"ARR2CAT" -> "HOAGG"
-"TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))"
-    -> "HomogeneousAggregate(a:Type)"
-"TwoDimensionalArrayCategory(a:Type,d:IndexedOneDimensionalArray(a,b),e:IndexedOneDimensionalArray(a,c))"
--> "TwoDimensionalArrayCategory(a:Type,b:FiniteLinearAggregate(a),c:FiniteLinearAggregate(a))"
-@
-<<category ARR2CAT TwoDimensionalArrayCategory>>=
-)abbrev category ARR2CAT TwoDimensionalArrayCategory
-++ Two dimensional array categories and domains
-++ Author:
-++ Date Created: 27 October 1989
-++ Date Last Updated: 27 June 1990
-++ Keywords: array, data structure
-++ Examples:
-++ References:
-TwoDimensionalArrayCategory(R,Row,Col): Category == Definition where
- R   : Type
- Row : FiniteLinearAggregate R
- Col : FiniteLinearAggregate R
-
- Definition == HomogeneousAggregate(R) with
-
-   shallowlyMutable
-    ++ one may destructively alter arrays
-
-   finiteAggregate
-    ++ two-dimensional arrays are finite
-
---% Array creation
-
-   new: (NonNegativeInteger,NonNegativeInteger,R) -> %
-    ++ new(m,n,r) is an m-by-n array all of whose entries are r
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,0)
-    
-   fill_!: (%,R) -> %
-    ++ fill!(m,r) fills m with r's
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,0)
-    ++X fill!(arr,10)
-
---% Size inquiries
-
-   minRowIndex : % -> Integer
-    ++ minRowIndex(m) returns the index of the 'first' row of the array m
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X minRowIndex(arr)
-
-   maxRowIndex : % -> Integer
-    ++ maxRowIndex(m) returns the index of the 'last' row of the array m
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X maxRowIndex(arr)
-
-   minColIndex : % -> Integer
-    ++ minColIndex(m) returns the index of the 'first' column of the array m
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X minColIndex(arr)
-
-   maxColIndex : % -> Integer
-    ++ maxColIndex(m) returns the index of the 'last' column of the array m
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X maxColIndex(arr)
-
-   nrows : % -> NonNegativeInteger
-    ++ nrows(m) returns the number of rows in the array m
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X nrows(arr)
-
-   ncols : % -> NonNegativeInteger
-    ++ ncols(m) returns the number of columns in the array m
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X ncols(arr)
-
---% Part extractions
-
-   elt: (%,Integer,Integer) -> R
-    ++ elt(m,i,j) returns the element in the ith row and jth
-    ++ column of the array m
-    ++ error check to determine if indices are in proper ranges
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X elt(arr,1,1)
-
-   qelt: (%,Integer,Integer) -> R
-    ++ qelt(m,i,j) returns the element in the ith row and jth
-    ++ column of the array m
-    ++ NO error check to determine if indices are in proper ranges
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X qelt(arr,1,1)
-
-   elt: (%,Integer,Integer,R) -> R
-    ++ elt(m,i,j,r) returns the element in the ith row and jth
-    ++ column of the array m, if m has an ith row and a jth column,
-    ++ and returns r otherwise
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X elt(arr,1,1,6)
-    ++X elt(arr,1,10,6)
-
-   row: (%,Integer) -> Row
-    ++ row(m,i) returns the ith row of m
-    ++ error check to determine if index is in proper ranges
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X row(arr,1)
-
-   column: (%,Integer) -> Col
-    ++ column(m,j) returns the jth column of m
-    ++ error check to determine if index is in proper ranges
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X column(arr,1)
-
-   parts: % -> List R
-    ++ parts(m) returns a list of the elements of m in row major order
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X parts(arr)
-
---% Part assignments
-
-   setelt: (%,Integer,Integer,R) -> R
-    -- will become setelt_!
-    ++ setelt(m,i,j,r) sets the element in the ith row and jth
-    ++ column of m to r
-    ++ error check to determine if indices are in proper ranges
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,0)
-    ++X setelt(arr,1,1,17)
-
-   qsetelt_!: (%,Integer,Integer,R) -> R
-    ++ qsetelt!(m,i,j,r) sets the element in the ith row and jth
-    ++ column of m to r
-    ++ NO error check to determine if indices are in proper ranges
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,0)
-    ++X qsetelt!(arr,1,1,17)
-
-   setRow_!: (%,Integer,Row) -> %
-    ++ setRow!(m,i,v) sets to ith row of m to v
-    ++
-    ++X T1:=TwoDimensionalArray Integer
-    ++X arr:T1:= new(5,4,0)
-    ++X T2:=OneDimensionalArray Integer
-    ++X arow:=construct([1,2,3,4]::List(INT))$T2
-    ++X setRow!(arr,1,arow)$T1
-
-   setColumn_!: (%,Integer,Col) -> %
-    ++ setColumn!(m,j,v) sets to jth column of m to v
-    ++
-    ++X T1:=TwoDimensionalArray Integer
-    ++X arr:T1:= new(5,4,0)
-    ++X T2:=OneDimensionalArray Integer
-    ++X acol:=construct([1,2,3,4,5]::List(INT))$T2
-    ++X setColumn!(arr,1,acol)$T1
-
---% Map and Zip
-
-   map: (R -> R,%) -> %
-    ++ map(f,a) returns \spad{b}, where \spad{b(i,j) = f(a(i,j))} 
-    ++ for all \spad{i, j}
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X map(-,arr)
-    ++X map((x +-> x + x),arr)
-
-   map_!: (R -> R,%) -> %
-    ++ map!(f,a)  assign \spad{a(i,j)} to \spad{f(a(i,j))} for all \spad{i, j}
-    ++
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X map!(-,arr)
-
-   map:((R,R) -> R,%,%) -> %
-    ++ map(f,a,b) returns \spad{c}, where \spad{c(i,j) = f(a(i,j),b(i,j))}
-    ++ for all \spad{i, j}
-    ++
-    ++X adder(a:Integer,b:Integer):Integer == a+b
-    ++X arr : ARRAY2 INT := new(5,4,10)
-    ++X map(adder,arr,arr)
-
-   map:((R,R) -> R,%,%,R) -> %
-    ++ map(f,a,b,r) returns \spad{c}, where \spad{c(i,j) = f(a(i,j),b(i,j))}
-    ++ when both \spad{a(i,j)} and \spad{b(i,j)} exist;
-    ++ else \spad{c(i,j) = f(r, b(i,j))} when \spad{a(i,j)} does not exist;
-    ++ else \spad{c(i,j) = f(a(i,j),r)} when \spad{b(i,j)} does not exist;
-    ++ otherwise \spad{c(i,j) = f(r,r)}.
-    ++
-    ++X adder(a:Integer,b:Integer):Integer == a+b
-    ++X arr1 : ARRAY2 INT := new(5,4,10)
-    ++X arr2 : ARRAY2 INT := new(3,3,10)
-    ++X map(adder,arr1,arr2,17)
-
-  add
-
---% Predicates
-
-    any?(f,m) ==
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          f(qelt(m,i,j)) => return true
-      false
-
-    every?(f,m) ==
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          not f(qelt(m,i,j)) => return false
-      true
-
-    size?(m,n) == nrows(m) * ncols(m) = n
-    less?(m,n) == nrows(m) * ncols(m) < n
-    more?(m,n) == nrows(m) * ncols(m) > n
-
---% Size inquiries
-
-    # m == nrows(m) * ncols(m)
-
---% Part extractions
-
-    elt(m,i,j,r) ==
-      i < minRowIndex(m) or i > maxRowIndex(m) => r
-      j < minColIndex(m) or j > maxColIndex(m) => r
-      qelt(m,i,j)
-
-    count(f:R -> Boolean,m:%) ==
-      num : NonNegativeInteger := 0
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          if f(qelt(m,i,j)) then num := num + 1
-      num
-
-    parts m ==
-      entryList : List R := nil()
-      for i in maxRowIndex(m)..minRowIndex(m) by -1 repeat
-        for j in maxColIndex(m)..minColIndex(m) by -1 repeat
-          entryList := concat(qelt(m,i,j),entryList)
-      entryList
-
---% Creation
-
-    copy m ==
-      ans := new(nrows m,ncols m,NIL$Lisp)
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          qsetelt_!(ans,i,j,qelt(m,i,j))
-      ans
-
-    fill_!(m,r) ==
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          qsetelt_!(m,i,j,r)
-      m
-
-    map(f,m) ==
-      ans := new(nrows m,ncols m,NIL$Lisp)
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          qsetelt_!(ans,i,j,f(qelt(m,i,j)))
-      ans
-
-    map_!(f,m) ==
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          qsetelt_!(m,i,j,f(qelt(m,i,j)))
-      m
-
-    map(f,m,n) ==
-      (nrows(m) ^= nrows(n)) or (ncols(m) ^= ncols(n)) =>
-        error "map: arguments must have same dimensions"
-      ans := new(nrows m,ncols m,NIL$Lisp)
-      for i in minRowIndex(m)..maxRowIndex(m) repeat
-        for j in minColIndex(m)..maxColIndex(m) repeat
-          qsetelt_!(ans,i,j,f(qelt(m,i,j),qelt(n,i,j)))
-      ans
-
-    map(f,m,n,r) ==
-      maxRow := max(maxRowIndex m,maxRowIndex n)
-      maxCol := max(maxColIndex m,maxColIndex n)
-      ans := new(max(nrows m,nrows n),max(ncols m,ncols n),NIL$Lisp)
-      for i in minRowIndex(m)..maxRow repeat
-        for j in minColIndex(m)..maxCol repeat
-          qsetelt_!(ans,i,j,f(elt(m,i,j,r),elt(n,i,j,r)))
-      ans
-
-    setRow_!(m,i,v) ==
-      i < minRowIndex(m) or i > maxRowIndex(m) =>
-        error "setRow!: index out of range"
-      for j in minColIndex(m)..maxColIndex(m) _
-        for k in minIndex(v)..maxIndex(v) repeat
-          qsetelt_!(m,i,j,v.k)
-      m
-
-    setColumn_!(m,j,v) ==
-      j < minColIndex(m) or j > maxColIndex(m) =>
-        error "setColumn!: index out of range"
-      for i in minRowIndex(m)..maxRowIndex(m) _
-        for k in minIndex(v)..maxIndex(v) repeat
-          qsetelt_!(m,i,j,v.k)
-      m
-
-    if R has _= : (R,R) -> Boolean then
-
-      m = n ==
-        eq?(m,n) => true
-        (nrows(m) ^= nrows(n)) or (ncols(m) ^= ncols(n)) => false
-        for i in minRowIndex(m)..maxRowIndex(m) repeat
-          for j in minColIndex(m)..maxColIndex(m) repeat
-            not (qelt(m,i,j) = qelt(n,i,j)) => return false
-        true
-
-      member?(r,m) ==
-        for i in minRowIndex(m)..maxRowIndex(m) repeat
-          for j in minColIndex(m)..maxColIndex(m) repeat
-            qelt(m,i,j) = r => return true
-        false
-
-      count(r:R,m:%) == count(#1 = r,m)
-
-    if Row has shallowlyMutable then
-
-      row(m,i) ==
-        i < minRowIndex(m) or i > maxRowIndex(m) =>
-          error "row: index out of range"
-        v : Row := new(ncols m,NIL$Lisp)
-        for j in minColIndex(m)..maxColIndex(m) _
-          for k in minIndex(v)..maxIndex(v) repeat
-            qsetelt_!(v,k,qelt(m,i,j))
-        v
-
-    if Col has shallowlyMutable then
-
-      column(m,j) ==
-        j < minColIndex(m) or j > maxColIndex(m) =>
-          error "column: index out of range"
-        v : Col := new(nrows m,NIL$Lisp)
-        for i in minRowIndex(m)..maxRowIndex(m) _
-          for k in minIndex(v)..maxIndex(v) repeat
-            qsetelt_!(v,k,qelt(m,i,j))
-        v
-
-    if R has CoercibleTo(OutputForm) then
-
-      coerce(m:%) ==
-        l : List List OutputForm
-        l := [[qelt(m,i,j) :: OutputForm _
-                  for j in minColIndex(m)..maxColIndex(m)] _
-                  for i in minRowIndex(m)..maxRowIndex(m)]
-        matrix l
-
-@
 \section{domain IIARRAY2 InnerIndexedTwoDimensionalArray}
 This is an internal type which provides an implementation of
 2-dimensional arrays as PrimitiveArray's of PrimitiveArray's.
@@ -1010,7 +643,6 @@ TwoDimensionalArray(R):Exports == Implementation where
 @
 <<*>>=
 
-<<category ARR2CAT TwoDimensionalArrayCategory>>
 <<domain IIARRAY2 InnerIndexedTwoDimensionalArray>>
 <<domain IARRAY2 IndexedTwoDimensionalArray>>
 <<domain ARRAY2 TwoDimensionalArray>>
diff --git a/src/algebra/attreg.spad.pamphlet b/src/algebra/attreg.spad.pamphlet
deleted file mode 100644
index 0dbacc1..0000000
--- a/src/algebra/attreg.spad.pamphlet
+++ /dev/null
@@ -1,131 +0,0 @@
-\documentclass{article}
-\usepackage{axiom}
-\begin{document}
-\title{\$SPAD/src/algebra attreg.spad}
-\author{The Axiom Team}
-\maketitle
-\begin{abstract}
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-\section{category ATTREG AttributeRegistry}
-<<dot>>=
-"ATTREG" -> "CATEGORY"
-"AttributeRegistry()" -> "Category"
-@
-<<category ATTREG AttributeRegistry>>=
-)abbrev category ATTREG AttributeRegistry
-
-++ This category exports the attributes in the AXIOM Library
-AttributeRegistry(): Category == with
-  finiteAggregate
-    ++ \spad{finiteAggregate} is true if it is an aggregate with a 
-    ++ finite number of elements.
-  commutative("*")
-    ++ \spad{commutative("*")} is true if it has an operation
-    ++ \spad{"*": (D,D) -> D} which is commutative.
-  shallowlyMutable
-    ++ \spad{shallowlyMutable} is true if its values
-    ++ have immediate components that are updateable (mutable).
-    ++ Note: the properties of any component domain are irrevelant to the
-    ++ \spad{shallowlyMutable} proper.
-  unitsKnown
-    ++ \spad{unitsKnown} is true if a monoid (a multiplicative semigroup 
-    ++ with a 1) has \spad{unitsKnown} means that
-    ++ the operation \spadfun{recip} can only return "failed" 
-    ++ if its argument is not a unit.
-  leftUnitary
-    ++ \spad{leftUnitary} is true if \spad{1 * x = x} for all x.
-  rightUnitary
-    ++ \spad{rightUnitary} is true if \spad{x * 1 = x} for all x.
-  noZeroDivisors
-    ++ \spad{noZeroDivisors} is true if \spad{x * y \~~= 0} implies 
-    ++ both x and y are non-zero.
-  canonicalUnitNormal
-    ++ \spad{canonicalUnitNormal} is true if we can choose a canonical
-    ++ representative for each class of associate elements, that is
-    ++ \spad{associates?(a,b)} returns true if and only if 
-    ++ \spad{unitCanonical(a) = unitCanonical(b)}.
-  canonicalsClosed
-    ++ \spad{canonicalsClosed} is true if 
-    ++ \spad{unitCanonical(a)*unitCanonical(b) = unitCanonical(a*b)}.
-  arbitraryPrecision
-    ++ \spad{arbitraryPrecision} means the user can set the 
-    ++ precision for subsequent calculations.
-  partiallyOrderedSet
-    ++ \spad{partiallyOrderedSet} is true if
-    ++ a set with \spadop{<} which is transitive, 
-    ++ but \spad{not(a < b or a = b)}
-    ++ does not necessarily imply \spad{b<a}.
-  central
-    ++ \spad{central} is true if, given an algebra over a ring R,
-    ++ the image of R is the center
-    ++ of the algebra, i.e. the set of members of the algebra which commute
-    ++ with all others is precisely the image of R in the algebra.
-  noetherian
-    ++ \spad{noetherian} is true if all of its ideals are finitely generated.
-  additiveValuation
-    ++ \spad{additiveValuation} implies
-    ++ \spad{euclideanSize(a*b)=euclideanSize(a)+euclideanSize(b)}.
-  multiplicativeValuation
-    ++ \spad{multiplicativeValuation} implies
-    ++ \spad{euclideanSize(a*b)=euclideanSize(a)*euclideanSize(b)}.
-  NullSquare
-    ++ \axiom{NullSquare} means that \axiom{[x,x] = 0} holds.
-    ++ See \axiomType{LieAlgebra}.
-  JacobiIdentity
-    ++ \axiom{JacobiIdentity} means that 
-    ++ \axiom{[x,[y,z]]+[y,[z,x]]+[z,[x,y]] = 0} holds.
-    ++ See \axiomType{LieAlgebra}.
-  canonical
-    ++ \spad{canonical} is true if and only if distinct elements have 
-    ++ distinct data structures. For example, a domain of mathematical objects 
-    ++ which has the \spad{canonical} attribute means that two objects 
-    ++ are mathematically
-    ++ equal if and only if their data structures are equal.
-
-@
-\section{License}
-<<license>>=
---Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
---All rights reserved.
---
---Redistribution and use in source and binary forms, with or without
---modification, are permitted provided that the following conditions are
---met:
---
---    - Redistributions of source code must retain the above copyright
---      notice, this list of conditions and the following disclaimer.
---
---    - Redistributions in binary form must reproduce the above copyright
---      notice, this list of conditions and the following disclaimer in
---      the documentation and/or other materials provided with the
---      distribution.
---
---    - Neither the name of The Numerical ALgorithms Group Ltd. nor the
---      names of its contributors may be used to endorse or promote products
---      derived from this software without specific prior written permission.
---
---THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
---IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
---TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
---PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
---OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
---EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
---PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
---PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
---LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
---NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
---SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-@
-<<*>>=
-<<license>>
-
-<<category ATTREG AttributeRegistry>>
-@
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} nothing
-\end{thebibliography}
-\end{document}
diff --git a/src/algebra/retract.spad.pamphlet b/src/algebra/retract.spad.pamphlet
index 3492d7e..4b36a2b 100644
--- a/src/algebra/retract.spad.pamphlet
+++ b/src/algebra/retract.spad.pamphlet
@@ -9,48 +9,6 @@
 \eject
 \tableofcontents
 \eject
-\section{category FRETRCT FullyRetractableTo}
-<<dot>>=
-"FRETRCT" -> "RETRACT"
-"FullyRetractableTo(a:Type)" -> "RetractableTo(a:Type)"
-"FullyRetractableTo(a:Ring)" -> "FullyRetractableTo(a:Type)"
-"FullyRetractableTo(a:CommutativeRing)" -> "FullyRetractableTo(a:Type)"
-@
-<<category FRETRCT FullyRetractableTo>>=
-)abbrev category FRETRCT FullyRetractableTo
-++ Author: Manuel Bronstein
-++ Description:
-++   A is fully retractable to B means that A is retractable to B, and,
-++   in addition, if B is retractable to the integers or rational
-++   numbers then so is A.
-++   In particular, what we are asserting is that there are no integers
-++   (rationals) in A which don't retract into B.
-++ Date Created: March 1990
-++ Date Last Updated: 9 April 1991
-FullyRetractableTo(S: Type): Category == RetractableTo(S) with
-    if (S has RetractableTo Integer) then RetractableTo Integer
-    if (S has RetractableTo Fraction Integer) then
-              RetractableTo Fraction Integer
-  add
-    if not(S is Integer) then
-      if (S has RetractableTo Integer) then    -- induction
-        coerce(n:Integer):%  == n::S::%
-        retract(r:%):Integer == retract(retract(r)@S)
- 
-        retractIfCan(r:%):Union(Integer, "failed") ==
-          (u:= retractIfCan(r)@Union(S,"failed")) case "failed"=> "failed"
-          retractIfCan(u::S)
- 
-    if not(S is Fraction Integer) then
-      if (S has RetractableTo Fraction Integer) then   -- induction
-        coerce(n:Fraction Integer):%  == n::S::%
-        retract(r:%):Fraction(Integer) == retract(retract(r)@S)
- 
-        retractIfCan(r:%):Union(Fraction Integer, "failed") ==
-          (u:=retractIfCan(r)@Union(S,"failed")) case "failed"=>"failed"
-          retractIfCan(u::S)
-
-@
 \section{package INTRET IntegerRetractions}
 <<dot>>=
 "INTRET" -> "PACKAGE"
@@ -140,7 +98,6 @@ RationalRetractions(S:RetractableTo(Fraction Integer)): with
 <<*>>=
 <<license>>
  
-<<category FRETRCT FullyRetractableTo>>
 <<package INTRET IntegerRetractions>>
 <<package RATRET RationalRetractions>>
 @
