diff --git a/books/bookvol10.3.pamphlet b/books/bookvol10.3.pamphlet
index 61e026f..f165480 100644
--- a/books/bookvol10.3.pamphlet
+++ b/books/bookvol10.3.pamphlet
@@ -67867,6 +67867,292 @@ OrderedDirectProduct(dim:NonNegativeInteger,
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \section{domain OFMONOID OrderedFreeMonoid}
+<<OrderedFreeMonoid.input>>=
+)set break resume
+)sys rm -f OrderedFreeMonoid.output
+)spool OrderedFreeMonoid.output
+)set message test on
+)set message auto off
+)clear all
+
+--S 1 of 24
+m1:=(x*y*y*z)$OFMONOID(Symbol)
+--E 1
+
+--S 2 of 24
+m2:=(x*y)$OFMONOID(Symbol)
+--E 2
+
+--S 3 of 24
+lquo(m1,m2)
+--E 3
+
+--S 4 of 24
+m3:=(y*y)$OFMONOID(Symbol)
+--E 4
+
+--S 5 of 24
+divide(m1,m2)
+--E 5
+
+--S 6 of 24
+divide(m1,m3)
+--E 6
+
+--S 7 of 24
+m4:=(y^3)$OFMONOID(Symbol)
+--E 7
+
+--S 8 of 24
+divide(m1,m4)
+--E 8
+
+)set function compile on
+
+-- Build the non-commutative algebra h=k[x,y] and then make computations
+-- in h using some predefined rules for x and y. For example, giving
+--   x*y*x=y*x*y
+--   x*x=a*x+b
+--   y*y=a*y+b
+-- where a dn b are generic elements of k.
+-- Then reduce the polynomials in x and y according to the previous rules.
+-- That is, given
+--   (x+y)^2   ( = x^2+x*y+y*x+y^2)
+-- should reduce to
+--   a*(x+y)+2*b+x*y+y*x
+
+-- Generic elements of k (OVAR is OrderedVariableList)
+
+--S 9 of 24
+C ==> OVAR [a,b]
+--E 9
+
+-- Commutative Field: k = Q[a,b]
+-- Q = Fraction Integer
+-- SMP = SparseMultivariatePolynomials
+
+--S 10 of 24
+K ==> SMP(FRAC INT,C)
+--E 10
+
+-- Non-commutative variables
+
+--S 11 of 24
+V ==> OVAR [x,y]
+--E 11
+
+-- Non-commuative algebra k=k[x,y]
+-- XDPOLY XDistributedPolynomial
+
+--S 12 of 24
+H ==> XDPOLY(V,K)
+--E 12
+
+-- Free Monoid
+
+--S 13 of 24
+M ==> OFMONOID V
+--E 13
+
+-- Substitution rules are applied to words from the monoid over the 
+-- variables and retun polynomials
+
+--S 14 of 24
+subs(w:M):H ==
+  -- x*y*x = y*x*y
+  n1:=lquo(w,(x::V*y::V*x::V)$M)$M
+  n1 case "failed" => monom(w,1)$H
+      -- x*x = a*x+b
+    n2:=lquo(w,(x::V^2)$M)$M
+    n2 case "failed" => monom(w,1)$H
+      -- y*y = a*y+b
+      n3:lquo(w,(y::V^2)$M)$M
+      n3 case "failed" => monom(w,1)$H
+      monom(n3,1)$H * (a::K*y::V+b::K)$M * monom(n3,1)$H
+    monom(n2,1)$H * (a::K*x::V+b::K)$H * monom(n2,1)$H
+  monom(n1,1)$H * (y::V*x::V*y::V)$H * monom(n1,1)$H
+--E 14
+
+-- Apply rules to a term. Keep coefficients
+--S 15 of 24
+newterm(x:Record(k:M,c:K)):H == x.c*subs(x,k)
+--E 15
+
+-- Reconstruct the polynomial term by term
+
+--S 16 of 24
+newpoly(t:H):H == reduce(+,map(newterm,listOfTerms(t)))
+--E 16
+
+-- Example calcuations
+
+--S 17 of 24
+p1:(x::V+y::V)$H^2
+--E 17
+
+--S 18 of 24
+newpoly(p1)
+--E 18
+
+--S 19 of 24
+p2:=(x::V+y::V)$H^3
+--E 19
+
+--S 20 of 24
+pNew:=newpoly(p2)
+--E 20
+
+-- But the rules should be applied more than once
+--S 21 of 24
+while pNew ~= p2 repeat
+  p2 := pNew
+  pNew := newpoly(p2)
+--E 21
+
+--S 22 of 24
+pNew
+--E 22
+
+--S 23 of 24
+reduce(p:H):H ==
+  p2 := newpoly(p)
+  p3 := newpoly(p2)
+  while p3 ~= p2 repeat
+    p2 := p3
+    p3 := newpoly(p2)
+  p3
+--E 23
+
+--S 24 of 24
+reduce(p2)
+--E 24
+
+)spool
+)lisp (bye)
+@
+<<OrderedFreeMonoid.help>>=
+====================================================================
+OrderedFreeMonoid examples
+====================================================================
+
+m1:=(x*y*y*z)$OFMONOID(Symbol)
+
+m2:=(x*y)$OFMONOID(Symbol)
+
+lquo(m1,m2)
+
+m3:=(y*y)$OFMONOID(Symbol)
+
+div(m1,m2)
+
+div(m1,m3)
+
+m4:=(y^3)$OFMONOID(Symbol)
+
+div(m1,m4)
+
+Build the non-commutative algebra h=k[x,y] and then make computations
+in h using some predefined rules for x and y. For example, giving
+
+   x*y*x=y*x*y
+   x*x=a*x+b
+   y*y=a*y+b
+
+where a dn b are generic elements of k.
+
+Then reduce the polynomials in x and y according to the previous rules.
+That is, given
+
+   (x+y)^2   ( = x^2+x*y+y*x+y^2)
+
+should reduce to
+
+   a*(x+y)+2*b+x*y+y*x
+
+We can reduce the clutter of the work by defining macros for the types
+of the domains we need to create. So first we create those macros.
+
+We create generic elements of k. First we define a macro for the domain of
+ordered variables (OVAR is OrderedVariableList)
+
+  C ==> OVAR [a,b]
+
+Next we define a macro for the commutative field domain k = Q[a,b]
+where Q is Fraction(Integer) and SMP is SparseMultivariatePolynomials
+
+  K ==> SMP(FRAC INT,C)
+
+Now we need some non-commutative variables so we create a macro for that.
+
+  V ==> OVAR [x,y]
+
+And now we need to define the non-commuative algebra k=k[x,y].
+We use the domain XDistributedPolynomial (XDPOLY) as a macro.
+
+  H ==> XDPOLY(V,K)
+
+The non-commutative variables are in an Ordered Free Monoid
+
+  M ==> OFMONOID V
+
+We have three rules to apply. So we create a function that examines one
+term. Substitution rules are applied to words from the monoid over the 
+variables and retun polynomials. If any rule matches we construct the
+substitution, create a new monomial term and return it.
+
+  subs(w:M):H ==
+    -- x*y*x = y*x*y
+    n1:=lquo(w,(x::V*y::V*x::V)$M)$M
+    n1 case "failed" => monom(w,1)$H
+        -- x*x = a*x+b
+      n2:=lquo(w,(x::V^2)$M)$M
+      n2 case "failed" => monom(w,1)$H
+        -- y*y = a*y+b
+        n3:lquo(w,(y::V^2)$M)$M
+        n3 case "failed" => monom(w,1)$H
+        monom(n3,1)$H * (a::K*y::V+b::K)$M * monom(n3,1)$H
+      monom(n2,1)$H * (a::K*x::V+b::K)$H * monom(n2,1)$H
+    monom(n1,1)$H * (y::V*x::V*y::V)$H * monom(n1,1)$H
+
+We apply these rules to a term, remembering the coefficient
+
+  newterm(x:Record(k:M,c:K)):H == x.c*subs(x,k)
+
+
+And now we create a function to reconstruct the polynomial term by term.
+
+  newpoly(t:H):H == reduce(+,map(newterm,listOfTerms(t)))
+
+
+For example,
+
+  p1:(x::V+y::V)$H^2
+
+  newpoly(p1)
+
+  p2:=(x::V+y::V)$H^3
+
+  pNew:=newpoly(p2)
+
+But the rules should be applied more than once so we create a function
+to iterate the rules until nothing changes.
+
+  reduce(p:H):H ==
+    p2 := newpoly(p)
+    p3 := newpoly(p2)
+    while p3 ~= p2 repeat
+      p2 := p3
+      p3 := newpoly(p2)
+    p3
+
+And we can see it work
+
+  reduce(p2)
+
+See Also:
+o )show OrderedFreeMonoid
+
+@
 \pagehead{OrderedFreeMonoid}{OFMONOID}
 \pagepic{ps/v103orderedfreemonoid.ps}{OFMONOID}{1.00}
 
@@ -67928,138 +68214,218 @@ OrderedDirectProduct(dim:NonNegativeInteger,
 ++ are non-negative integers. The multiplication is not commutative.
 ++ For two elements \spad{x} and \spad{y} the relation \spad{x < y}
 ++ holds if either \spad{length(x) < length(y)} holds or if these lengths
-++ are equal and if \spad{x} is smaller than \spad{y} w.r.t. the lexicographical
-++ ordering induced by \spad{S}.
+++ are equal and if \spad{x} is smaller than \spad{y} w.r.t. the 
+++ lexicographical ordering induced by \spad{S}.
 ++ This domain inherits implementation from \spadtype{FreeMonoid}.
 ++ Author: Michel Petitot (petitot@lifl.fr)
 
 OrderedFreeMonoid(S: OrderedSet): OFMcategory == OFMdefinition where
-    NNI ==> NonNegativeInteger
-    REC ==> Record(gen:S, exp:NNI)
- 
-    OFMcategory == Join(OrderedMonoid, RetractableTo S) with
-        "*":    (S, %) -> %
-          ++ \spad{s * x} returns the product of \spad{x} by \spad{s} on the left.
-        "*":    (%, S) -> %
-          ++ \spad{x * s} returns the product of \spad{x} by \spad{s} on the right.
-        "**":   (S, NNI) -> %
-          ++ \spad{s ** n} returns the product of \spad{s} by itself \spad{n} times.
-        first: % -> S
-          ++ \spad{first(x)} returns the first letter of \spad{x}.
-        rest:  % -> %
-          ++ \spad{rest(x)} returns \spad{x} except the first letter.
-        mirror: % -> %
-          ++ \spad{mirror(x)} returns the reversed word of \spad{x}.
-        lexico: (%,%) -> Boolean
-          ++ \spad{lexico(x,y)} returns \spad{true} iff \spad{x} is smaller than \spad{y}
-          ++ w.r.t. the pure lexicographical ordering induced by \spad{S}.
-        hclf:   (%, %) -> %
-          ++ \spad{hclf(x, y)} returns the highest common left factor 
-          ++ of \spad{x} and \spad{y},
-          ++ that is the largest \spad{d} such that \spad{x = d a} and \spad{y = d b}.
-        hcrf:   (%, %) -> %
-          ++ \spad{hcrf(x, y)} returns the highest common right 
-          ++ factor of \spad{x} and \spad{y},
-          ++ that is the largest \spad{d} such that \spad{x = a d} and \spad{y = b d}.
-        lquo:   (%, %) -> Union(%, "failed")
-          ++ \spad{lquo(x, y)} returns the exact left quotient of \spad{x}
-          ++  by \spad{y} that is \spad{q} such that \spad{x = y * q},
-          ++ "failed" if \spad{x} is not of the form \spad{y * q}.
-        rquo:   (%, %) -> Union(%, "failed")
-          ++ \spad{rquo(x, y)} returns the exact right quotient of \spad{x} 
-          ++ by \spad{y} that is \spad{q} such that \spad{x = q * y},
-          ++ "failed" if \spad{x} is not of the form \spad{q * y}.
-        lquo:   (%, S) -> Union(%, "failed")
-          ++ \spad{lquo(x, s)} returns the exact left quotient of \spad{x} 
-          ++ by \spad{s}. 
-        rquo:   (%, S) -> Union(%, "failed")
-          ++ \spad{rquo(x, s)} returns the exact right quotient 
-          ++ of \spad{x} by \spad{s}.
-        "div":   (%, %) -> Union(Record(lm: %, rm: %), "failed")
-          ++ \spad{x div y} returns the left and right exact quotients of
-          ++ \spad{x} by \spad{y}, that is \spad{[l, r]} such that \spad{x = l * y * r}.
-          ++ "failed" is returned iff \spad{x} is not of the form \spad{l * y * r}.
-        overlap: (%, %) -> Record(lm: %, mm: %, rm: %)
-          ++ \spad{overlap(x, y)} returns \spad{[l, m, r]} such that
-          ++ \spad{x = l * m} and \spad{y = m * r} hold and such that 
-          ++ \spad{l} and \spad{r} have no overlap,
-          ++ that is \spad{overlap(l, r) = [l, 1, r]}.
-        size:   % -> NNI
-          ++ \spad{size(x)} returns the number of monomials in \spad{x}.
-        nthExpon:  (%, Integer) -> NNI
-          ++ \spad{nthExpon(x, n)} returns the exponent of the 
-          ++ \spad{n-th} monomial of \spad{x}.
-        nthFactor: (%, Integer) -> S
-          ++ \spad{nthFactor(x, n)} returns the factor of the \spad{n-th} 
-          ++ monomial of \spad{x}.
-        factors: % -> List REC
-          ++ \spad{factors(a1\^e1,...,an\^en)} returns \spad{[[a1, e1],...,[an, en]]}.
-        length: % -> NNI
-          ++ \spad{length(x)} returns the length of \spad{x}.
-        varList: % -> List S
-          ++ \spad{varList(x)} returns the list of variables of \spad{x}.
-
-    OFMdefinition == FreeMonoid(S) add
-        Rep := ListMonoidOps(S, NNI, 1)
+  NNI ==> NonNegativeInteger
+  REC ==> Record(gen:S, exp:NNI)
+  RESULT ==> Union(Record(lm:Union(%,"failed"),rm:Union(%,"failed")),"failed")
+ 
+  OFMcategory == Join(OrderedMonoid, RetractableTo S) with
+    "*":    (S, %) -> %
+      ++ \spad{s*x} returns the product of \spad{x} by \spad{s} on the left.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X x*m1
+    "*":    (%, S) -> %
+      ++ \spad{x*s} returns the product of \spad{x} by \spad{s} on the right.
+      ++
+      ++X m1:=(y**3)$OFMONOID(Symbol)
+      ++X m1*x
+    "**":   (S, NNI) -> %
+      ++ \spad{s**n} returns the product of \spad{s} by itself \spad{n} times.
+      ++
+      ++X m1:=(y**3)$OFMONOID(Symbol)
+    first: % -> S
+      ++ \spad{first(x)} returns the first letter of \spad{x}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X first m1
+    rest:  % -> %
+      ++ \spad{rest(x)} returns \spad{x} except the first letter.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X rest m1
+    mirror: % -> %
+      ++ \spad{mirror(x)} returns the reversed word of \spad{x}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X mirror m1
+    lexico: (%,%) -> Boolean
+      ++ \spad{lexico(x,y)} returns \spad{true} 
+      ++ iff \spad{x} is smaller than \spad{y}
+      ++ w.r.t. the pure lexicographical ordering induced by \spad{S}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X m2:=(x*y)$OFMONOID(Symbol)
+      ++X lexico(m1,m2)
+      ++X lexico(m2,m1)
+    hclf:   (%, %) -> %
+      ++ \spad{hclf(x, y)} returns the highest common left factor 
+      ++ of \spad{x} and \spad{y},
+      ++ that is the largest \spad{d} such that \spad{x = d a} 
+      ++ and \spad{y = d b}.
+      ++
+      ++X m1:=(x*y*z)$OFMONOID(Symbol)
+      ++X m2:=(x*y)$OFMONOID(Symbol)
+      ++X hclf(m1,m2)
+    hcrf:   (%, %) -> %
+      ++ \spad{hcrf(x, y)} returns the highest common right 
+      ++ factor of \spad{x} and \spad{y},
+      ++ that is the largest \spad{d} such that \spad{x = a d} 
+      ++ and \spad{y = b d}.
+      ++
+      ++X m1:=(x*y*z)$OFMONOID(Symbol)
+      ++X m2:=(y*z)$OFMONOID(Symbol)
+      ++X hcrf(m1,m2)
+    lquo:   (%, %) -> Union(%, "failed")
+      ++ \spad{lquo(x, y)} returns the exact left quotient of \spad{x}
+      ++  by \spad{y} that is \spad{q} such that \spad{x = y * q},
+      ++ "failed" if \spad{x} is not of the form \spad{y * q}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X m2:=(x*y)$OFMONOID(Symbol)
+      ++X lquo(m1,m2)
+    rquo:   (%, %) -> Union(%, "failed")
+      ++ \spad{rquo(x, y)} returns the exact right quotient of \spad{x} 
+      ++ by \spad{y} that is \spad{q} such that \spad{x = q * y},
+      ++ "failed" if \spad{x} is not of the form \spad{q * y}.
+      ++
+      ++X m1:=(q*y^3)$OFMONOID(Symbol)
+      ++X m2:=(y^2)$OFMONOID(Symbol)
+      ++X lquo(m1,m2)
+    lquo:   (%, S) -> Union(%, "failed")
+      ++ \spad{lquo(x, s)} returns the exact left quotient of \spad{x} 
+      ++ by \spad{s}. 
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X lquo(m1,x)
+    rquo:   (%, S) -> Union(%, "failed")
+      ++ \spad{rquo(x, s)} returns the exact right quotient 
+      ++ of \spad{x} by \spad{s}.
+      ++
+      ++X m1:=(x*y)$OFMONOID(Symbol)
+      ++X div(m1,y)
+    divide: (%, %) -> RESULT
+      ++ \spad{divide(x,y)} returns the left and right exact quotients of
+      ++ \spad{x} by \spad{y}, that is \spad{[l,r]} such that \spad{x = l*y*r}.
+      ++ "failed" is returned iff \spad{x} is not of the form \spad{l * y * r}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X m2:=(x*y)$OFMONOID(Symbol)
+      ++X divide(m1,m2)
+    overlap: (%, %) -> Record(lm: %, mm: %, rm: %)
+      ++ \spad{overlap(x, y)} returns \spad{[l, m, r]} such that
+      ++ \spad{x = l * m} and \spad{y = m * r} hold and such that 
+      ++ \spad{l} and \spad{r} have no overlap,
+      ++ that is \spad{overlap(l, r) = [l, 1, r]}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X m2:=(x*y)$OFMONOID(Symbol)
+      ++X overlap(m1,m2)
+    size:   % -> NNI
+      ++ \spad{size(x)} returns the number of monomials in \spad{x}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X size(m1,2)
+    nthExpon:  (%, Integer) -> NNI
+      ++ \spad{nthExpon(x, n)} returns the exponent of the 
+      ++ \spad{n-th} monomial of \spad{x}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X nthExpon(m1,2)
+    nthFactor: (%, Integer) -> S
+      ++ \spad{nthFactor(x, n)} returns the factor of the \spad{n-th} 
+      ++ monomial of \spad{x}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X nthFactor(m1,2)
+    factors: % -> List REC
+      ++ \spad{factors(a1\^e1,...,an\^en)} returns 
+      ++ \spad{[[a1, e1],...,[an, en]]}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X factors m1
+    length: % -> NNI
+      ++ \spad{length(x)} returns the length of \spad{x}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X length m1
+    varList: % -> List S
+      ++ \spad{varList(x)} returns the list of variables of \spad{x}.
+      ++
+      ++X m1:=(x*y*y*z)$OFMONOID(Symbol)
+      ++X varList m1
+
+  OFMdefinition == FreeMonoid(S) add
+    Rep := ListMonoidOps(S, NNI, 1)
         
-      -- definitions
-        lquo(w:%, l:S) == 
-          x: List REC := listOfMonoms(w)$Rep
-          null x        => "failed"
-          fx: REC := first x
-          fx.gen ^= l  => "failed"
-          fx.exp = 1   => makeMulti rest(x)
-          makeMulti [[fx.gen, (fx.exp - 1)::NNI ]$REC, :rest x]
+    -- definitions
+    lquo(w:%, l:S) == 
+      x: List REC := listOfMonoms(w)$Rep
+      null x        => "failed"
+      fx: REC := first x
+      fx.gen ^= l  => "failed"
+      fx.exp = 1   => makeMulti rest(x)
+      makeMulti [[fx.gen, (fx.exp - 1)::NNI ]$REC, :rest x]
        
-        rquo(w:%, l:S) ==
-          u:% := reverse w
-          (r := lquo (u,l)) case "failed" => "failed"
-          reverse_! (r::%)
-
-        length x == reduce("+" ,[f.exp for f in listOfMonoms x], 0)
-
-        varList x ==
-          le: List S := [t.gen for t in listOfMonoms x]
-          sort_! removeDuplicates(le)
- 
-        first w ==
-          x: List REC := listOfMonoms w
-          null x => error "empty word !!!"
-          x.first.gen
-
-        rest w ==
-          x: List REC := listOfMonoms w
-          null x => error "empty word !!!"
-          fx: REC := first x
-          fx.exp = 1 => makeMulti rest x
-          makeMulti [[fx.gen , (fx.exp - 1)::NNI ]$REC , :rest x]
-
-        lexico(a,b) ==         --  ordre lexicographique
-            la := listOfMonoms a
-            lb := listOfMonoms b
-            while (not null la) and (not null lb) repeat
-                la.first.gen > lb.first.gen => return false
-                la.first.gen < lb.first.gen => return true
-                if la.first.exp = lb.first.exp then
-                    la:=rest la
-                    lb:=rest lb
-                else if la.first.exp > lb.first.exp then
-                    la:=concat([la.first.gen,
-                           (la.first.exp - lb.first.exp)::NNI], rest lb)
-                    lb:=rest lb
-                else
-                    lb:=concat([lb.first.gen,
-                             (lb.first.exp-la.first.exp)::NNI], rest la)
-                    la:=rest la
-            empty? la and not empty? lb
+    rquo(w:%, l:S) ==
+      u:% := reverse w
+      (r := lquo (u,l)) case "failed" => "failed"
+      reverse_! (r::%)
+
+    divide(left:%,right:%) == 
+      a:=lquo(left,right) 
+      b:=rquo(left,right)
+      [a,b]
+
+    length x == reduce("+" ,[f.exp for f in listOfMonoms x], 0)
+
+    varList x ==
+      le: List S := [t.gen for t in listOfMonoms x]
+      sort_! removeDuplicates(le)
+ 
+    first w ==
+      x: List REC := listOfMonoms w
+      null x => error "empty word !!!"
+      x.first.gen
+
+    rest w ==
+      x: List REC := listOfMonoms w
+      null x => error "empty word !!!"
+      fx: REC := first x
+      fx.exp = 1 => makeMulti rest x
+      makeMulti [[fx.gen , (fx.exp - 1)::NNI ]$REC , :rest x]
+
+    lexico(a,b) ==         --  ordre lexicographique
+      la := listOfMonoms a
+      lb := listOfMonoms b
+      while (not null la) and (not null lb) repeat
+        la.first.gen > lb.first.gen => return false
+        la.first.gen < lb.first.gen => return true
+        if la.first.exp = lb.first.exp then
+          la:=rest la
+          lb:=rest lb
+        else if la.first.exp > lb.first.exp then
+          la:=concat([la.first.gen,
+                 (la.first.exp - lb.first.exp)::NNI], rest lb)
+          lb:=rest lb
+        else
+          lb:=concat([lb.first.gen,
+                   (lb.first.exp-la.first.exp)::NNI], rest la)
+          la:=rest la
+      empty? la and not empty? lb
 
 
-        a < b ==               --  ordre lexicographique par longueur
-            la:NNI := length a; lb:NNI := length b
-            la = lb =>  lexico(a,b)
-            la < lb 
+    a < b ==               --  ordre lexicographique par longueur
+      la:NNI := length a; lb:NNI := length b
+      la = lb =>  lexico(a,b)
+      la < lb 
 
-        mirror x == reverse(x)$Rep
+    mirror x == reverse(x)$Rep
 
 @
 <<OFMONOID.dotabb>>=
diff --git a/changelog b/changelog
index e35ff72..8919c24 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,6 @@
+20091030 tpd src/axiom-website/patches.html 20091030.02.tpd.patch
+20091030 tpd src/algebra/Makefile add OFMONOID.help
+20091030 tpd books/bookvol10.3 document OrderedFreeMonoid
 20091030 tpd src/axiom-website/patches.html 20091030.01.tpd.patch
 20091030 tpd src/input/Makefile add donsimple.input 
 20091030 tpd src/input/donsimple.input added
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index b9ed5b2..808c021 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -16429,48 +16429,70 @@ SPADHELP=\
  ${HELP}/Any.help \
  ${HELP}/ApplicationProgramInterface.help \
  ${HELP}/ArrayStack.help \
- ${HELP}/AssociationList.help        ${HELP}/BalancedBinaryTree.help \
- ${HELP}/BasicOperator.help          ${HELP}/Bezier.help \
+ ${HELP}/AssociationList.help \
+ ${HELP}/BalancedBinaryTree.help \
+ ${HELP}/BasicOperator.help \
+ ${HELP}/Bezier.help \
  ${HELP}/BinaryExpansion.help \
- ${HELP}/BinarySearchTree.help       ${HELP}/CardinalNumber.help \
- ${HELP}/CartesianTensor.help        ${HELP}/Character.help \
- ${HELP}/CharacterClass.help         ${HELP}/CliffordAlgebra.help \
+ ${HELP}/BinarySearchTree.help \
+ ${HELP}/CardinalNumber.help \
+ ${HELP}/CartesianTensor.help \
+ ${HELP}/Character.help \
+ ${HELP}/CharacterClass.help \
+ ${HELP}/CliffordAlgebra.help \
  ${HELP}/CombinatorialFunction.help \
- ${HELP}/Complex.help                ${HELP}/ContinuedFraction.help \
- ${HELP}/CycleIndicators.help        ${HELP}/DeRhamComplex.help \
- ${HELP}/DecimalExpansion.help       ${HELP}/Dequeue.help \
+ ${HELP}/Complex.help \
+ ${HELP}/ContinuedFraction.help \
+ ${HELP}/CycleIndicators.help \
+ ${HELP}/DeRhamComplex.help \
+ ${HELP}/DecimalExpansion.help \
+ ${HELP}/Dequeue.help \
  ${HELP}/DistributedMultivariatePolynomial.help \
- ${HELP}/DoubleFloat.help            ${HELP}/ElementaryFunction.help \
- ${HELP}/EqTable.help                ${HELP}/Equation.help \
+ ${HELP}/DoubleFloat.help \
+ ${HELP}/ElementaryFunction.help \
+ ${HELP}/EqTable.help \
+ ${HELP}/Equation.help \
  ${HELP}/Expression.help \
  ${HELP}/EuclideanGroebnerBasisPackage.help \
- ${HELP}/Factored.help               ${HELP}/FactoredFunctions2.help \
- ${HELP}/File.help                   ${HELP}/FileName.help \
- ${HELP}/FlexibleArray.help          ${HELP}/Float.help \
+ ${HELP}/Factored.help \
+ ${HELP}/FactoredFunctions2.help \
+ ${HELP}/File.help \
+ ${HELP}/FileName.help \
+ ${HELP}/FlexibleArray.help \
+ ${HELP}/Float.help \
  ${HELP}/Fraction.help \
  ${HELP}/FullPartialFractionExpansion.help \
  ${HELP}/GeneralDistributedMultivariatePolynomial.help \
- ${HELP}/GeneralSparseTable.help ${HELP}/GroebnerFactorizationPackage.help \
+ ${HELP}/GeneralSparseTable.help \
+ ${HELP}/GroebnerFactorizationPackage.help \
  ${HELP}/GroebnerPackage.help \
- ${HELP}/Heap.help                   ${HELP}/HexadecimalExpansion.help \
+ ${HELP}/Heap.help \
+ ${HELP}/HexadecimalExpansion.help \
  ${HELP}/HomogeneousDistributedMultivariatePolynomial.help \
  ${HELP}/Integer.help \
  ${HELP}/IntegerCombinatoricFunctions.help \
  ${HELP}/IntegerLinearDependence.help \
  ${HELP}/IntegerNumberTheoryFunctions.help \
- ${HELP}/Kernel.help                 ${HELP}/KeyedAccessFile.help \
+ ${HELP}/Kernel.help \
+ ${HELP}/KeyedAccessFile.help \
  ${HELP}/LazardSetSolvingPackage.help \
- ${HELP}/LexTriangularPackage.help   ${HELP}/Library.help \
- ${HELP}/LieExponentials.help        ${HELP}/LiePolynomial.help  \
+ ${HELP}/LexTriangularPackage.help \
+ ${HELP}/Library.help \
+ ${HELP}/LieExponentials.help \
+ ${HELP}/LiePolynomial.help \
  ${HELP}/LinearOrdinaryDifferentialOperator.help \
  ${HELP}/LinearOrdinaryDifferentialOperator1.help \
- ${HELP}/LinearOrdinaryDifferentialOperator2.help ${HELP}/List.help \
- ${HELP}/LyndonWord.help             ${HELP}/Magma.help \
+ ${HELP}/LinearOrdinaryDifferentialOperator2.help \
+ ${HELP}/List.help \
+ ${HELP}/LyndonWord.help \
+ ${HELP}/Magma.help \
  ${HELP}/MakeFunction.help \
  ${HELP}/MathMLFormat.help \
  ${HELP}/MappingPackage1.help \
- ${HELP}/MappingPackage2.help        ${HELP}/MappingPackage3.help \
- ${HELP}/Matrix.help                 ${HELP}/MatrixCategory.help \
+ ${HELP}/MappingPackage2.help \
+ ${HELP}/MappingPackage3.help \
+ ${HELP}/Matrix.help \
+ ${HELP}/MatrixCategory.help \
  ${HELP}/Multiset.help \
  ${HELP}/MultivariatePolynomial.help \
  ${HELP}/NagEigenPackage.help \
@@ -16489,36 +16511,55 @@ SPADHELP=\
  ${HELP}/NagSpecialFunctionsPackage.help \
  ${HELP}/None.help \
  ${HELP}/NottinghamGroup.help \
- ${HELP}/Octonion.help               ${HELP}/OneDimensionalArray.help \
- ${HELP}/Operator.help               ${HELP}/OrderedVariableList.help \
+ ${HELP}/Octonion.help \
+ ${HELP}/OneDimensionalArray.help \
+ ${HELP}/Operator.help \
+ ${HELP}/OrderedFreeMonoid.help \
+ ${HELP}/OrderedVariableList.help \
  ${HELP}/OrderlyDifferentialPolynomial.help \
- ${HELP}/PlaneAlgebraicCurvePlot.help ${HELP}/Plot.help \
+ ${HELP}/PlaneAlgebraicCurvePlot.help \
+ ${HELP}/Plot.help \
  ${HELP}/PartialFraction.help \
- ${HELP}/Permanent.help              ${HELP}/Permutation.help \
- ${HELP}/Polynomial.help             ${HELP}/Product.help \
+ ${HELP}/Permanent.help \
+ ${HELP}/Permutation.help \
+ ${HELP}/Polynomial.help \
+ ${HELP}/Product.help \
  ${HELP}/Quaternion.help \
  ${HELP}/QuaternionCategoryFunctions2.help \
  ${HELP}/Queue.help \
- ${HELP}/RadixExpansion.help         ${HELP}/RealClosure.help \
- ${HELP}/RealSolvePackage.help       ${HELP}/RegularTriangularSet.help \
- ${HELP}/RomanNumeral.help           ${HELP}/Segment.help \
+ ${HELP}/RadixExpansion.help \
+ ${HELP}/RealClosure.help \
+ ${HELP}/RealSolvePackage.help \
+ ${HELP}/RegularTriangularSet.help \
+ ${HELP}/RomanNumeral.help \
+ ${HELP}/Segment.help \
  ${HELP}/SegmentBinding.help \
- ${HELP}/Set.help                    ${HELP}/SingleInteger.help \
- ${HELP}/SparseTable.help            \
+ ${HELP}/Set.help \
+ ${HELP}/SingleInteger.help \
+ ${HELP}/SparseTable.help \
  ${HELP}/SparseMultivariateTaylorSeries.help \
  ${HELP}/SquareMatrix.help \
- ${HELP}/SquareFreeRegularTriangularSet.help ${HELP}/Stack.help \
- ${HELP}/Stream.help                 ${HELP}/String.help \
- ${HELP}/StringTable.help            ${HELP}/Symbol.help \
- ${HELP}/TexFormat.help              \
- ${HELP}/Table.help                  ${HELP}/TextFile.help \
+ ${HELP}/SquareFreeRegularTriangularSet.help \
+ ${HELP}/Stack.help \
+ ${HELP}/Stream.help \
+ ${HELP}/String.help \
+ ${HELP}/StringTable.help \
+ ${HELP}/Symbol.help \
+ ${HELP}/TexFormat.help \
+ ${HELP}/Table.help \
+ ${HELP}/TextFile.help \
  ${HELP}/TransSolvePackage.help \
- ${HELP}/TwoDimensionalArray.help    ${HELP}/TwoDimensionalViewport.help \
+ ${HELP}/TwoDimensionalArray.help   \
+ ${HELP}/TwoDimensionalViewport.help \
  ${HELP}/UnivariateSkewPolynomial.help \
- ${HELP}/UnivariatePolynomial.help   ${HELP}/UniversalSegment.help \
- ${HELP}/Vector.help                 ${HELP}/Void.help \
- ${HELP}/WuWenTsunTriangularSet.help ${HELP}/XPBWPolynomial.help \
- ${HELP}/XPolynomial.help            ${HELP}/XPolynomialRing.help \
+ ${HELP}/UnivariatePolynomial.help \
+ ${HELP}/UniversalSegment.help \
+ ${HELP}/Vector.help \
+ ${HELP}/Void.help \
+ ${HELP}/WuWenTsunTriangularSet.help \
+ ${HELP}/XPBWPolynomial.help \
+ ${HELP}/XPolynomial.help \
+ ${HELP}/XPolynomialRing.help \
  ${HELP}/ZeroDimensionalSolvePackage.help
 
 @
@@ -16532,74 +16573,120 @@ TESTSYS=  ${OBJ}/${SYS}/bin/interpsys
 REGRESS= Any.regress \
  ApplicationProgramInterface.regress \
  ArrayStack.regress \
- AssociationList.regress        BalancedBinaryTree.regress \
- BasicOperator.regress          Bezier.regress \
+ AssociationList.regress \
+ BalancedBinaryTree.regress \
+ BasicOperator.regress \
+ Bezier.regress \
  BinaryExpansion.regress \
- BinarySearchTree.regress       CardinalNumber.regress \
- CartesianTensor.regress        Character.regress \
- CharacterClass.regress         CliffordAlgebra.regress \
+ BinarySearchTree.regress \
+ CardinalNumber.regress \
+ CartesianTensor.regress \
+ Character.regress \
+ CharacterClass.regress \
+ CliffordAlgebra.regress \
  CombinatorialFunction.regress \
- Complex.regress                ContinuedFraction.regress \
- CycleIndicators.regress        DeRhamComplex.regress \
- DecimalExpansion.regress       Dequeue.regress \
- DoubleFloat.regress            ElementaryFunction.regress \
+ Complex.regress \
+ ContinuedFraction.regress \
+ CycleIndicators.regress \
+ DeRhamComplex.regress \
+ DecimalExpansion.regress \
+ Dequeue.regress \
+ DoubleFloat.regress \
+ ElementaryFunction.regress \
  DistributedMultivariatePolynomial.regress \
- EqTable.regress                Equation.regress \
+ EqTable.regress \
+ Equation.regress \
  Expression.regress \
  EuclideanGroebnerBasisPackage.regress \
- Factored.regress               FactoredFunctions2.regress \
- File.regress                   FileName.regress \
- FlexibleArray.regress          Float.regress \
- Fraction.regress               FullPartialFractionExpansion.regress \
+ Factored.regress \
+ FactoredFunctions2.regress \
+ File.regress \
+ FileName.regress \
+ FlexibleArray.regress \
+ Float.regress \
+ Fraction.regress \
+ FullPartialFractionExpansion.regress \
  GeneralDistributedMultivariatePolynomial.regress \
- GeneralSparseTable.regress     GroebnerFactorizationPackage.regress \
+ GeneralSparseTable.regress \
+ GroebnerFactorizationPackage.regress \
  GroebnerPackage.regress \
- Heap.regress                   HexadecimalExpansion.regress \
+ Heap.regress \
+ HexadecimalExpansion.regress \
  HomogeneousDistributedMultivariatePolynomial.regress \
- Integer.regress                IntegerCombinatoricFunctions.regress \
+ Integer.regress \
+ IntegerCombinatoricFunctions.regress \
  IntegerLinearDependence.regress \
  IntegerNumberTheoryFunctions.regress \
- Kernel.regress                 KeyedAccessFile.regress \
+ Kernel.regress \
+ KeyedAccessFile.regress \
  LazardSetSolvingPackage.regress \
- LexTriangularPackage.regress   Library.regress \
- LieExponentials.regress        LiePolynomial.regress \
+ LexTriangularPackage.regress \
+ Library.regress \
+ LieExponentials.regress \
+ LiePolynomial.regress \
  LinearOrdinaryDifferentialOperator.regress \
  LinearOrdinaryDifferentialOperator1.regress \
- LinearOrdinaryDifferentialOperator2.regress List.regress \
- LyndonWord.regress             Magma.regress \
+ LinearOrdinaryDifferentialOperator2.regress \
+ List.regress \
+ LyndonWord.regress \
+ Magma.regress \
  MathMLFormat.regress \
- MakeFunction.regress           MappingPackage1.regress \
- MappingPackage2.regress        MappingPackage3.regress \
- Matrix.regress                 MatrixCategory.regress \
+ MakeFunction.regress \
+ MappingPackage1.regress \
+ MappingPackage2.regress \
+ MappingPackage3.regress \
+ Matrix.regress \
+ MatrixCategory.regress \
  Multiset.regress \
  MultivariatePolynomial.regress None.regress \
  NottinghamGroup.regress \
- Octonion.regress               OneDimensionalArray.regress \
- Operator.regress               OrderedVariableList.regress \
+ Octonion.regress \
+ OneDimensionalArray.regress \
+ Operator.regress \
+ OrderedFreeMonoid.regress \
+ OrderedVariableList.regress \
  OrderlyDifferentialPolynomial.regress \
  PartialFraction.regress \
- Permanent.regress              Permutation.regress \
- PlaneAlgebraicCurvePlot.regress Plot.regress \
+ Permanent.regress \
+ Permutation.regress \
+ PlaneAlgebraicCurvePlot.regress \
+ Plot.regress \
  Product.regress \
- Polynomial.regress             Quaternion.regress \
+ Polynomial.regress \
+ Quaternion.regress \
  QuaternionCategoryFunctions2.regress \
  Queue.regress \
- RadixExpansion.regress         RealClosure.regress \
- RealSolvePackage.regress       RegularTriangularSet.regress \
- RomanNumeral.regress           Segment.regress \
- Set.regress                    SingleInteger.regress \
- SparseTable.regress            SparseMultivariateTaylorSeries.regress \
+ RadixExpansion.regress \
+ RealClosure.regress \
+ RealSolvePackage.regress \
+ RegularTriangularSet.regress \
+ RomanNumeral.regress \
+ Segment.regress \
+ Set.regress \
+ SingleInteger.regress \
+ SparseTable.regress \
+ SparseMultivariateTaylorSeries.regress \
  SquareMatrix.regress \
- SquareFreeRegularTriangularSet.regress Stack.regress \
- Stream.regress                 String.regress \
- StringTable.regress            Symbol.regress \
- Table.regress                  TexFormat.regress \
- TextFile.regress               TransSolvePackage.regress \
- TwoDimensionalArray.regress    UnivariateSkewPolynomial.regress \
- UnivariatePolynomial.regress   UniversalSegment.regress \
- Vector.regress                 Void.regress \
- WuWenTsunTriangularSet.regress XPBWPolynomial.regress \
- XPolynomial.regress            XPolynomialRing.regress \
+ SquareFreeRegularTriangularSet.regress \
+ Stack.regress \
+ Stream.regress \
+ String.regress \
+ StringTable.regress \
+ Symbol.regress \
+ Table.regress \
+ TexFormat.regress \
+ TextFile.regress \
+ TransSolvePackage.regress \
+ TwoDimensionalArray.regress \
+ UnivariateSkewPolynomial.regress \
+ UnivariatePolynomial.regress \
+ UniversalSegment.regress \
+ Vector.regress \
+ Void.regress \
+ WuWenTsunTriangularSet.regress \
+ XPBWPolynomial.regress \
+ XPolynomial.regress \
+ XPolynomialRing.regress \
  ZeroDimensionalSolvePackage.regress
 # these requires graphics
 # TwoDimensionalViewport
@@ -17515,6 +17602,16 @@ ${HELP}/Operator.help: ${BOOKS}/bookvol10.3.pamphlet
             >${INPUT}/Operator.input
 	@echo "Operator (OP)" >>${HELPFILE}
 
+${HELP}/OrderedFreeMonoid.help: ${BOOKS}/bookvol10.3.pamphlet
+	@echo 7855 create OrderedFreeMonoid.help from \
+           ${BOOKS}/bookvol10.3.pamphlet
+	@${TANGLE} -R"OrderedFreeMonoid.help" ${BOOKS}/bookvol10.3.pamphlet \
+           >${HELP}/OrderedFreeMonoid.help
+	@cp ${HELP}/OrderedFreeMonoid.help ${HELP}/OFMONOID.help
+	@${TANGLE} -R"OrderedFreeMonoid.input" ${BOOKS}/bookvol10.3.pamphlet \
+            >${INPUT}/OrderedFreeMonoid.input
+	@echo "OrderedFreeMonoid (OFMONOID)" >>${HELPFILE}
+
 ${HELP}/OrderedVariableList.help: ${BOOKS}/bookvol10.3.pamphlet
 	@echo 7860 create OrderedVariableList.help from \
            ${BOOKS}/bookvol10.3.pamphlet
diff --git a/src/axiom-website/patches.html b/src/axiom-website/patches.html
index f3cffcc..6db18b6 100644
--- a/src/axiom-website/patches.html
+++ b/src/axiom-website/patches.html
@@ -2199,5 +2199,7 @@ src/input/lexp.input removed, duplicate of LEXP domain<br/>
 src/input/numericgamma.input added<br/>
 <a href="patches/20091030.01.tpd.patch">20091030.01.tpd.patch</a>
 src/input/donsimple.input added<br/>
+<a href="patches/20091030.02.tpd.patch">20091030.02.tpd.patch</a>
+books/bookvol10.3 document OrderedFreeMonoid<br/>
  </body>
 </html>
