--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.

)abbrev domain MODMONOM ModuleMonomial
++ Description:
++ This package \undocumented
ModuleMonomial(IS: OrderedSet,
               E: SetCategory,
               ff:(MM, MM) -> Boolean): T == C where

   MM ==> Record(index:IS, exponent:E)

   T == Join(OrderedSet, HomotopicTo MM)  with
        exponent: $ -> E
		++ exponent(x) \undocumented
        index: $ -> IS
		++ index(x) \undocumented
        construct: (IS, E) -> $
		++ construct(i,e) \undocumented
   C == MM  add
        Rep:= MM
        x:$ < y:$ == ff(x::Rep, y::Rep)
        exponent(x:$):E == x.exponent
        index(x:$): IS == x.index
        coerce(x:$):MM == x::Rep::MM
        coerce(x:MM):$ == x::Rep::$
        construct(i:IS, e:E):$ == [i, e]$MM::Rep::$

)abbrev domain GMODPOL GeneralModulePolynomial
++ Description:
++ This package \undocumented
GeneralModulePolynomial(vl, R, IS, E, ff, P): public  ==  private where
  vl: List(Symbol)
  R: CommutativeRing
  IS: OrderedSet
  NNI ==> NonNegativeInteger
  E: DirectProductCategory(#vl, NNI)
  MM ==> Record(index:IS, exponent:E)
  ff: (MM, MM) -> Boolean
  OV  ==> OrderedVariableList(vl)
  P: PolynomialCategory(R, E, OV)
  ModMonom ==> ModuleMonomial(IS, E, ff)


  public  ==  Join(Module(P), Module(R))  with
        leadingCoefficient: $ -> R
		++ leadingCoefficient(x) \undocumented
        leadingMonomial: $ -> ModMonom
		++ leadingMonomial(x) \undocumented
        leadingExponent: $ -> E
		++ leadingExponent(x) \undocumented
        leadingIndex: $ -> IS
		++ leadingIndex(x) \undocumented
        reductum: $ -> $
		++ reductum(x) \undocumented
        monomial: (R, ModMonom) -> $
		++ monomial(r,x) \undocumented
        unitVector: IS -> $
		++ unitVector(x) \undocumented
        build: (R, IS, E) -> $
		++ build(r,i,e) \undocumented
        multMonom: (R, E, $) -> $
		++ multMonom(r,e,x) \undocumented
        *: (P,$) -> $
		++ p*x \undocumented


  private  ==  FreeModule(R, ModMonom)  add
        Rep:= FreeModule(R, ModMonom)
        leadingMonomial(p:$):ModMonom == leadingSupport(p)$Rep
        leadingExponent(p:$):E == exponent(leadingMonomial p)
        leadingIndex(p:$):IS == index(leadingMonomial p)
        unitVector(i:IS):$ == monomial(1,[i, 0$E]$ModMonom)


 -----------------------------------------------------------------------------

        build(c:R, i:IS, e:E):$  ==  monomial(c, construct(i, e))

 -----------------------------------------------------------------------------

     ----   WARNING: assumes c ~= 0

        multMonom(c:R, e:E, mp:$):$  ==
            zero? mp => mp
            monomial(c * leadingCoefficient mp, [leadingIndex mp,
                     e + leadingExponent mp]) + multMonom(c, e, reductum mp)

 -----------------------------------------------------------------------------


        ((p:P) * (mp:$)):$  ==
            zero? p => 0
            multMonom(leadingCoefficient p, degree p, mp) +
               reductum(p) * mp

