## `expand` -- expand an expression

#### Introduction

`expand(`f`)` expands the arithmetical expression `f`.

#### Call(s)

`expand(f)`
`expand(f, g1, g2, ...)`

#### Parameters

`f, g1, g2, ...` | - | arithmetical expressions

#### Returns

an arithmetical expression.

### Overloadable:

`f`

#### Side Effects

`expand` is sensitive to properties of identifiers set via `assume`.

#### Further Documentation

Chapter ``Manipulating Expressions'' of the Tutorial.

#### Related Functions

`collect`, `combine`, `denom`, `factor`, `normal`, `numer`, `partfrac`, `rationalize`, `rectform`, `rewrite`, `simplify`

#### Details

- The most important use of `expand` is the application of the distributivity law to rewrite products of sums as sums of products. In this respect, `expand` is the inverse function of `factor`.

  Powers of sums with positive integer exponents are expanded as well, but powers of sums with negative integer exponents are not expanded; see example 2.

  The numerator of a fraction is expanded, and then the fraction is rewritten as a sum of fractions with simpler numerators; see example 1. In a certain sense, this is the inverse functionality of `normal`. Use `partfrac` for a more powerful way to rewrite a fraction as a sum of simpler fractions.

- `expand(`f`)` also applies the following rewriting rules to powers occurring as subexpressions in `f`:
  - x^(a + b) = x^a*x^b
  - (x*y)^a = x^b*y^b
  - (x^a)^b=x^(a*b)
  The last two rules are only valid under certain additional restrictions, e.g., when `b` is an integer. Except for the third rule, this behavior of `expand` is the inverse functionality of `combine`. See example 3.
- `expand` works recursively on the subexpressions of an expression `f`. If `f` is of one of the container types `array`, `list`, `set`, or `table`, `expand` only returns `f` and does not map on the entries. If you want to expand all entries of one of the containers please use `map`. See example 4.
- If optional arguments `g1, g2, ...` are present, then any subexpression of `f` that is equal to one of these additional arguments is not expanded; see example 5. See section ``Background'' for a description how this works.
- Properties of identifiers are taken into account (see `assume`). Identifiers without any properties are assumed to be complex. See example 6.
- `expand` also handles various types of special mathematical functions. It rewrites a single call of a special function with a complicated argument as a sum or a product of several calls of the same function or related functions with simpler arguments. In this respect, `expand` is the inverse function of `combine`.

  In particular, `expand` implements the functional equations of the exponential function and the logarithm, the gamma function and the polygamma function, and the addition theorems for the trigonometric functions and the hyperbolic functions. See example 7.

- `expand` is a function of the system kernel.

#### Example 1

`expand` expands products of sums by multiplying out:

    >> expand((x + 1)*(y + z)^2)

                                         2    2      2      2
                      2 y z + 2 x y z + y  + z  + x y  + x z

After expansion of the numerator, a fraction is rewritten as a sum of fractions:

    >> expand((x + 1)^2*y/(y + z)^2)

                                                   2
                             y        2 x y       x  y
                          -------- + -------- + --------
                                 2          2          2
                          (y + z)    (y + z)    (y + z)

#### Example 2

Powers of sums with positive integer exponents are expanded:

    >> expand((x + y)^2)

                                           2    2
                                  2 x y + x  + y

Powers of sums with negative integer exponents are regarded as denominators of fractions and are not expanded:

    >> expand((x + y)^(-2))

                                        1
                                     --------
                                            2
                                     (x + y)

#### Example 3

A power with a sum in the exponent is rewritten as a product of powers:

    >> expand(x^(y + z + 2))

                                      2  y  z
                                     x  x  x

If one of the additive terms in the exponent is negative, the power is expanded into a fraction of powers:

    >> expand((x + y)^(z - 2))

                                            z
                                     (x + y)
                                     --------
                                            2
                                     (x + y)

#### Example 4

`expand` works in a recursive fashion. In the following example, the power (x + y)^(z + 2) is first expanded into a product of two powers. Then the power (x + y)^2 is expanded into a sum. Finally, the product of the latter sum and the remaining power (x + y)^2 is multiplied out:

    >> expand((x + y)^(z + 2))

                                 z    2        z    2        z
                    2 x y (x + y)  + x  (x + y)  + y  (x + y)

Here is another example:

    >> expand(2^((x + y)^2))

                                    2   2
                                   x   y   2 x y
                                  2   2   2

`expand` does not map on the entries of a container type:

    >> expand([(a + b)^2, c]), expand({(a + b)^2, c})

                                   2                 2
                           [(a + b) , c], {c, (a + b) }

Use `map` in order to expand all entries of a container:

    >> map([(a + b)^2, c], expand), map({(a + b)^2, c}, expand)

                              2    2                   2    2
                    [2 a b + a  + b , c], {c, 2 a b + a  + b }

#### Example 5

If additional arguments are provided, `expand` performs only a partial expansion. These additional expressions, such as `x + 1` in the following example, are not expanded:

    >> expand((x + 1)*(y + z))

                                 y + z + x y + x z

    >> expand((x + 1)*(y + z), x + 1)

                               y (x + 1) + z (x + 1)

#### Example 6

The following expansions are not valid for all values `a`, `b` from the complex plane. Therefore no expansion is done:

    >> expand(ln(a^2)), expand(ln(a*b))

                                      2
                                  ln(a ), ln(a b)

The expansions are valid under the assumption that `a` is a positive real number:

    >> assume(a > 0):  expand(ln(a^2)), expand(ln(a*b))

                              2 ln(a), ln(a) + ln(b)

    >> unassume(a):

#### Example 7

The addition theorems of trigonometry are implemented by `"`expand"-slots of the trigonometric functions `sin` and `cos`:

    >> expand(sin(a + b)), expand(sin(2*a))

                  cos(a) sin(b) + cos(b) sin(a), 2 cos(a) sin(a)

The same is true for the hyperbolic functions `sinh` and `cosh`:

    >> expand(cosh(a + b)), expand(cosh(2*a))

                                                             2
                 cosh(a) cosh(b) + sinh(a) sinh(b), 2 cosh(a)  - 1

The exponential function with a sum as argument is expanded via `exp::expand`:

    >> expand(exp(a + b))

                                   exp(a) exp(b)

Here are some more expansion examples for the functions `sum`, `fact`, `abs`, `coth`, `sign`, `binomial`, `beta`, `gamma`, `log`, `cot`, `tan`, `exp` and `psi`:

    >> sum(x + exp(x),x);  expand(%)

                                sum(x + exp(x), x)

                                 2
                                x    x     exp(x)
                                -- - - + ----------
                                2    2   exp(1) - 1

    >> fact(x + 1);  expand(%)

                                    fact(x + 1)

                                  fact(x) (x + 1)

    >> abs(a*b);  expand(%)

                                     abs(a b)

                                   abs(a) abs(b)

    >> coth(a + b);  expand(%)

                                    coth(a + b)

                   cosh(a) cosh(b)
          --------------------------------- +
          cosh(a) sinh(b) + cosh(b) sinh(a)

                      sinh(a) sinh(b)
             ---------------------------------
             cosh(a) sinh(b) + cosh(b) sinh(a)

    >> coth(a*b);  expand(%)

                                     coth(a b)

                                     cosh(a b)
                                     ---------
                                     sinh(a b)

    >> sign(a*b);  expand(%)

                                     sign(a b)

                                  sign(a) sign(b)

    >> tan(a);  expand(%)

                                      tan(a)

                                      sin(a)
                                      ------
                                      cos(a)

    >> binomial(n, m);  expand(%)

                                  binomial(n, m)

                                    n gamma(n)
                          -------------------------------
                          m gamma(m) (n - m) gamma(n - m)

    >> beta(n, m);  expand(%)

                                    beta(m, n)

                                 gamma(m) gamma(n)
                                 -----------------
                                   gamma(m + n)

    >> gamma(x+1);  expand(%)

                                   gamma(x + 1)

                                    x gamma(x)

    >> log(10, x); expand(%)

                                    log(10, x)

                                      ln(x)
                                      ------
                                      ln(10)

    >> cot(x);  expand(%)

                                      cot(x)

                                      cos(x)
                                      ------
                                      sin(x)

    >> exp(x + y);  expand(%)

                                    exp(x + y)

                                   exp(x) exp(y)

    >> psi(x + 2);  expand(%)

                                    psi(x + 2)

                                         1     1
                                psi(x) + - + -----
                                         x   x + 1

#### Example 8

This example illustrates how to extend the functionality of `expand` to user-defined mathematical functions. As an example, we consider the sine function. (Of course, the system function `sin` already has an `"`expand" slot; see example 7.)

We first embed our function into a function environment, which we call `Sin`, in order not to overwrite the system function `sin`. Then we implement the addition theorem sin(x + y) = sin(x)*cos(y) + sin(y)*cos(x) in the `"`expand" slot of the function environment, i.e., the slot routine `Sin::expand`:

    >> Sin := funcenv(Sin):
       Sin::expand := proc(u) // compute expand(Sin(u))
         local x, y;
       begin
         // recursively expand the argument u
         u := expand(u);

         if type(u) = "_plus" then // u is a sum

           x := op(u, 1); // the first term
           y := u - x;    // the remaining terms

           // apply the addition theorem and
           // expand the result again
           expand(Sin(x)*cos(y) + cos(x)*Sin(y))
         else
           Sin(u)
         end_if
       end_proc:

Now, if `expand` encounters a subexpression of the form `Sin(u)`, it calls `Sin::expand(u)` to expand `Sin(u)`. The following command first expands the argument `a*(b+c)` via the recursive call in `Sin::expand`, then applies the addition theorem, and finally `expand` itself expands the product of the result with `z`:

    >> expand(z*Sin(a*(b + c)))

                     z Sin(a b) cos(a c) + z Sin(a c) cos(a b)

The expansion after the application of the addition theorem in `Sin::expand` is necessary to handle the case when `u` is a sum with more than two terms: then `y` is again a sum, and `cos(y)` and `Sin(y)` are expanded recursively:

    >> expand(Sin(a + b + c))

          Sin(a) cos(b) cos(c) + Sin(b) cos(a) cos(c) +

             Sin(c) cos(a) cos(b) - Sin(a) sin(b) sin(c)

#### Background

- With optional arguments `g1, g2, ...`, the expansion of certain subexpressions of `f` can be prevented. This works as follows: every occurrence of `g1, g2, ...` in `f` is replaced by an auxiliary variable before the expansion, and afterwards the auxiliary variables are replaced by the original subexpressions.
- Users can extend the functionality of `expand` to their own special mathematical functions via `overloading`. To this end, embed your function into a function environment `g` and implement the behavior of `expand` for this function in the `"`expand" slot of the function environment.

  Whenever `expand` encounters a subexpression of the form `g(u,..)`, it issues the call `g::expand(u,..)` to the slot routine to expand the subexpression, passing the not yet expanded arguments `u,..` of `g` as arguments. The result of this call is not expanded any further by `expand`. See example 8 above.

- Similarly, an `"`expand" slot can be defined for a user-defined library domain `T`. Whenever `expand` encounters a subexpression `d` of domain type `T`, it issues the call `T::expand(d)` to the slot routine to expand `d`. The result of this call is not expanded any further by `expand`. If `T` has no `"`expand" slot, then `d` remains unchanged.

#### Changes

- `expand` now reacts to properties of identifiers.

Do you have questions or comments?
Copyright © SciFace Software GmbH & Co. KG 2000