)abbrev package ICDEN InnerCommonDenominator
--% InnerCommonDenominator
++ Author: Manuel Bronstein
++ Date Created: 2 May 1988
++ Description: InnerCommonDenominator provides functions to compute
++ the common denominator of a finite linear aggregate of elements
++ of the quotient field of an integral domain.
++ Keywords: gcd, quotient, common, denominator.
InnerCommonDenominator(R, Q, A, B) : Exports == Implementation where
  R : IntegralDomain
  Q : QuotientFieldCategory R
  A : Join(LinearAggregate R, finiteAggregate)
  B : Join(LinearAggregate Q, finiteAggregate)

  Exports ==> with
    commonDenominator : B -> R
      ++ commonDenominator([q1, ..., qn]) returns a common denominator
      ++ d for q1, ..., qn.
    clearDenominator : B -> A
      ++ clearDenominator([q1, ..., qn]) returns \spad{[p1, ..., pn]} such that
      ++ \spad{qi = pi/d} where d is a common denominator for the qi's.
    splitDenominator : B -> Record(num : A, den : R)
      ++ splitDenominator([q1, ..., qn]) returns
      ++ \spad{[[p1, ..., pn], d]} such that
      ++ \spad{qi = pi/d} and d is a common denominator for the qi's.

  Implementation ==> add
    import from FiniteLinearAggregateFunctions2(Q, B, R, A)

    clearDenominator l ==
      d := commonDenominator l
      map(x +-> numer(d*x), l)

    splitDenominator l ==
      d := commonDenominator l
      [map(x +-> numer(d*x), l), d]

    if R has GcdDomain then
      commonDenominator l == reduce(lcm, map(denom, l), 1)
    else
      commonDenominator l == reduce("*", map(denom, l), 1)

)abbrev package CDEN CommonDenominator
--% CommonDenominator
++ Author: Manuel Bronstein
++ Date Created: 2 May 1988
++ Description: CommonDenominator provides functions to compute the
++ common denominator of a finite linear aggregate of elements of
++ the quotient field of an integral domain.
++ Keywords: gcd, quotient, common, denominator.
CommonDenominator(R, Q, A) : Exports == Implementation where
  R : IntegralDomain
  Q : QuotientFieldCategory R
  A : FiniteLinearAggregate Q

  Exports ==> with
    commonDenominator : A -> R
      ++ commonDenominator([q1, ..., qn]) returns a common denominator
      ++ d for q1, ..., qn.
    clearDenominator : A -> A
      ++ clearDenominator([q1, ..., qn]) returns \spad{[p1, ..., pn]} such that
      ++ \spad{qi = pi/d} where d is a common denominator for the qi's.
    splitDenominator : A -> Record(num : A, den : R)
      ++ splitDenominator([q1, ..., qn]) returns
      ++ \spad{[[p1, ..., pn], d]} such that
      ++ \spad{qi = pi/d} and d is a common denominator for the qi's.

  Implementation ==> add
    clearDenominator l ==
      d := commonDenominator l
      map(x +-> numer(d*x)::Q, l)

    splitDenominator l ==
      d := commonDenominator l
      [map(x +-> numer(d*x)::Q, l), d]

    if R has GcdDomain then
      qlcm : (Q, Q) -> Q

      qlcm(a, b)          == lcm(numer a, numer b)::Q
      commonDenominator l == numer reduce(qlcm, map(x +-> denom(x)::Q, l), 1)
    else
      commonDenominator l == numer reduce("*", map(x +-> denom(x)::Q, l), 1)


)abbrev package PCDEN PolynomialCommonDenominator
++ Author: Manuel Bronstein
++ Description: PolynomialCommonDenominator provides
++  functions to compute and clear the common denominator of the
++  coefficients of polynomials over the quotient field.
++ Keywords: gcd, quotient, common, denominator, polynomial.

PolynomialCommonDenominator(R, Q, E, VarSet, P
                           ) : Exports == Implementation where
  R : IntegralDomain
  Q : QuotientFieldCategory R
  E : OrderedAbelianMonoidSup
  VarSet : OrderedSet
  P : PolynomialCategory(Q, E, VarSet)

  Exports ==> with
    commonDenominator : P -> R
      ++ commonDenominator(q) returns a common denominator d for
      ++ the coefficients of q.
    clearDenominator : P -> P
      ++ clearDenominator(q) returns p such that \spad{q = p/d} where d is
      ++ a common denominator for the coefficients of q.
    splitDenominator : P -> Record(num : P, den : R)
      ++ splitDenominator(q) returns \spad{[p, d]} such that \spad{q = p/d}
      ++ and d is a common denominator for the coefficients of q.

  Implementation ==> add

    import from CommonDenominator(R, Q, List Q)

    commonDenominator p == commonDenominator coefficients p

    clearDenominator p ==
        d := commonDenominator p
        map(x +-> numer(d*x)::Q, p)

    splitDenominator p ==
        d := commonDenominator p
        [map(x +-> numer(d*x)::Q, p), d]


)abbrev package UPCDEN UnivariatePolynomialCommonDenominator
UnivariatePolynomialCommonDenominator(R : IntegralDomain,
  Q : QuotientFieldCategory R, UP : UnivariatePolynomialCategory Q) ==
    PolynomialCommonDenominator(R, Q, NonNegativeInteger,
                                SingletonAsOrderedSet, UP)


)abbrev package MCDEN MatrixCommonDenominator
--% MatrixCommonDenominator
++ Author: Manuel Bronstein
++ Date Created: 2 May 1988
++ Description: MatrixCommonDenominator provides functions to
++ compute the common denominator of a matrix of elements of the
++ quotient field of an integral domain.
++ Keywords: gcd, quotient, matrix, common, denominator.
MatrixCommonDenominator(R, Q) : Exports == Implementation where
  R : IntegralDomain
  Q : QuotientFieldCategory R

  VR ==> Vector R
  VQ ==> Vector Q

  Exports ==> with
    commonDenominator : Matrix Q -> R
      ++ commonDenominator(q) returns a common denominator d for
      ++ the elements of q.
    clearDenominator : Matrix Q -> Matrix R
      ++ clearDenominator(q) returns p such that \spad{q = p/d} where d is
      ++ a common denominator for the elements of q.
    splitDenominator : Matrix Q -> Record(num : Matrix R, den : R)
      ++ splitDenominator(q) returns \spad{[p, d]} such that \spad{q = p/d} and d
      ++ is a common denominator for the elements of q.

  Implementation ==> add
    import from ListFunctions2(Q, R)
    import from MatrixCategoryFunctions2(Q, VQ, VQ, Matrix Q, R, VR, VR, Matrix R)

    clearDenominator m ==
      d := commonDenominator m
      map(x +-> numer(d*x), m)

    splitDenominator m ==
      d := commonDenominator m
      [map(x +-> numer(d*x), m), d]

    if R has GcdDomain then
      commonDenominator m == lcm map(denom, parts m)
    else
      commonDenominator m == reduce("*",map(denom, parts m),1)$List(R)

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