## `rectform` -- rectangular form of a complex expression

#### Introduction

`rectform(`z`)` computes the rectangular form of the complex expression z, i.e., it splits z into z = Re(z) + I*Im(z).

#### Call(s)

`rectform(z)`

#### Parameters

`z` | - | an arithmetical expression, a polynomial, a series expansion, an array, a list, or a set

#### Returns

an element of the domain `rectform` if `z` is an arithmetical expression, and an object of the same type as `z` otherwise.

#### Side Effects

The function is sensitive to properties of identifiers set via `assume`; see example 3.

### Overloadable:

`z`

#### Further Documentation

Chapter ``Manipulating Expressions'' of the Tutorial.

#### Related Functions

`abs`, `assume`, `collect`, `combine`, `conjugate`, `expand`, `Im`, `normal`, `radsimp`, `Re`, `rewrite`, `sign`, `simplify`

#### Details

- `rectform``(z)` tries to split `z` into its real and imaginary part and to return `z` in the form Re(z) + I*Im(z).

  `rectform` works recursively, i.e., it first tries to split each subexpression of `z` into its real and imaginary part and then tackles `z` as a whole.

- Use `Re` and `Im` to extract the real and imaginary parts, respectively, from the result of `rectform`. See example 1.

- `rectform` is more powerful than a direct application of `Re` and `Im` to `z`. However, usually it is much slower. For constant arithmetical expressions, it is therefore recommended to use the functions `Re` and `Im` directly. See example 2.

- The main use of `rectform` is for symbolic expressions, and properties of identifiers are taken into account (see `assume`). An identifier without any property is assumed to be complex valued. See example 3.

- If `z` is a array, a list, or a set, then `rectform` is applied to each entry of `z`.

  If `z` is a polynomial or a series expansion, of type `Series::Puiseux` or `Series::gseries`, then `rectform` is applied to each coefficient of `z`.

  See example 5.

- The result `r := rectform(z)` is an element of the domain `rectform`. Such a domain element consists of three operands, satisfying the following equality:
  `z = op(r, 1) + I*op(r, 2) + op(r, 3)`.
  The first two operands are real arithmetical expressions, and the third operand is an expression that cannot be splitted into its real and imaginary part.

  Sometimes `rectform` is unable to compute the required decomposition. Then it still tries to return some partial information by extracting as much as possible from the real and imaginary part of `z`. The extracted parts are stored in the first two operands, and the third operand contains the remainder, where no further extraction is possible. In extreme cases, the first two operands may even be zero. Example 6 illustrates some possible cases.

- Arithmetical operations with elements of the domain type `rectform` are possible. The result of an arithmetical operation is again an element of this domain (see example 4).

- Most MuPAD functions handling arithmetical expressions (e.g., `expand`, `normal`, `simplify` etc.) can be applied to elements of type `rectform`. They act on each of the three operands individually.

- Use `expr` to convert the result of `rectform` into an element of a basic domain; see example 4.

#### Example 1

The rectangular form of sin (z) for complex values z is:

    >> delete z: r := rectform(sin(z))

                sin(Re(z)) cosh(Im(z)) + (cos(Re(z)) sinh(Im(z))) I

The real and the imaginary part can be extracted as follows:

    >> Re(r), Im(r)

                  sin(Re(z)) cosh(Im(z)), cos(Re(z)) sinh(Im(z))

The complex conjugate of `r` can be obtained directly:

    >> conjugate(r)

               sin(Re(z)) cosh(Im(z)) + (-cos(Re(z)) sinh(Im(z))) I

#### Example 2

The real and the imaginary part of a constant arithmetical expression can be determined by the functions `Re` and `Im`, as in the following example:

    >> Re(ln(-4)) + I*Im(ln(-4))

                                   I PI + ln(4)

In fact, they work much faster than `rectform`. However, they fail to compute the real and the imaginary part of arbitrary symbolic expressions, such as for the term exp(I*sin(z)):

    >> delete z: f := exp(I*sin(z)):
       Re(f), Im(f)

                       Re(exp(I sin(z))), Im(exp(I sin(z)))

The function `rectform` is more powerful. It is able to split the expression above into its real and imaginary part:

    >> r := rectform(f)

          cos(sin(Re(z)) cosh(Im(z))) exp(-cos(Re(z)) sinh(Im(z))) +

             (sin(sin(Re(z)) cosh(Im(z))) exp(-cos(Re(z)) sinh(Im(z)))) I

Now we can extract the real and the imaginary part of `f`:

    >> Re(r)

             cos(sin(Re(z)) cosh(Im(z))) exp(-cos(Re(z)) sinh(Im(z)))

    >> Im(r)

             sin(sin(Re(z)) cosh(Im(z))) exp(-cos(Re(z)) sinh(Im(z)))

#### Example 3

Identifiers without properties are considered to be complex variables:

    >> delete z: rectform(ln(z))

                             2        2
                     ln(Im(z)  + Re(z) )
                     ------------------- + I arg(Re(z), Im(z))
                              2

However, you can affect the behavior of `rectform` by attaching properties to the identifiers. For example, if z assumes only real negative values, the real and the imaginary part simplify considerably:

    >> assume(z < 0): rectform(ln(z))

                                   ln(-z) + I PI

#### Example 4

We compute the rectangular form of the complex variable x:

    >> delete x: a := rectform(x)

                                  Re(x) + I Im(x)

Then we do the same for the real variable y:

    >> delete y: assume(y, Type::Real): b := rectform(y)

                                         y

    >> domtype(a), domtype(b)

                                rectform, rectform

We have stored the results, i.e., the elements of domain type `rectform`, in the two identifiers `a` and `b`. We compute the sum of `a` and `b`, which is again of domain type `rectform`, i.e., it is already splitted into its real and imaginary part:

    >> c := a + b

                               (y + Re(x)) + I Im(x)

    >> domtype(c)

                                     rectform

The result of an arithmetical operation between an element of domain type `rectform` and an arbitrary arithmetical expression is of domain type `rectform` as well:

    >> delete z: d := a + 2*b + exp(z)

          (2 y + Re(x) + cos(Im(z)) exp(Re(z))) +

             I (Im(x) + sin(Im(z)) exp(Re(z)))

    >> domtype(d)

                                     rectform

Use the function `expr` to convert an element of domain type `rectform` into an element of a basic domain:

    >> expr(d)

          2 y + I Im(x) + Re(x) + cos(Im(z)) exp(Re(z)) +

             I sin(Im(z)) exp(Re(z))

    >> domtype(%)

                                     DOM_EXPR

#### Example 5

`rectform` also works for polynomials and series expansions, namely individually on each coefficient:

    >> delete x, y: p := poly(ln(-4) + y*x, [x]):
       rectform(p)

                  poly((Re(y) + I Im(y)) x + (ln(4) + I PI), [x])

Similarly, `rectform` works for lists, sets, or arrays, where it is applied to each individual entry:

    >> a := array(1..2, [x, y]):
       rectform(a)

                       +-                                -+
                       | Re(x) + I Im(x), Re(y) + I Im(y) |
                       +-                                -+

Note that `rectform` does not work directly for other basic data types. For example, if the input expression is a table of arithmetical expressions, then `rectform` responds with an error message:

    >> a := table("1st" = x, "2nd" = y):
       rectform(a)

          Error: invalid argument, expecting an arithmetical expression \
          [rectform::new]

Use `map` to apply `rectform` to the operands of such an object:

    >> map(a, rectform)

                            table(
                              "2nd" = Re(y) + I Im(y),
                              "1st" = Re(x) + I Im(x)
                            )

#### Example 6

This example illustrates the meaning of the three operands of an object returned by `rectform`.

We start with the expression x+sin(y), for which `rectform` is able to compute a complete decomposition into real and imaginary part:

    >> delete x, y: r := rectform(x + sin(y))

          (Re(x) + sin(Re(y)) cosh(Im(y))) +

             I (Im(x) + cos(Re(y)) sinh(Im(y)))

The first two operands of `r` are the real and imaginary part of the expression, and the third operand is 0:

    >> op(r)

          Re(x) + sin(Re(y)) cosh(Im(y)),

             Im(x) + cos(Re(y)) sinh(Im(y)), 0

Next we consider the expression x+f(y), where f(y) represents an unknown function in a complex variable. `rectform` can split x into its real and imaginary part, but fails to do this for the subexpression f(y):

    >> delete f: r := rectform(x + f(y))

                              Re(x) + I Im(x) + f(y)

The first two operands of the returned object are the real and the imaginary part of x, and the third operand is the remainder f(y), for which `rectform` was not able to extract any information about its real and imaginary part:

    >> op(r)

                                Re(x), Im(x), f(y)

    >> Re(r), Im(r)

                        Re(x) + Re(f(y)), Im(x) + Im(f(y))

Sometimes `rectform` is not able to extract any information about the real and imaginary part of the input expression. Then the third operand contains the whole input expression, possibly in a rewritten form, due to the recursive mode of operation of `rectform`. The first two operands are 0. Here is an example:

    >> r := rectform(sin(x + f(y)))

                            sin(f(y) + I Im(x) + Re(x))

    >> op(r)

                         0, 0, sin(f(y) + I Im(x) + Re(x))

    >> Re(r), Im(r)

          Re(sin(f(y) + I Im(x) + Re(x))),

             Im(sin(f(y) + I Im(x) + Re(x)))

#### Example 7

Advanced users can extend `rectform` to their own special mathematical functions (see section ``Backgrounds'' below). To this end, embed your mathematical function into a function environment `f` and implement the behavior of `rectform` for this function as the `"rectform"` slot of the function environment.

If a subexpression of the form `f(u,..)` occurs in `z`, then `rectform` issues the call `f::rectform(u,..)` to the slot routine to determine the rectangular form of `f(u,..)`.

For illustration, we show how this works for the sine function. Of course, the function environment `sin` already has a `"rectform"` slot. We call our function environment `Sin` in order not to overwrite the existing system function `sin`:

    >> Sin := funcenv(Sin):
       Sin::rectform := proc(u) // compute rectform(Sin(u))
         local r, a, b;
       begin
         // recursively compute rectform of u
         r := rectform(u);

         if op(r, 3) <> 0 then
           // we cannot split Sin(u)
           new(rectform, 0, 0, Sin(u))
         else
           a := op(r, 1); // real part of u
           b := op(r, 2); // imaginary part of u
           new(rectform, Sin(a)*cosh(b), cos(a)*sinh(b), 0)
         end_if
       end:

    >> delete z: rectform(Sin(z))

                Sin(Re(z)) cosh(Im(z)) + (cos(Re(z)) sinh(Im(z))) I

If the `if` condition is true, then `rectform` is unable to split `u` completely into its real and imaginary part. In this case, `Sin::rectform` is unable to split `Sin(u)` into its real and imaginary part and indicates this by storing the whole expression `Sin(u)` in the third operand of the resulting `rectform` object:

    >> delete f: rectform(Sin(f(z)))

                                     Sin(f(z))

    >> op(%)

                                  0, 0, Sin(f(z))

#### Background

- If a subexpression of the form `f(u,..)` occurs in `z` and `f` is a function environment, then `rectform` attempts to call the slot `"rectform"` of `f` to determine the rectangular form of `f(u,..)`. In this way, you can extend the functionality of `rectform` to your own special mathematical functions.

  The slot `"rectform"` is called with the arguments `u,..` of `f`. If the slot routine `f::rectform` is not able to determine the rectangular form of `f(u,..)`, then it should return `new(rectform(0,0,f(u,..)))`. See example 7. If `f` does not have a slot `"rectform"`, then `rectform` returns the object `new(rectform(0,0,f(u,..)))` for the corresponding subexpression.

- Similarly, if an element `d` of a library domain `T` occurs as a subexpression of `z`, then `rectform` attempts to call the slot `"rectform"` of that domain with `d` as argument to compute the rectangular form of `d`.

  If the slot routine `T::rectform` is not able to determine the rectangular form of `d`, then it should return `new(rectform(0,0,d))`.

  If the domain `T` does not have a slot `"rectform"`, then `rectform` returns the object `new(rectform(0,0,d))` for the corresponding subexpression.

#### Changes

- `rectform` reacts to of properties of identifiers set via `assume`. Hence, the second argument of `rectform` (a set of real variables) became obsolete.

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