## `numeric::realroot` -- numerical search for a real root of a real univariate function

#### Introduction

`numeric::realroot``(f(x), x=a..b, ..)` computes a numerical real root of f(x) in the interval [a,b].

#### Call(s)

`numeric::realroot(f(x), x = a..b <, SearchLevel = s>)`

#### Parameters

`f(x)` | - | an arithmetical expression in one unknown `x`. Alternatively, an equation `f1(x)=f2(x)` equivalent to the expression `f1(x)-f2(x)`.
`x` | - | an identifier or an indexed identifier
`a, b` | - | finite real numerical values

#### Options

`SearchLevel =` s | - | `s` is a small non-zero integer. It controls the internal refinement of the search.

#### Returns

a single numerical real root of domain type `DOM_FLOAT`. If no solution is found, then `FAIL` is returned.

#### Side Effects

The function is sensitive to the environment variable `DIGITS`, which determines the numerical working precision.

#### Related Functions

`numeric::fsolve`, `numeric::polyroots`, `numeric::realroots`, `polylib::realroots`, `solve`

#### Details

- The expression `f(x)` must not contain symbolic objects other than the indeterminate `x` that cannot be converted to numerical values via `float`. Symbolic objects such as `PI` or `sqrt(2)` etc. are accepted. The same holds true for the boundaries `a,b` of the search interval.
- The function must produce real values. If `float(f(x))` does not yield real floating point numbers for all real floating point numbers `x` from the interval `[a,b]`, then internal problems may occur. Cf. example 5.
- `numeric::realroot` never tries to evaluate `f(x)` outside the search interval. Consequently, singularities outside the interval do not cause any problems. In many cases also singularities inside the interval do not affect the numerical search. However, `numeric::realroot` is not guaranteed to work in such a case. An error may occur, if the internal search accidentally hits a singularity. Cf. example 5.
- Up to round-off effects numerical roots r with |r|>= 10^(-DIGITS) are computed to a relative precision of `DIGITS` significant decimal places. Roots of smaller absolute size are computed to an absolute precision of 10^(-2*DIGITS). These precision goals are not achieved, if significant round-off occurs in the numerical evaluation of f(x).
- If `f` takes opposite signs at the endpoints `a,b` of the search interval and does not have zero-crossing singularities, then `numeric::realroot` is bound to find a root in the interval `[a,b]`.
- User defined functions can be handled. Cf. example 2.

- `numeric::realroot` approximates a point where `f(x)` changes its sign. This is a root only if the function `f` is continuous. Cf. example 3.

- `setuserinfo(numeric::realroot,1)` provides information on the internal search.
- Note that `numeric::realroots` may be used to isolate all real roots. However, this function is much slower than `numeric::realroot`, if `f` is not a polynomial.
- For univariate polynomials we recommend to use `polylib::realroots` rather than `numeric::realroot`.

#### Option: SearchLevel= `s`

- The nonnegative integer s controls the internal refinement of the search. The default value is s=1. Increasing s increases the chance of finding roots that are difficult to detect numerically. Cf. example 6.
- Note that increasing s by 1 may quadruple the time before `FAIL` is returned, if no real root is found. For this reason we recommend to restrict s to small values (s<=5, say).

#### Example 1

The following functions assume different signs at the boundaries, so the searches are bound to succeed:

    >> numeric::realroot(x^3 - exp(3), x = -PI..10)

                                    2.718281829

    >> numeric::realroot(exp(-x[1]) = x[1], x[1] = 0..1)

                                   0.5671432904

#### Example 2

The following function cannot be evaluated for non-numerical `x`. So one has to delay evaluation via `hold`:

    >> f := proc(x) begin
             if x<0 then 1 - x else exp(x) - 10*x end_if
            end_proc:

    >> numeric::realroot(hold(f)(x), x = -10..10)

                                   0.1118325592

    >> delete f:

#### Example 3

`numeric::realroot` approximates a point, where f(x) changes its sign. For the following function this happens at the discontinuity x=1:

    >> f := proc(x) begin if x<1 then -1 else x end_if end_proc:

    >> numeric::realroot(hold(f)(x), x = 0..3)

                                        1.0

    >> delete f:

#### Example 4

The following function does not have a real root. Consequently, `numeric::realroot` fails:

    >> numeric::realroot(x^2 + 1, x = -2..2)

                                       FAIL

The following function does not have a real root in the search interval:

    >> numeric::realroot(x^2 - 1, x =  2..3)

                                       FAIL

#### Example 5

The following function is complex valued for x^2 <3.5. An error occurs, when the internal search hits such a point:

    >> numeric::realroot(ln(x^2 - 3.5), x = -2..3)

          Error: Complex arguments are not allowed in comparisons;
          during evaluation of 'numeric::BrentFindRoot'

The singularity at x=2 does not cause any problem in the following call:

    >> numeric::realroot((x-1)/(x-2), x = -10..PI)

                                        1.0

However, the singularity may be hit accidentally in the internal search:

    >> numeric::realroot((x-1)/(x-2), x = -10..14)

          Error: Division by zero [_power];
          during evaluation of 'f'

#### Example 6

The following function has a root close to 1.0, which is difficult to detect. With the default search level s=1 this root is not found:

    >> f := 2 - exp(-100*(x - 2)^2) - 2*exp(-1000*(x - 1)^2):

    >> numeric::realroot(f, x = 0..5)

                                       FAIL

The root is detected with an increased search level:

    >> numeric::realroot(f, x = 0..5, SearchLevel = 3)

                                        1.0

    >> delete f:

#### Background

- A mixture of bisectioning, secant steps and quadratic interpolation is used by `numeric::realroot`.

#### Changes

- new function

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