====================================================================
UnivariatePolynomial examples
====================================================================

The domain constructor UnivariatePolynomial (abbreviated UP) creates
domains of univariate polynomials in a specified variable.  For
example, the domain UP(a1,POLY FRAC INT) provides polynomials in the
single variable a1 whose coefficients are general polynomials with
rational number coefficients.

Restriction: FriCAS does not allow you to create types where
UnivariatePolynomial is contained in the coefficient type of
Polynomial. Therefore, UP(x,POLY INT) is legal but POLY UP(x,INT)
is not.

UP(x,INT) is the domain of polynomials in the single variable x with 
integer coefficients.

  (p,q) : UP(x,INT)
                          Type: Void

  p := (3*x-1)**2 * (2*x + 8)
       3      2
    18x  + 60x  - 46x + 8
                          Type: UnivariatePolynomial(x,Integer)

  q := (1 - 6*x + 9*x**2)**2
       4       3      2
    81x  - 108x  + 54x  - 12x + 1
                          Type: UnivariatePolynomial(x,Integer)

The usual arithmetic operations are available for univariate polynomials.

  p**2 + p*q 
         7        6        5         4        3        2
    1458x  + 3240x  - 7074x  + 10584x  - 9282x  + 4120x  - 878x + 72
                          Type: UnivariatePolynomial(x,Integer)

The operation leadingCoefficient extracts the coefficient of the term
of highest degree.

  leadingCoefficient p
    18
                          Type: PositiveInteger

The operation degree returns the degree of the polynomial.  Since the
polynomial has only one variable, the variable is not supplied to
operations like degree.

  degree p
    3
                          Type: PositiveInteger

The reductum of the polynomial, the polynomial obtained by subtracting
the term of highest order, is returned by reductum.

  reductum p
       2
    60x  - 46x + 8
                          Type: UnivariatePolynomial(x,Integer)

The operation gcd computes the greatest common divisor of two polynomials.

  gcd(p,q)
      2
    9x  - 6x + 1
                          Type: UnivariatePolynomial(x,Integer)

The operation lcm computes the least common multiple.

  lcm(p,q)
        5       4       3       2
    162x  + 432x  - 756x  + 408x  - 94x + 8
                          Type: UnivariatePolynomial(x,Integer)

The operation resultant computes the resultant of two univariate
polynomials.  In the case of p and q, the resultant is 0 because they
share a common root.

  resultant(p,q)
    0
                          Type: NonNegativeInteger

To compute the derivative of a univariate polynomial with respect to its
variable, use the function D.

  D p
       2
    54x  + 120x - 46
                          Type: UnivariatePolynomial(x,Integer)

Univariate polynomials can also be used as if they were functions.  To
evaluate a univariate polynomial at some point, apply the polynomial
to the point.

  p(2)
    300
                          Type: PositiveInteger

The same syntax is used for composing two univariate polynomials, i.e.
substituting one polynomial for the variable in another.  This substitutes 
q for the variable in p.

  p(q)
             12            11            10            9            8
     9565938x   - 38263752x   + 70150212x   - 77944680x  + 58852170x
   + 
                7            6           5           4          3         2
     - 32227632x  + 13349448x  - 4280688x  + 1058184x  - 192672x  + 23328x
   + 
     - 1536x + 40
                          Type: UnivariatePolynomial(x,Integer)

This substitutes p for the variable in q.

  q(p)
             12             11             10             9              8
     8503056x   + 113374080x   + 479950272x   + 404997408x  - 1369516896x
   + 
                 7              6              5              4             3
     - 626146848x  + 2939858712x  - 2780728704x  + 1364312160x  - 396838872x
   + 
              2
     69205896x  - 6716184x + 279841
                          Type: UnivariatePolynomial(x,Integer)

To obtain a list of coefficients of the polynomial, use coefficients.

  l := coefficients p
    [18,60,- 46,8]
                          Type: List Integer

From this you can use gcd and reduce to compute the content of the polynomial.

  reduce(gcd,l)
    2
                          Type: PositiveInteger

Alternatively (and more easily), you can just call content.

  content p
    2
                          Type: PositiveInteger

Note that the operation coefficients omits the zero coefficients from
the list.  Sometimes it is useful to convert a univariate polynomial
to a vector whose i-th position contains the degree i-1 coefficient of
the polynomial.

  ux := (x**4+2*x+3)::UP(x,INT)
     4
    x  + 2x + 3
                          Type: UnivariatePolynomial(x,Integer)

To get a complete vector of coefficients, use the operation vectorise,
which takes a univariate polynomial and an integer denoting the length
of the desired vector.

  vectorise(ux,5)
    [3,2,0,0,1]
                          Type: Vector Integer

It is common to want to do something to every term of a polynomial,
creating a new polynomial in the process.

This is a function for iterating across the terms of a polynomial,
squaring each term.

  squareTerms(p) ==   reduce(+,[t**2 for t in monomials p])
                          Type: Void

Recall what p looked like.

  p
       3      2
    18x  + 60x  - 46x + 8
                          Type: UnivariatePolynomial(x,Integer)

We can demonstrate squareTerms on p.

  squareTerms p
        6        4        2
    324x  + 3600x  + 2116x  + 64
                          Type: UnivariatePolynomial(x,Integer)

When the coefficients of the univariate polynomial belong to a field,
it is possible to compute quotients and remainders.  For example, when
the coefficients are rational numbers, as opposed to integers.  The
important property of a field is that non-zero elements can be divided
and produce another element. The quotient of the integers 2 and 3 is
not another integer.

  (r,s) : UP(a1,FRAC INT)
                          Type: Void

  r := a1**2 - 2/3
      2   2
    a1  - -
          3
                          Type: UnivariatePolynomial(a1,Fraction Integer)

  s := a1 + 4
    a1 + 4
                          Type: UnivariatePolynomial(a1,Fraction Integer)

When the coefficients are rational numbers or rational expressions,
the operation quo computes the quotient of two polynomials.

  r quo s
    a1 - 4
                          Type: UnivariatePolynomial(a1,Fraction Integer)

The operation rem computes the remainder.

  r rem s
    46
    --
     3
                          Type: UnivariatePolynomial(a1,Fraction Integer)

The operation divide can be used to return a record of both components.

  d := divide(r, s)
                                 46
    [quotient= a1 - 4,remainder= --]
                                  3
       Type: Record(quotient: UnivariatePolynomial(a1,Fraction Integer),
                    remainder: UnivariatePolynomial(a1,Fraction Integer))

Now we check the arithmetic!

  r - (d.quotient * s + d.remainder) 
    0
                          Type: UnivariatePolynomial(a1,Fraction Integer)

It is also possible to integrate univariate polynomials when the
coefficients belong to a field.

  integrate r
    1   3   2
    - a1  - - a1
    3       3
                          Type: UnivariatePolynomial(a1,Fraction Integer)

  integrate s
    1   2
    - a1  + 4a1
    2
                          Type: UnivariatePolynomial(a1,Fraction Integer)

One application of univariate polynomials is to see expressions in terms
of a specific variable.

We start with a polynomial in a1 whose coefficients are quotients of
polynomials in b1 and b2.

  t : UP(a1,FRAC POLY INT)
                          Type: Void

Since in this case we are not talking about using multivariate
polynomials in only two variables, we use Polynomial.  We also use
Fraction because we want fractions.

  t := a1**2 - a1/b2 + (b1**2-b1)/(b2+3)
                    2
      2    1      b1  - b1
    a1  - -- a1 + --------
          b2       b2 + 3
                   Type: UnivariatePolynomial(a1,Fraction Polynomial Integer)

We push all the variables into a single quotient of polynomials.

  u : FRAC POLY INT := t
       2  2      2           2
     a1 b2  + (b1  - b1 + 3a1  - a1)b2 - 3a1
     ---------------------------------------
                      2
                    b2  + 3b2
                          Type: Fraction Polynomial Integer

Alternatively, we can view this as a polynomial in the variable This
is a mode-directed conversion: you indicate as much of the structure
as you care about and let FriCAS decide on the full type and how to do
the transformation.

  u :: UP(b1,?)
                                2
        1     2      1        a1 b2 - a1
     ------ b1  - ------ b1 + ----------
     b2 + 3       b2 + 3          b2
                   Type: UnivariatePolynomial(b1,Fraction Polynomial Integer)

See Also:
o )help MultivariatePolynomial
o )help DistributedMultivariatePolynomial
o )show UnivariatePolynomial

