This routine computes all zeros of a polynomial of degree NDEG with complex coefficients by computing the eigenvalues of the companion matrix.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | ndeg |
degree of polynomial |
||
complex(kind=wp), | intent(in), | dimension(ndeg+1) | :: | coeff |
|
|
complex(kind=wp), | intent(out), | dimension(ndeg) | :: | root |
|
|
integer, | intent(out) | :: | ierr |
Output Error Code. Normal Code:
Abnormal Codes:
|
subroutine cpqr79(ndeg, coeff, root, ierr) implicit none integer, intent(in) :: ndeg !! degree of polynomial complex(wp), dimension(ndeg+1), intent(in) :: coeff !! `(NDEG+1)` coefficients in descending order. i.e., !! `P(Z)= COEFF(1)*(Z**NDEG) + COEFF(NDEG)*Z + COEFF(NDEG+1)` complex(wp), dimension(ndeg), intent(out) :: root !! `(NDEG)` vector of roots integer, intent(out) :: ierr !! Output Error Code. !! !!### Normal Code: !! !! * 0 -- means the roots were computed. !! !!### Abnormal Codes: !! !! * 1 -- more than 30 QR iterations on some eigenvalue of the companion matrix !! * 2 -- COEFF(1)=0.0 !! * 3 -- NDEG is invalid (less than or equal to 0) complex(wp) :: scale, c integer :: k, khr, khi, kwr, kwi, kad, kj, km1 real(wp), dimension(:), allocatable :: work !! work array of dimension `2*NDEG*(NDEG+1)` ierr = 0 if (abs(coeff(1)) == 0.0_wp) then ierr = 2 write (*, *) 'leading coefficient is zero.' return end if if (ndeg <= 0) then ierr = 3 write (*, *) 'degree invalid.' return end if if (ndeg == 1) then root(1) = -coeff(2)/coeff(1) return end if ! allocate work array: allocate (work(2*NDEG*(NDEG + 1))) scale = 1.0_wp/coeff(1) khr = 1 khi = khr + ndeg*ndeg kwr = khi + khi - khr kwi = kwr + ndeg do k = 1, kwr work(k) = 0.0_wp end do do k = 1, ndeg kad = (k - 1)*ndeg + 1 c = scale*coeff(k + 1) work(kad) = -real(c, wp) kj = khi + kad - 1 work(kj) = -aimag(c) if (k /= ndeg) work(kad + k) = 1.0_wp end do call comqr(ndeg, ndeg, 1, ndeg, work(khr), work(khi), work(kwr), work(kwi), ierr) if (ierr /= 0) then write (*, *) 'no convergence in 30 qr iterations. ierr = ', ierr ierr = 1 return end if do k = 1, ndeg km1 = k - 1 root(k) = cmplx(work(kwr + km1), work(kwi + km1), wp) end do end subroutine cpqr79