polyroots_module Module

Polynomial Roots with Modern Fortran

Author

  • Jacob Williams

Note

The default real kind (wp) can be changed using optional preprocessor flags. This library was built with real kind: real(kind=real64) [8 bytes]


Uses

  • module~~polyroots_module~~UsesGraph module~polyroots_module polyroots_module ieee_arithmetic ieee_arithmetic module~polyroots_module->ieee_arithmetic iso_fortran_env iso_fortran_env module~polyroots_module->iso_fortran_env

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: polyroots_module_rk = real64

real kind used by this module [8 bytes]

integer, private, parameter :: wp = polyroots_module_rk

local copy of polyroots_module_rk with a shorter name

real(kind=wp), private, parameter :: eps = epsilon(1.0_wp)

machine epsilon

real(kind=wp), private, parameter :: pi = acos(-1.0_wp)
real(kind=wp), private, parameter :: deg2rad = pi/180.0_wp

Interfaces

public interface newton_root_polish

"Polish" a root using Newton Raphson. This routine will perform a Newton iteration and update the roots only if they improve, otherwise, they are left as is.

  • private subroutine newton_root_polish_real(n, p, zr, zi, ftol, ztol, maxiter, istat)

    "Polish" a root using a complex Newton Raphson method. This routine will perform a Newton iteration and update the roots only if they improve, otherwise, they are left as is.

    History

    • Jacob Williams, 9/15/2023, created this routine.

    Arguments

    Type IntentOptional Attributes Name
    integer, intent(in) :: n

    degree of polynomial

    real(kind=wp), intent(in), dimension(n+1) :: p

    vector of coefficients in order of decreasing powers

    real(kind=wp), intent(inout) :: zr

    real part of the zero

    real(kind=wp), intent(inout) :: zi

    imaginary part of the zero

    real(kind=wp), intent(in) :: ftol

    convergence tolerance for the root

    real(kind=wp), intent(in) :: ztol

    convergence tolerance for x

    integer, intent(in) :: maxiter

    maximum number of iterations

    integer, intent(out) :: istat

    status flag:

    Read more…
  • private subroutine newton_root_polish_complex(n, p, zr, zi, ftol, ztol, maxiter, istat)

    "Polish" a root using a complex Newton Raphson method. This routine will perform a Newton iteration and update the roots only if they improve, otherwise, they are left as is.

    Note

    Same as newton_root_polish_real except that p is complex(wp)

    Arguments

    Type IntentOptional Attributes Name
    integer, intent(in) :: n

    degree of polynomial

    complex(kind=wp), intent(in), dimension(n+1) :: p

    vector of coefficients in order of decreasing powers

    real(kind=wp), intent(inout) :: zr

    real part of the zero

    real(kind=wp), intent(inout) :: zi

    imaginary part of the zero

    real(kind=wp), intent(in) :: ftol

    convergence tolerance for the root

    real(kind=wp), intent(in) :: ztol

    convergence tolerance for x

    integer, intent(in) :: maxiter

    maximum number of iterations

    integer, intent(out) :: istat

    status flag:

    Read more…

Functions

private pure function dcbrt(x)

Cube root of a real number.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: x

Return Value real(kind=wp)

private function dcpabs(x, y)

evaluation of sqrt(x*x + y*y)

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: x
real(kind=wp), intent(in) :: y

Return Value real(kind=wp)

private pure function pythag(a, b)

Compute the complex square root of a complex number without destructive overflow or underflow.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: a
real(kind=wp), intent(in) :: b

Return Value real(kind=wp)

private function ctest(n, a, il, i, ir)

test the convexity of the angle formed by (il,a(il)), (i,a(i)), (ir,a(ir)) at the vertex (i,a(i)), up to within the tolerance toler. if convexity holds then the function is set to .true., otherwise ctest=.false. the parameter toler is set to 0.4 by default.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

length of the vector a

real(kind=wp), intent(in) :: a(n)

vector of double

integer, intent(in) :: il

integers such that il<i<ir

integer, intent(in) :: i

integers such that il<i<ir

integer, intent(in) :: ir

integers such that il<i<ir

Return Value logical

  • .true. if the angle formed by (il,a(il)), (i,a(i)), (ir,a(ir)) at the vertex (i,a(i)), is convex up to within the tolerance toler, i.e., if (a(i)-a(il))(ir-i)-(a(ir)-a(i))(i-il)>toler.
  • .false., otherwise.

Subroutines

public subroutine rpoly(op, degree, zeror, zeroi, istat)

Finds the zeros of a general real polynomial using the Jenkins & Traub algorithm.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in), dimension(degree+1) :: op

vector of coefficients in order of decreasing powers

integer, intent(in) :: degree

degree of polynomial

real(kind=wp), intent(out), dimension(degree) :: zeror

output vector of real parts of the zeros

real(kind=wp), intent(out), dimension(degree) :: zeroi

output vector of imaginary parts of the zeros

integer, intent(out) :: istat

status output:

Read more…

public subroutine dcbcrt(a, zr, zi)

Computes the roots of a cubic polynomial of the form a(1) + a(2)*z + a(3)*z**2 + a(4)*z**3 = 0

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in), dimension(4) :: a

coefficients

real(kind=wp), intent(out), dimension(3) :: zr

real components of roots

real(kind=wp), intent(out), dimension(3) :: zi

imaginary components of roots

public pure subroutine dqdcrt(a, zr, zi)

Computes the roots of a quadratic polynomial of the form a(1) + a(2)*z + a(3)*z**2 = 0

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in), dimension(3) :: a

coefficients

real(kind=wp), intent(out), dimension(2) :: zr

real components of roots

real(kind=wp), intent(out), dimension(2) :: zi

imaginary components of roots

public subroutine quadpl(a, b, c, sr, si, lr, li)

Calculate the zeros of the quadratic a*z**2 + b*z + c.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: a

coefficients

real(kind=wp), intent(in) :: b

coefficients

real(kind=wp), intent(in) :: c

coefficients

real(kind=wp), intent(out) :: sr

real part of first root

real(kind=wp), intent(out) :: si

imaginary part of first root

real(kind=wp), intent(out) :: lr

real part of second root

real(kind=wp), intent(out) :: li

imaginary part of second root

public subroutine dqtcrt(a, zr, zi)

dqtcrt computes the roots of the real polynomial

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp) :: a(5)
real(kind=wp) :: zr(4)
real(kind=wp) :: zi(4)

private subroutine daord(a, n)

Used to reorder the elements of the double precision array a so that abs(a(i)) <= abs(a(i+1)) for i = 1,...,n-1. it is assumed that n >= 1.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: a(n)
integer, intent(in) :: n

private subroutine dcsqrt(z, w)

w = sqrt(z) for the double precision complex number z

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: z(2)
real(kind=wp), intent(out) :: w(2)

public subroutine qr_algeq_solver(n, c, zr, zi, istatus, detil)

Solve the real coefficient algebraic equation by the qr-method.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

degree of the monic polynomial.

real(kind=wp), intent(in) :: c(n+1)

coefficients of the polynomial. in order of decreasing powers.

real(kind=wp), intent(out) :: zr(n)

real part of output roots

real(kind=wp), intent(out) :: zi(n)

imaginary part of output roots

integer, intent(out) :: istatus

return code:

Read more…
real(kind=wp), intent(out), optional :: detil

accuracy hint.

private subroutine cpevl(n, m, a, z, c, b, kbd)

Evaluate a complex polynomial and its derivatives. Optionally compute error bounds for these values.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

Degree of the polynomial

integer, intent(in) :: m

Number of derivatives to be calculated:

Read more…
complex(kind=wp), intent(in) :: a(*)

vector containing the N+1 coefficients of polynomial. A(I) = coefficient of Z**(N+1-I)

complex(kind=wp), intent(in) :: z

point at which the evaluation is to take place

complex(kind=wp), intent(out) :: c(*)

Array of 2(M+1) words: C(I+1) contains the complex value of the I-th derivative at Z, I=0,...,M

complex(kind=wp), intent(out) :: b(*)

Array of 2(M+1) words: B(I) contains the bounds on the real and imaginary parts of C(I) if they were requested. only needed if bounds are to be calculated. It is not used otherwise.

logical, intent(in) :: kbd

A logical variable, e.g. .TRUE. or .FALSE. which is to be set .TRUE. if bounds are to be computed.

public subroutine cpzero(in, a, r, iflg, s)

Find the zeros of a polynomial with complex coefficients: P(Z)= A(1)*Z**N + A(2)*Z**(N-1) +...+ A(N+1)

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: in

N, the degree of P(Z)

complex(kind=wp), intent(in), dimension(in+1) :: a

complex vector containing coefficients of P(Z), A(I) = coefficient of Z**(N+1-i)

complex(kind=wp), intent(inout), dimension(in) :: r

N word complex vector. On input: containing initial estimates for zeros if these are known. On output: Ith zero

integer, intent(inout) :: iflg

flag to indicate if initial estimates of zeros are input:

Read more…
real(kind=wp), intent(out) :: s(in)

an N word array. S(I) = bound for R(I)

public subroutine rpzero(n, a, r, iflg, s)

Find the zeros of a polynomial with real coefficients: P(X)= A(1)*X**N + A(2)*X**(N-1) +...+ A(N+1)

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

degree of P(X)

real(kind=wp), intent(in), dimension(n+1) :: a

real vector containing coefficients of P(X), A(I) = coefficient of X**(N+1-I)

complex(kind=wp), intent(inout), dimension(n) :: r

N word complex vector. On Input: containing initial estimates for zeros if these are known. On output: ith zero.

integer, intent(inout) :: iflg

flag to indicate if initial estimates of zeros are input:

Read more…
real(kind=wp), intent(out), dimension(n) :: s

an N word array. bound for R(I).

public subroutine rpqr79(ndeg, coeff, root, ierr)

This routine computes all zeros of a polynomial of degree NDEG with real coefficients by computing the eigenvalues of the companion matrix.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: ndeg

degree of polynomial

real(kind=wp), intent(in), dimension(ndeg+1) :: coeff

NDEG+1 coefficients in descending order. i.e., P(Z) = COEFF(1)*(Z**NDEG) + COEFF(NDEG)*Z + COEFF(NDEG+1)

complex(kind=wp), intent(out), dimension(ndeg) :: root

NDEG vector of roots

integer, intent(out) :: ierr

Output Error Code

Read more…

private subroutine hqr(nm, n, low, igh, h, wr, wi, ierr)

This subroutine finds the eigenvalues of a real upper hessenberg matrix by the qr method.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nm

must be set to the row dimension of two-dimensional array parameters as declared in the calling program dimension statement.

integer, intent(in) :: n

order of the matrix

integer, intent(in) :: low

low and igh are integers determined by the balancing subroutine balanc. if balanc has not been used, set low=1, igh=n.

integer, intent(in) :: igh

low and igh are integers determined by the balancing subroutine balanc. if balanc has not been used, set low=1, igh=n.

real(kind=wp), intent(inout) :: h(nm,n)

On input: contains the upper hessenberg matrix. information about the transformations used in the reduction to hessenberg form by elmhes or orthes, if performed, is stored in the remaining triangle under the hessenberg matrix.

Read more…
real(kind=wp), intent(out) :: wr(n)

the real parts of the eigenvalues. the eigenvalues are unordered except that complex conjugate pairs of values appear consecutively with the eigenvalue having the positive imaginary part first. if an error exit is made, the eigenvalues should be correct for indices ierr+1,...,n.

real(kind=wp), intent(out) :: wi(n)

the imaginary parts of the eigenvalues. the eigenvalues are unordered except that complex conjugate pairs of values appear consecutively with the eigenvalue having the positive imaginary part first. if an error exit is made, the eigenvalues should be correct for indices ierr+1,...,n.

integer, intent(out) :: ierr

is set to:

Read more…

public subroutine polyroots(n, p, wr, wi, info)

Solve for the roots of a real polynomial equation by computing the eigenvalues of the companion matrix.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

polynomial degree

real(kind=wp), intent(in), dimension(n+1) :: p

polynomial coefficients array, in order of decreasing powers

real(kind=wp), intent(out), dimension(n) :: wr

real parts of roots

real(kind=wp), intent(out), dimension(n) :: wi

imaginary parts of roots

integer, intent(out) :: info

output from the lapack solver.

Read more…

public subroutine cpolyroots(n, p, w, info)

Solve for the roots of a complex polynomial equation by computing the eigenvalues of the companion matrix.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

polynomial degree

complex(kind=wp), intent(in), dimension(n+1) :: p

polynomial coefficients array, in order of decreasing powers

complex(kind=wp), intent(out), dimension(n) :: w

roots

integer, intent(out) :: info

output from the lapack solver.

Read more…

public subroutine cpqr79(ndeg, coeff, root, ierr)

This routine computes all zeros of a polynomial of degree NDEG with complex coefficients by computing the eigenvalues of the companion matrix.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: ndeg

degree of polynomial

complex(kind=wp), intent(in), dimension(ndeg+1) :: coeff

(NDEG+1) coefficients in descending order. i.e., P(Z)= COEFF(1)*(Z**NDEG) + COEFF(NDEG)*Z + COEFF(NDEG+1)

complex(kind=wp), intent(out), dimension(ndeg) :: root

(NDEG) vector of roots

integer, intent(out) :: ierr

Output Error Code.

Read more…

private subroutine comqr(nm, n, low, igh, hr, hi, wr, wi, ierr)

this subroutine finds the eigenvalues of a complex upper hessenberg matrix by the qr method.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nm

row dimension of two-dimensional array parameters

integer, intent(in) :: n

the order of the matrix

integer, intent(in) :: low

integer determined by the balancing subroutine cbal. if cbal has not been used, set low=1

integer, intent(in) :: igh

integer determined by the balancing subroutine cbal. if cbal has not been used, igh=n.

real(kind=wp), intent(inout) :: hr(nm,n)

On input: hr and hi contain the real and imaginary parts, respectively, of the complex upper hessenberg matrix. their lower triangles below the subdiagonal contain information about the unitary transformations used in the reduction by corth, if performed.

Read more…
real(kind=wp), intent(inout) :: hi(nm,n)

See hr description

real(kind=wp), intent(out) :: wr(n)

the real parts of the eigenvalues. if an error exit is made, the eigenvalues should be correct for indices ierr+1,...,n.

real(kind=wp), intent(out) :: wi(n)

the imaginary parts of the eigenvalues. if an error exit is made, the eigenvalues should be correct for indices ierr+1,...,n.

integer, intent(out) :: ierr

is set to:

Read more…

private pure subroutine csroot(xr, xi, yr, yi)

Compute the complex square root of a complex number.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: xr
real(kind=wp), intent(in) :: xi
real(kind=wp), intent(out) :: yr
real(kind=wp), intent(out) :: yi

private pure subroutine cdiv(ar, ai, br, bi, cr, ci)

Compute the complex quotient of two complex numbers.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: ar
real(kind=wp), intent(in) :: ai
real(kind=wp), intent(in) :: br
real(kind=wp), intent(in) :: bi
real(kind=wp), intent(out) :: cr
real(kind=wp), intent(out) :: ci

private subroutine newton_root_polish_real(n, p, zr, zi, ftol, ztol, maxiter, istat)

"Polish" a root using a complex Newton Raphson method. This routine will perform a Newton iteration and update the roots only if they improve, otherwise, they are left as is.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

degree of polynomial

real(kind=wp), intent(in), dimension(n+1) :: p

vector of coefficients in order of decreasing powers

real(kind=wp), intent(inout) :: zr

real part of the zero

real(kind=wp), intent(inout) :: zi

imaginary part of the zero

real(kind=wp), intent(in) :: ftol

convergence tolerance for the root

real(kind=wp), intent(in) :: ztol

convergence tolerance for x

integer, intent(in) :: maxiter

maximum number of iterations

integer, intent(out) :: istat

status flag:

Read more…

private subroutine newton_root_polish_complex(n, p, zr, zi, ftol, ztol, maxiter, istat)

"Polish" a root using a complex Newton Raphson method. This routine will perform a Newton iteration and update the roots only if they improve, otherwise, they are left as is.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

degree of polynomial

complex(kind=wp), intent(in), dimension(n+1) :: p

vector of coefficients in order of decreasing powers

real(kind=wp), intent(inout) :: zr

real part of the zero

real(kind=wp), intent(inout) :: zi

imaginary part of the zero

real(kind=wp), intent(in) :: ftol

convergence tolerance for the root

real(kind=wp), intent(in) :: ztol

convergence tolerance for x

integer, intent(in) :: maxiter

maximum number of iterations

integer, intent(out) :: istat

status flag:

Read more…

public subroutine cmplx_roots_gen(degree, poly, roots, polish_roots_after, use_roots_as_starting_points)

This subroutine finds roots of a complex polynomial. It uses a new dynamic root finding algorithm (see the Paper).

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: degree

degree of the polynomial and size of 'roots' array

complex(kind=wp), intent(in), dimension(degree+1) :: poly

coeffs of the polynomial, in order of increasing powers.

complex(kind=wp), intent(inout), dimension(degree) :: roots

array which will hold all roots that had been found. If the flag 'use_roots_as_starting_points' is set to .true., then instead of point (0,0) we use value from this array as starting point for cmplx_laguerre

logical, intent(in), optional :: polish_roots_after

after all roots have been found by dividing original polynomial by each root found, you can opt in to polish all roots using full polynomial. [default is false]

logical, intent(in), optional :: use_roots_as_starting_points

usually we start Laguerre's method from point (0,0), but you can decide to use the values of 'roots' array as starting point for each new root that is searched for. This is useful if you have very rough idea where some of the roots can be. [default is false]

public subroutine cpoly(opr, opi, degree, zeror, zeroi, fail)

Finds the zeros of a complex polynomial.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in), dimension(degree+1) :: opr

vectors of real parts of the coefficients in order of decreasing powers.

real(kind=wp), intent(in), dimension(degree+1) :: opi

vectors of imaginary parts of the coefficients in order of decreasing powers.

integer, intent(in) :: degree

degree of polynomial

real(kind=wp), intent(out), dimension(degree) :: zeror

real parts of the zeros

real(kind=wp), intent(out), dimension(degree) :: zeroi

imaginary parts of the zeros

logical, intent(out) :: fail

true only if leading coefficient is zero or if cpoly has found fewer than degree zeros.

public subroutine polzeros(n, poly, nitmax, root, radius, err)

Numerical computation of the roots of a polynomial having complex coefficients, based on aberth's method.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

degree of the polynomial.

complex(kind=wp), intent(in) :: poly(n+1)

complex vector of n+1 components, poly(i) is the coefficient of x**(i-1), i=1,...,n+1 of the polynomial p(x)

integer, intent(in) :: nitmax

the max number of allowed iterations.

complex(kind=wp), intent(out) :: root(n)

complex vector of n components, containing the approximations to the roots of p(x).

real(kind=wp), intent(out) :: radius(n)

real vector of n components, containing the error bounds to the approximations of the roots, i.e. the disk of center root(i) and radius radius(i) contains a root of p(x), for i=1,...,n. radius(i) is set to -1 if the corresponding root cannot be represented as floating point due to overflow or underflow.

logical, intent(out) :: err(n)

vector of n components detecting an error condition:

Read more…

private subroutine newton(n, poly, apoly, apolyr, z, small, radius, corr, again)

compute the newton's correction, the inclusion radius (4) and checks the stop condition (3)

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

degree of the polynomial p(x)

complex(kind=wp), intent(in) :: poly(n+1)

coefficients of the polynomial p(x)

real(kind=wp), intent(in) :: apoly(n+1)

upper bounds on the backward perturbations on the coefficients of p(x) when applying ruffini-horner's rule

real(kind=wp), intent(in) :: apolyr(n+1)

upper bounds on the backward perturbations on the coefficients of p(x) when applying (2), (2')

complex(kind=wp), intent(in) :: z

value at which the newton correction is computed

real(kind=wp), intent(in) :: small

the min positive real(wp), small=2**(-1074) for the ieee.

real(kind=wp), intent(out) :: radius

upper bound to the distance of z from the closest root of the polynomial computed according to (4).

complex(kind=wp), intent(out) :: corr

newton's correction

logical, intent(out) :: again

this variable is .true. if the computed value p(z) is reliable, i.e., (3) is not satisfied in z. again is .false., otherwise.

private subroutine aberth(n, j, root, abcorr)

compute the aberth correction. to save time, the reciprocation of root(j)-root(i) could be performed in single precision (complex*8) in principle this might cause overflow if both root(j) and root(i) have too small moduli.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

degree of the polynomial

integer, intent(in) :: j

index of the component of root with respect to which the aberth correction is computed

complex(kind=wp), intent(in) :: root(n)

vector containing the current approximations to the roots

complex(kind=wp), intent(out) :: abcorr

aberth's correction (compare (1))

private subroutine start(n, a, y, radius, nz, small, big)

compute the starting approximations of the roots

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

number of the coefficients of the polynomial

real(kind=wp), intent(inout) :: a(n+1)

moduli of the coefficients of the polynomial

complex(kind=wp), intent(out) :: y(n)

starting approximations

real(kind=wp), intent(out) :: radius(n)

if a component is -1 then the corresponding root has a too big or too small modulus in order to be represented as double float with no overflow/underflow

integer, intent(out) :: nz

number of roots which cannot be represented without overflow/underflow

real(kind=wp), intent(in) :: small

the min positive real(wp), small=2**(-1074) for the ieee.

real(kind=wp), intent(in) :: big

the max real(wp), big=2**1023 for the ieee standard.

private subroutine cnvex(n, a, h)

compute the upper convex hull of the set (i,a(i)), i.e., the set of vertices (i_k,a(i_k)), k=1,2,...,m, such that the points (i,a(i)) lie below the straight lines passing through two consecutive vertices. the abscissae of the vertices of the convex hull equal the indices of the true components of the logical output vector h. the used method requires o(nlog n) comparisons and is based on a divide-and-conquer technique. once the upper convex hull of two contiguous sets (say, {(1,a(1)),(2,a(2)),...,(k,a(k))} and {(k,a(k)), (k+1,a(k+1)),...,(q,a(q))}) have been computed, then the upper convex hull of their union is provided by the subroutine cmerge. the program starts with sets made up by two consecutive points, which trivially constitute a convex hull, then obtains sets of 3,5,9... points, up to arrive at the entire set. the program uses the subroutine cmerge; the subroutine cmerge uses the subroutines left, right and ctest. the latter tests the convexity of the angle formed by the points (i,a(i)), (j,a(j)), (k,a(k)) in the vertex (j,a(j)) up to within a given tolerance toler, where i<j<k.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n
real(kind=wp) :: a(n)
logical, intent(out) :: h(n)

private subroutine left(n, h, i, il)

given as input the integer i and the vector h of logical, compute the the maximum integer il such that il<i and h(il) is true.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

length of the vector h

logical, intent(in) :: h(n)

vector of logical

integer, intent(in) :: i

integer

integer, intent(out) :: il

maximum integer such that il<i, h(il)=.true.

private subroutine right(n, h, i, ir)

given as input the integer i and the vector h of logical, compute the the minimum integer ir such that ir>i and h(il) is true.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

length of the vector h

logical, intent(in) :: h(n)

vector of logical

integer, intent(in) :: i

integer

integer, intent(out) :: ir

minimum integer such that ir>i, h(ir)=.true.

private subroutine cmerge(n, a, i, m, h)

given the upper convex hulls of two consecutive sets of pairs (j,a(j)), compute the upper convex hull of their union

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

length of the vector a

real(kind=wp), intent(in) :: a(n)

vector defining the points (j,a(j))

integer, intent(in) :: i

abscissa of the common vertex of the two sets

integer, intent(in) :: m

the number of elements of each set is m+1

logical, intent(out) :: h(n)

vector defining the vertices of the convex hull, i.e., h(j) is .true. if (j,a(j)) is a vertex of the convex hull this vector is used also as output.

public subroutine fpml(poly, deg, roots, berr, cond, conv, itmax)

FPML: Fourth order Parallelizable Modification of Laguerre's method

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=wp), intent(in) :: poly(deg+1)

coefficients

integer, intent(in) :: deg

polynomial degree

complex(kind=wp), intent(out) :: roots(:)

the root approximations

real(kind=wp), intent(out) :: berr(:)

the backward error in each approximation

real(kind=wp), intent(out) :: cond(:)

the condition number of each root approximation

integer, intent(out) :: conv(:)
integer, intent(in) :: itmax

public subroutine rroots_chebyshev_cubic(coeffs, zr, zi)

Compute the roots of a cubic equation with real coefficients.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in), dimension(4) :: coeffs

vector of coefficients in order of decreasing powers

real(kind=wp), intent(out), dimension(3) :: zr

output vector of real parts of the zeros

real(kind=wp), intent(out), dimension(3) :: zi

output vector of imaginary parts of the zeros

public pure subroutine sort_roots(x, y)

Sorts a set of complex numbers (with real and imag parts in different vectors) in increasing order.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout), dimension(:) :: x

the real parts to be sorted. on exit,x has been sorted into increasing order (x(1) <= ... <= x(n))

real(kind=wp), intent(inout), dimension(:) :: y

the imaginary parts to be sorted

public subroutine dpolz(ndeg, a, zr, zi, ierr)

Given coefficients A(1),...,A(NDEG+1) this subroutine computes the NDEG roots of the polynomial A(1)*X**NDEG + ... + A(NDEG+1) storing the roots as complex numbers in the array Z. Require NDEG >= 1 and A(1) /= 0.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: ndeg

Degree of the polynomial

real(kind=wp), intent(in) :: a(ndeg+1)

Contains the coefficients of a polynomial, high order coefficient first with A(1)/=0.

real(kind=wp), intent(out) :: zr(ndeg)

Contains the real parts of the roots

real(kind=wp), intent(out) :: zi(ndeg)

Contains the imaginary parts of the roots

integer, intent(out) :: ierr

Error flag:

Read more…

public subroutine cpolz(a, ndeg, z, ierr)

In the discussion below, the notation A([*,],k} should be interpreted as the complex number A(k) if A is declared complex, and should be interpreted as the complex number A(1,k) + i * A(2,k) if A is not declared to be of type complex. Similar statements apply for Z(k).

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=wp), intent(in) :: a(ndeg+1)

contains the complex coefficients of a polynomial high order coefficient first, with a([,]1)/=0. the real and imaginary parts of the jth coefficient must be provided in a([],j). the contents of this array will not be modified by the subroutine.

integer, intent(in) :: ndeg

degree of the polynomial

complex(kind=wp), intent(out) :: z(ndeg)

contains the polynomial roots stored as complex numbers. the real and imaginary parts of the jth root will be stored in z([*,]j).

integer, intent(out) :: ierr

error flag. set by the subroutine to 0 on normal termination. set to -1 if a([*,]1)=0. set to -2 if ndeg <= 0. set to j > 0 if the iteration count limit has been exceeded and roots 1 through j have not been determined.

private subroutine scomqr(nm, n, low, igh, hr, hi, z, ierr)

This subroutine finds the eigenvalues of a complex upper hessenberg matrix by the qr method.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nm

the row dimension of two-dimensional array parameters as declared in the calling program dimension statement

integer, intent(in) :: n

the order of the matrix

integer, intent(in) :: low

low and igh are integers determined by the balancing subroutine cbal. if cbal has not been used, set low=1, igh=n

integer, intent(in) :: igh

low and igh are integers determined by the balancing subroutine cbal. if cbal has not been used, set low=1, igh=n

real(kind=wp), intent(inout) :: hr(nm,n)

see hi description

real(kind=wp), intent(inout) :: hi(nm,n)

Input: hr and hi contain the real and imaginary parts, respectively, of the complex upper hessenberg matrix. their lower triangles below the subdiagonal contain information about the unitary transformations used in the reduction by corth, if performed.

Read more…
complex(kind=wp), intent(out) :: z(n)

the real and imaginary parts, respectively, of the eigenvalues. if an error exit is made, the eigenvalues should be correct for indices ierr+1,...,n,

integer, intent(out) :: ierr

is set to:

Read more…