https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_polynomial@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 908 1028 88.3 %
Date: 2024-04-08 03:18:57 Functions: 42 56 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       2             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       3             : !!!!                                                                                                                            !!!!
       4             : !!!!    ParaMonte: Parallel Monte Carlo and Machine Learning Library.                                                           !!!!
       5             : !!!!                                                                                                                            !!!!
       6             : !!!!    Copyright (C) 2012-present, The Computational Data Science Lab                                                          !!!!
       7             : !!!!                                                                                                                            !!!!
       8             : !!!!    This file is part of the ParaMonte library.                                                                             !!!!
       9             : !!!!                                                                                                                            !!!!
      10             : !!!!    LICENSE                                                                                                                 !!!!
      11             : !!!!                                                                                                                            !!!!
      12             : !!!!       https://github.com/cdslaborg/paramonte/blob/main/LICENSE.md                                                          !!!!
      13             : !!!!                                                                                                                            !!!!
      14             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      15             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      16             : 
      17             : !>  \brief
      18             : !>  This include file contains procedure implementations of [pm_polynomial](@ref pm_polynomial).
      19             : !>
      20             : !>  \finmain
      21             : !>
      22             : !>  \author
      23             : !>  \AmirShahmoradi, Sunday 3:33 PM, September 19, 2021, Dallas, TX
      24             : 
      25             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      26             : 
      27             :         ! Define zero.
      28             : #if     CK_ENABLED || CK_CK_ENABLED
      29             : #define TYPE_KIND complex(TKC)
      30             :         complex(TKC), parameter :: ZERO = (0._TKC, 0._TKC), ONE = (1._TKC, 0._TKC)
      31             : #elif   RK_ENABLED || RK_RK_ENABLED || RK_CK_ENABLED
      32             : #define TYPE_KIND real(TKC)
      33             :         real(TKC), parameter :: ZERO = 0._TKC, ONE = 1._TKC
      34             : #else
      35             : #error  "Unrecognized interface."
      36             : #endif
      37             : #if     setPolyRoot_ENABLED && Jen_ENABLED
      38             : !       Bypass the non-existence of `SIND` and `COSD` for compilers (other than Intel/GNU): !(INTEL_ENABLED || GNU_ENABLED)
      39             : #if     1
      40             : #define COSD(x) cos(x * acos(real(-1, kind(x))) / real(180, kind(x)))
      41             : #define SIND(x) sin(x * acos(real(-1, kind(x))) / real(180, kind(x)))
      42             : #endif
      43             : !       Enable robust calculations.
      44             : !       \todo `hypot` argument still needs work.
      45             : #if     0
      46             :         use pm_complexDiv, only: getDiv
      47             : #define GET_RATIO(x, y) getDiv(x, y)
      48             : #define GET_ABS(x) hypot(x%re, x%im)
      49             : #else
      50             : #define GET_RATIO(x, y) x / y
      51             : #define GET_ABS(x) abs(x)
      52             : #endif
      53             : #endif
      54             : 
      55             :         !%%%%%%%%%%%%%%%%%
      56             : #if     getPolyVal_ENABLED
      57             :         !%%%%%%%%%%%%%%%%%
      58             : 
      59             :         integer(IK) :: i, degree
      60          77 :         degree = size(coef, 1, IK) - 1_IK
      61          77 :         CHECK_ASSERTION(__LINE__, 0_IK <= degree, SK_"@setPolyRoot(): The condition `0_IK < size(coef)` must hold. size(coef) = "//getStr(degree + 1_IK))
      62         646 :         poly = coef(degree)
      63         664 :         do i = degree - 1_IK, 0_IK, -1_IK
      64        5875 :             poly = poly * x + coef(i)
      65             :         end do
      66             : 
      67             :         !%%%%%%%%%%%%%%%%%
      68             : #elif   getPolyAdd_ENABLED
      69             :         !%%%%%%%%%%%%%%%%%
      70             : 
      71             :         integer(IK) :: lenLhs, lenRhs, lenMax
      72             :         lenLhs = size(lhs, 1, IK)
      73             :         lenRhs = size(rhs, 1, IK)
      74           2 :         do
      75          24 :             if (lenLhs == 0_IK) exit
      76          18 :             if (lhs(lenLhs) /= ZERO) exit
      77          18 :             lenLhs = lenLhs - 1_IK
      78             :         end do
      79           0 :         do
      80          22 :             if (lenRhs == 0_IK) exit
      81          18 :             if (rhs(lenRhs) /= ZERO) exit
      82          18 :             lenRhs = lenRhs - 1_IK
      83             :         end do
      84          22 :         if (0_IK < lenLhs .and. 0_IK < lenRhs) then
      85          14 :             lenMax = max(lenLhs, lenRhs)
      86          14 :             call setPolyAdd(add(1 : lenMax), lhs(1 : lenLhs), rhs(1 : lenRhs))
      87          14 :             add(lenMax + 1 :) = ZERO
      88           8 :         elseif (0_IK < lenLhs) then
      89           6 :             add(1 : lenLhs) = lhs(1 : lenLhs)
      90           2 :             add(lenLhs + 1:) = ZERO
      91             :         else
      92          16 :             add(1 : lenRhs) = rhs(1 : lenRhs)
      93           6 :             add(lenRhs + 1:) = ZERO
      94             :         end if
      95             : 
      96             :         !%%%%%%%%%%%%%%%%%
      97             : #elif   setPolyAdd_ENABLED
      98             :         !%%%%%%%%%%%%%%%%%
      99             : 
     100             :         integer(IK) :: lenRhs, lenLhs
     101          22 :         lenLhs = size(lhs, 1, IK)
     102          22 :         lenRhs = size(rhs, 1, IK)
     103          22 :         CHECK_ASSERTION(__LINE__, 0_IK < lenLhs, SK_"@setPolyAdd(): The condition `0 < size(lhs)` must hold. size(lhs) = "//getStr(lenLhs))
     104          22 :         CHECK_ASSERTION(__LINE__, 0_IK < lenRhs, SK_"@setPolyAdd(): The condition `0 < size(rhs)` must hold. size(rhs) = "//getStr(lenRhs))
     105          88 :         CHECK_ASSERTION(__LINE__, size(add, 1, IK) == max(lenLhs, lenRhs), \
     106             :         SK_"@setPolyAdd(): The condition `size(add) == max(lenLhs, lenRhs)` must hold. size(add), size(lhs), size(rhs) = "//\
     107             :         getStr([size(add, 1, IK), lenLhs, lenRhs]))
     108          22 :         CHECK_ASSERTION(__LINE__, lhs(lenLhs) /= ZERO, SK_"@setPolyAdd(): The condition `lhs(size(lhs)) /= 0.` must hold. lhs = "//getStr(lhs))
     109          22 :         CHECK_ASSERTION(__LINE__, rhs(lenRhs) /= ZERO, SK_"@setPolyAdd(): The condition `rhs(size(rhs)) /= 0.` must hold. rhs = "//getStr(rhs))
     110          22 :         if (lenLhs < lenRhs) then
     111          14 :             add(1 : lenLhs) = lhs(1 : lenLhs) + rhs(1 : lenLhs)
     112          22 :             add(lenLhs + 1 : lenRhs) = rhs(lenLhs + 1 : lenRhs)
     113             :         else
     114          52 :             add(1 : lenRhs) = lhs(1 : lenRhs) + rhs(1 : lenRhs)
     115          36 :             add(lenRhs + 1 : lenLhs) = lhs(lenRhs + 1 : lenLhs)
     116             :         end if
     117             : 
     118             :         !%%%%%%%%%%%%%%%%%
     119             : #elif   getPolySub_ENABLED
     120             :         !%%%%%%%%%%%%%%%%%
     121             : 
     122             :         integer(IK) :: lenLhs, lenRhs, lenMax
     123             :         lenLhs = size(lhs, 1, IK)
     124             :         lenRhs = size(rhs, 1, IK)
     125           0 :         do
     126          14 :             if (lenLhs == 0_IK) exit
     127          10 :             if (lhs(lenLhs) /= ZERO) exit
     128          10 :             lenLhs = lenLhs - 1_IK
     129             :         end do
     130           0 :         do
     131          14 :             if (lenRhs == 0_IK) exit
     132          10 :             if (rhs(lenRhs) /= ZERO) exit
     133          10 :             lenRhs = lenRhs - 1_IK
     134             :         end do
     135          14 :         if (0_IK < lenLhs .and. 0_IK < lenRhs) then
     136           8 :             lenMax = max(lenLhs, lenRhs)
     137           8 :             call setPolySub(sub(1 : lenMax), lhs(1 : lenLhs), rhs(1 : lenRhs))
     138           8 :             sub(lenMax + 1 :) = ZERO
     139           6 :         elseif (0_IK < lenLhs) then
     140           6 :             sub(1 : lenLhs) = lhs(1 : lenLhs)
     141           2 :             sub(lenLhs + 1:) = ZERO
     142             :         else
     143           8 :             sub(1 : lenRhs) = rhs(1 : lenRhs)
     144           4 :             sub(lenRhs + 1:) = ZERO
     145             :         end if
     146             : 
     147             :         !%%%%%%%%%%%%%%%%%
     148             : #elif   setPolySub_ENABLED
     149             :         !%%%%%%%%%%%%%%%%%
     150             : 
     151             :         integer(IK) :: lenRhs, lenLhs
     152          16 :         lenLhs = size(lhs, 1, IK)
     153          16 :         lenRhs = size(rhs, 1, IK)
     154          16 :         CHECK_ASSERTION(__LINE__, 0_IK < lenLhs, SK_"@setPolySub(): The condition `0 < size(lhs)` must hold. size(lhs) = "//getStr(lenLhs))
     155          16 :         CHECK_ASSERTION(__LINE__, 0_IK < lenRhs, SK_"@setPolySub(): The condition `0 < size(rhs)` must hold. size(rhs) = "//getStr(lenRhs))
     156          64 :         CHECK_ASSERTION(__LINE__, size(sub, 1, IK) == max(lenLhs, lenRhs), \
     157             :         SK_"@setPolySub(): The condition `size(sub) == max(lenLhs, lenRhs)` must hold. size(sub), size(lhs), size(rhs) = "//\
     158             :         getStr([size(sub, 1, IK), lenLhs, lenRhs]))
     159          16 :         CHECK_ASSERTION(__LINE__, lhs(lenLhs) /= ZERO, SK_"@setPolySub(): The condition `lhs(size(lhs)) /= 0.` must hold. lhs = "//getStr(lhs))
     160          16 :         CHECK_ASSERTION(__LINE__, rhs(lenRhs) /= ZERO, SK_"@setPolySub(): The condition `rhs(size(rhs)) /= 0.` must hold. rhs = "//getStr(rhs))
     161          16 :         if (lenLhs < lenRhs) then
     162           0 :             sub(1 : lenLhs) =  lhs(1 : lenLhs) - rhs(1 : lenLhs)
     163           0 :             sub(lenLhs + 1 : lenRhs) = -rhs(lenLhs + 1 : lenRhs)
     164             :         else
     165          52 :             sub(1 : lenRhs) =  lhs(1 : lenRhs) + rhs(1 : lenRhs)
     166          36 :             sub(lenRhs + 1 : lenLhs) = lhs(lenRhs + 1 : lenLhs)
     167             :         end if
     168             : 
     169             :         !%%%%%%%%%%%%%%%%%%
     170             : #elif   getPolyMul_ENABLED
     171             :         !%%%%%%%%%%%%%%%%%%
     172             : 
     173             :         integer(IK) :: lenLhs, lenRhs
     174             :         lenLhs = size(lhs, 1, IK)
     175             :         lenRhs = size(rhs, 1, IK)
     176           0 :         do
     177          30 :             if (lenLhs == 0_IK) exit
     178          26 :             if (lhs(lenLhs) /= ZERO) exit
     179          26 :             lenLhs = lenLhs - 1_IK
     180             :         end do
     181           0 :         do
     182          30 :             if (lenRhs == 0_IK) exit
     183          26 :             if (rhs(lenRhs) /= ZERO) exit
     184          26 :             lenRhs = lenRhs - 1_IK
     185             :         end do
     186          30 :         if (0_IK < lenLhs .and. 0_IK < lenRhs) then
     187          24 :             call setPolyMul(mul(1 : lenLhs + lenRhs - 1), lhs(1 : lenLhs), rhs(1 : lenRhs))
     188             :         else
     189           6 :             mul = ZERO
     190             :         end if
     191             : 
     192             :         !%%%%%%%%%%%%%%%%%
     193             : #elif   setPolyMul_ENABLED
     194             :         !%%%%%%%%%%%%%%%%%
     195             : 
     196             :         integer(IK) :: i, j
     197             :         integer(IK) :: lhsdeg, rhsdeg
     198          32 :         lhsdeg = size(lhs, 1, IK) - 1_IK
     199          32 :         rhsdeg = size(rhs, 1, IK) - 1_IK
     200          32 :         CHECK_ASSERTION(__LINE__, 0_IK <= lhsdeg, SK_"@setPolyMul(): The condition `0 < size(lhs)` must hold. size(lhs) = "//getStr(lhsdeg + 1_IK))
     201          32 :         CHECK_ASSERTION(__LINE__, 0_IK <= rhsdeg, SK_"@setPolyMul(): The condition `0 < size(rhs)` must hold. size(rhs) = "//getStr(rhsdeg + 1_IK))
     202         128 :         CHECK_ASSERTION(__LINE__, size(mul, 1, IK) == lhsdeg + rhsdeg + 1_IK, \
     203             :         SK_"@setPolyMul(): The condition `size(mul) == size(lhs) + size(rhs) - 1` must hold. size(mul), size(lhs), size(rhs) = "//\
     204             :         getStr([size(mul, 1, IK), lhsdeg + 1_IK, rhsdeg + 1_IK]))
     205          32 :         CHECK_ASSERTION(__LINE__, lhs(lhsdeg) /= ZERO, SK_"@setPolyMul(): The condition `lhs(size(lhs)) /= 0.` must hold. lhs = "//getStr(lhs))
     206          32 :         CHECK_ASSERTION(__LINE__, rhs(rhsdeg) /= ZERO, SK_"@setPolyMul(): The condition `rhs(size(rhs)) /= 0.` must hold. rhs = "//getStr(rhs))
     207         168 :         mul = ZERO
     208         124 :         do i = 0_IK, lhsdeg
     209         340 :             do j = 0_IK, rhsdeg
     210         308 :                 mul(i + j) = mul(i + j) + lhs(i) * rhs(j)
     211             :             end do
     212             :         end do
     213             : 
     214             :         !%%%%%%%%%%%%%%%%%
     215             : #elif   setPolyDiv_ENABLED
     216             :         !%%%%%%%%%%%%%%%%%
     217             : 
     218             :         TYPE_KIND :: remainder, normfac
     219             :         TYPE_KIND, allocatable :: DividendTerm(:), DivisorTerm(:), QuotientTerm(:)
     220             :         integer(IK) :: i, degDividend, degDivisor, lenDivisor, lenDividend
     221           8 :         lenDividend = size(dividend, 1, IK)
     222           8 :         lenDivisor = size(divisor, 1, IK)
     223           8 :         CHECK_ASSERTION(__LINE__, 0_IK < lenDivisor, SK_"@setPolyDiv(): The condition `0 < size(divisor)` must hold. size(divisor) = "//getStr(lenDivisor))
     224           8 :         CHECK_ASSERTION(__LINE__, 0_IK < lenDividend, SK_"@setPolyDiv(): The condition `0 < size(dividend)` must hold. size(dividend) = "//getStr(lenDividend))
     225          24 :         CHECK_ASSERTION(__LINE__, size(quorem, 1, IK) == lenDividend, SK_"@setPolyDiv(): The condition `size(quorem) == size(dividend)` must hold. size(quorem), size(dividend) = "//getStr([size(quorem, 1, IK), lenDividend]))
     226           8 :         CHECK_ASSERTION(__LINE__, dividend(lenDividend) /= ZERO, SK_"@setPolyDiv(): The condition `dividend(size(dividend)) /= 0.` must hold. dividend = "//getStr(dividend))
     227           8 :         CHECK_ASSERTION(__LINE__, divisor(lenDivisor) /= ZERO, SK_"@setPolyDiv(): The condition `divisor(size(divisor)) /= 0.` must hold. divisor = "//getStr(divisor))
     228           8 :         if (lenDivisor <= lenDividend) then
     229           8 :             if (lenDivisor > 2_IK) then
     230          18 :                 allocate(DivisorTerm(lenDividend), QuotientTerm(lenDividend), source = ZERO)
     231           8 :                 DivisorTerm(1:lenDivisor) = divisor
     232           2 :                 degDividend = lenDividend - 1_IK
     233           2 :                 degDivisor = lenDivisor - 1_IK
     234          12 :                 DividendTerm = dividend
     235           2 :                 lenQuo = 0_IK
     236             :                 do
     237          40 :                     DivisorTerm = eoshift(DivisorTerm, degDivisor - degDividend)
     238           4 :                     QuotientTerm(degDividend - degDivisor + 1) = DividendTerm(degDividend + 1) / DivisorTerm(degDividend + 1)
     239          20 :                     DividendTerm = DividendTerm - DivisorTerm * QuotientTerm(degDividend - degDivisor + 1)
     240           4 :                     lenQuo = max(lenQuo, degDividend - degDivisor)
     241             :                     do
     242           4 :                         degDividend = degDividend - 1_IK
     243           4 :                         if (DividendTerm(degDividend + 1) /= ZERO) exit
     244             :                     end do
     245          16 :                     DivisorTerm(1 : lenDivisor) = divisor
     246           8 :                     DivisorTerm(lenDivisor + 1 : lenDividend) = ZERO
     247           4 :                     if (degDividend < degDivisor) exit
     248             :                 end do
     249           2 :                 lenQuo = lenQuo + 1_IK
     250           6 :                 quorem(1 : lenQuo) = QuotientTerm(1 : lenQuo)
     251           6 :                 quorem(lenQuo + 1 : lenDividend) = DividendTerm(1 : degDividend + 1)
     252             :                 ! \bug gfortran as of version 12 fails to automatically deallocate heap allocations.
     253           2 :                 deallocate(DividendTerm, DivisorTerm, QuotientTerm)
     254           6 :             elseif (lenDivisor == 2_IK) then
     255           6 :                 if (divisor(2) /= ONE) then
     256           3 :                     normfac = ONE / divisor(2)
     257           3 :                     remainder = dividend(lenDividend) * normfac
     258          11 :                     do i = lenDividend - 1_IK, 1_IK, -1_IK
     259           8 :                         quorem(i) = remainder
     260          11 :                         remainder = (dividend(i) - divisor(1) * remainder) * normfac
     261             :                     end do
     262             :                 else
     263           3 :                     remainder = dividend(lenDividend)
     264          11 :                     do i = lenDividend - 1_IK, 1_IK, -1_IK
     265           8 :                         quorem(i) = remainder
     266          11 :                         remainder = dividend(i) - divisor(1) * remainder
     267             :                     end do
     268             :                 end if
     269           6 :                 quorem(lenDividend) = remainder
     270           6 :                 lenQuo = lenDividend - 1_IK
     271             :             else ! lenDivisor == 1_IK
     272           0 :                 normfac = ONE / divisor(1)
     273           0 :                 quorem = dividend * normfac
     274             :             end if
     275             :         else
     276           0 :             lenQuo = 0_IK
     277           0 :             quorem = dividend
     278             :         end if
     279             : 
     280             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     281             : #elif   (getPolyDiff_ENABLED || setPolyDiff_ENABLED) && Def_ENABLED
     282             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     283             : 
     284             :         integer(IK) :: i
     285             :         integer(IK), parameter :: order = 1
     286             : #if     setPolyDiff_ENABLED
     287           0 :         CHECK_ASSERTION(__LINE__, size(diff, 1, IK) == max(0_IK, size(coef, 1, IK) - order),\
     288             :         SK_"@setPolyDiff(): The condition `size(diff) == max(0, size(coef) - order)` must hold. size(diff), size(coef), order = "//\
     289             :         getStr([size(diff, 1, IK), size(coef, 1, IK), order]))
     290             : #elif   !getPolyDiff_ENABLED
     291             : #error  "Unrecognized interface."
     292             : #endif
     293             :         do concurrent(i = order : size(coef, 1, IK) - 1_IK)
     294           0 :             diff(i) = coef(i) * i
     295             :         end do
     296             : 
     297             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     298             : #elif   (getPolyDiff_ENABLED || setPolyDiff_ENABLED) && Ord_ENABLED
     299             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     300             : 
     301             :         integer(IK) :: i, lenCoef
     302          40 :         lenCoef = size(coef, 1, IK)
     303             : #if     setPolyDiff_ENABLED
     304         160 :         CHECK_ASSERTION(__LINE__, size(diff, 1, IK) == max(0_IK, lenCoef - order), \
     305             :         SK_"@setPolyDiff(): The condition `size(diff) == max(0, size(coef) - order)` must hold. size(diff), size(coef), order = "//\
     306             :         getStr([size(diff, 1, IK), lenCoef, order]))
     307             : #elif   !getPolyDiff_ENABLED
     308             : #error  "Unrecognized interface."
     309             : #endif
     310          80 :         if (0_IK < order) then
     311          35 :             do concurrent(i = order : lenCoef - 1_IK)
     312         201 :                 diff(i) = coef(i) * real(i, TKC)
     313             :             end do
     314             :         else
     315          12 :             CHECK_ASSERTION(__LINE__, 0_IK <= order, SK_"@setPolyDiff(): The condition `0 <= order` must hold. order = "//getStr(order))
     316          37 :             diff = coef
     317             :         end if
     318             : 
     319             :         !%%%%%%%%%%%%%%%%%
     320             : #elif   getPolyStr_ENABLED
     321             :         !%%%%%%%%%%%%%%%%%
     322             : 
     323             :         !> The maximum possible length of the string output from the functions under the generic interface `getStr`.
     324             :         !> Note that `NUMERIC_MAXLEN = 127` is very generous given that,
     325             :         !>  +   The maximum length of a complex of kind `real128` including signs, exponentiation, comma, and parentheses is `93` characters.
     326             :         !>      `(-1.189731495357231765085759326628007016E+4932,-1.189731495357231765085759326628007016E+4932)`
     327             :         !>  +   The maximum length of a real of kind `real128` including signs and exponentiation is `44` characters.
     328             :         !>      `-1.18973149535723176508575932662800702E+4932`
     329             :         !>  +   The maximum length of an integer of kind `int64` including signs `20` characters.
     330             :         !>      `-9223372036854775807`
     331             :         character(127, SK)          :: iomsg
     332             :         integer(IK)                 :: i, iostat, lenCoef, strlen
     333             :         integer(IK)     , parameter :: NUMERIC_MAXLEN = 127_IK
     334             :         character(*,SKC), parameter :: PRODSYM = SKC_""
     335             :         character(*,SKC), parameter :: VARNAME = SKC_"x"
     336             :         character(*,SKC), parameter :: POWSYM = SKC_"^"
     337             :         character(*,SKC), parameter :: FIXED = PRODSYM//VARNAME//POWSYM
     338             : #if     CK_ENABLED
     339             : #define GET_POLY_TERM(i) SKC_"(", coef(i)%re, SKC_",", coef(i)%im, SKC_")", FIXED, i
     340             : #define POLY_TERM_CONST GET_POLY_TERM(0)
     341             : #define GET_SIGNSYM(i) SKC_" + "
     342             : #elif   RK_ENABLED
     343             :         character(*,SKC), parameter :: SIGNSYM(-1:1) = [SKC_" - ", SKC_"   ", SKC_" + "]
     344             : #define POLY_TERM_CONST coef(0), FIXED, 0
     345             : #define GET_POLY_TERM(i) abs(coef(i)), FIXED, i
     346             : #define GET_SIGNSYM(i) SIGNSYM(int(sign(1.1_TKC, coef(i))))
     347             : #else
     348             : #error  "Unrecognized interface."
     349             : #endif
     350         414 :         lenCoef = size(coef, 1, IK)
     351         414 :         if (0 < lenCoef) then
     352         333 :             strlen = NUMERIC_MAXLEN * lenCoef
     353         333 :             allocate(character(strlen,SKC) :: str)
     354           0 :             loopExpandStr: do
     355        1175 :                 write(str, "(ss,*(g0))", iostat = iostat, iomsg = iomsg) POLY_TERM_CONST, (GET_SIGNSYM(i), GET_POLY_TERM(i), i = 1_IK, lenCoef - 1_IK)
     356             :                 !write(*,*); write(*,*) is_iostat_eor(iostat), iostat, iomsg; write(*,*)
     357         333 :                 if (iostat == 0_IK) then
     358         333 :                     str = getTrimmedTZ(str)
     359             :                     return
     360           0 :                 elseif (is_iostat_eor(iostat)) then
     361             :                     call setResized(str) ! LCOV_EXCL_LINE
     362             :                     cycle loopExpandStr ! LCOV_EXCL_LINE
     363             :                 else
     364             :                     error stop MODULE_NAME//& ! LCOV_EXCL_LINE
     365             :                     SK_"@getPolyStr(): A runtime error occurred while converting the polynomial coefficients to a polynomial expression: "//trim(iomsg) ! LCOV_EXCL_LINE
     366             :                 end if
     367             :             end do loopExpandStr
     368             :         else
     369          81 :             str = SKC_""
     370             :         end if
     371             : #undef  POLY_TERM_CONST
     372             : #undef  GET_POLY_TERM
     373             : #undef  GET_SIGNSYM
     374             : 
     375             :         !%%%%%%%%%%%%%%%%%%
     376             : #elif   getPolyRoot_ENABLED
     377             :         !%%%%%%%%%%%%%%%%%%
     378             : 
     379             :         integer(IK) :: count
     380             : #if     Def_ENABLED
     381             :         type(eigen_type), parameter :: method = eigen_type()
     382             : #elif   !(Eig_ENABLED || Jen_ENABLED || Lag_ENABLED)
     383             : #error  "Unrecognized interface."
     384             : #endif
     385          18 :         allocate(root(size(coef, 1, IK) - 1_IK))
     386          18 :         call setPolyRoot(root, count, coef, method)
     387         192 :         root = root(1 : count)
     388             : 
     389             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     390             : #elif   setPolyRoot_ENABLED && Eig_ENABLED
     391             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     392             : 
     393             :         real(TKC), parameter :: EPS = epsilon(0._TKC), BASE = radix(1._TKC), BASESQ = BASE * BASE
     394             : #if     RK_CK_ENABLED
     395             : #define GET_ABS(x) abs(x)
     396             :         real(TKC) :: p, q, t, w, x, y, zz
     397             :         integer(IK) :: k, l, m, ll, low, mm, mp2, na, niter, enm2
     398             :         logical(LK) :: notlas
     399             : #elif   CK_CK_ENABLED
     400             : #define GET_ABS(x) abs(x%re) + abs(x%im)
     401             : #else
     402             : #error  "Unrecognized interface."
     403             : #endif
     404             :         integer(IK) :: i, j, degree
     405             :         logical(LK) :: normReductionEnabled
     406           0 :         TYPE_KIND :: workspace(size(root, 1, IK), size(root, 1, IK))
     407             :         real(TKC) :: r, s, c, scaleFac, g
     408          29 :         degree = size(coef, 1, IK) - 1_IK
     409          29 :         CHECK_ASSERTION(__LINE__, 0_IK < degree, SK_"@setPolyRoot(): The condition `1 < size(coef)` must hold. size(coef) = "//getStr(degree + 1_IK))
     410          87 :         CHECK_ASSERTION(__LINE__, size(root, 1, IK) == degree, SK_"@setPolyRoot(): The condition `size(root) == size(coef) - 1` must hold. size(root), size(coef) - 1 = "//getStr([size(root, 1, IK), degree]))
     411         232 :         CHECK_ASSERTION(__LINE__, all(shape(workspace, kind = IK) == degree), SK_"@setPolyRoot(): The condition `all(shape(workspace) == size(coef) - 1)` must hold. shape(workspace), size(coef) = "//getStr([shape(workspace, kind = IK), degree + 1_IK]))
     412          29 :         CHECK_ASSERTION(__LINE__, coef(degree) /= ZERO, SK_"@setPolyRoot(): The condition `coef(size(coef)) /= 0.` must hold. degree = "//getStr(coef(degree)))
     413             : 
     414             :         ! Gracefully capture the error and return if the highest polynomial coefficient is zero.
     415             : 
     416          29 :         if (coef(degree) == ZERO) then
     417           0 :             count = 0_IK ! degree + 1_IK
     418           0 :             return
     419             :         end if
     420             : 
     421             :         ! Build the count row of the upper Hessenberg Companion matrix.
     422             : 
     423             :         do concurrent(i = 1_IK : degree)
     424         238 :             workspace(1, i) = -coef(degree - i) / coef(degree)
     425             :         end do
     426             : 
     427             :         ! Extract any exact ZERO roots and set degree = degree of remaining polynomial.
     428             : 
     429          29 :         do j = degree, 1_IK, -1_IK
     430          29 :             if (workspace(1, j) /= ZERO) exit
     431           0 :             root(j) = cmplx(ZERO, kind = TKC) ! xxx
     432          29 :             degree = degree - 1_IK
     433             :         end do
     434             : 
     435             :         ! The special case of `degree == 0` or `degree == 1`.
     436             : 
     437          29 :         if (degree == 0_IK) then ! Gracefully capture the error and return if the degree of polynomial is zero.
     438           0 :             count = 0_IK
     439           0 :             return
     440          29 :         elseif (degree == 1_IK) then
     441           0 :             root(1) = workspace(1,1)
     442           0 :             count = 1_IK
     443           0 :             return
     444             :         end if
     445             : 
     446             :         ! Build rows 2 through `degree` of the Companion matrix.
     447             : 
     448         209 :         do i = 2_IK, degree
     449        1782 :             do j = 1_IK, degree
     450        1782 :                 workspace(i, j) = ZERO
     451             :             end do
     452         209 :             workspace(i, i - 1) = ONE
     453             :         end do
     454             : 
     455             :         !   Balance the matrix.
     456             :         !   This is an adaption of the EISPACK subroutine `balanc` to the special case of a Companion matrix.
     457             :         !   The EISPACK balance is a translation of the Algol procedure balance, num. math. 13, 293-304(1969) by parlett and reinsch. handbook for auto. comp., vol.ii-linear algebra, 315-326(1971).
     458             : 
     459             :         !   Iterative loop for norm reduction
     460             : 
     461             :         loopNormReduction: do
     462             : 
     463             :             normReductionEnabled = .false.
     464             : 
     465         836 :             do i = 1_IK, degree
     466             : 
     467             :                 !   r = sum of magnitudes in row i skipping diagonal.
     468             :                 !   c = sum of magnitudes in col i skipping diagonal.
     469             : 
     470         744 :                 if (i == 1_IK) then
     471          92 :                     r = GET_ABS(workspace(1, 2))
     472         652 :                     do j = 3, degree
     473         652 :                         r = r + GET_ABS(workspace(1, j))
     474             :                     end do
     475          92 :                     c = GET_ABS(workspace(2, 1))
     476             :                 else
     477         652 :                     r = GET_ABS(workspace(i, i - 1))
     478         652 :                     c = GET_ABS(workspace(1, i))
     479         652 :                     if (i /= degree) c = c + GET_ABS(workspace(i + 1, i))
     480             :                 end if
     481             : 
     482             :                 ! Determine column scale factor, `scaleFac`.
     483             : 
     484         744 :                 g = r / BASE
     485         264 :                 scaleFac = real(ONE, TKC)
     486         744 :                 s = c + r
     487         468 :                 do
     488        1212 :                     if (c < g) then
     489         468 :                         scaleFac = scaleFac * BASE
     490         468 :                         c = c * BASESQ
     491             :                         cycle
     492             :                     end if
     493             :                     exit
     494             :                 end do
     495         744 :                 g = r * BASE
     496         628 :                 do
     497        1372 :                     if (c >= g) then
     498         628 :                         scaleFac = scaleFac / BASE
     499         628 :                         c = c / BASESQ
     500             :                         cycle
     501             :                     end if
     502             :                     exit
     503             :                 end do
     504             : 
     505             :                 ! Will the factor `scaleFac` have a significant effect?
     506             : 
     507         836 :                 if ((c + r) / scaleFac < .95_TKC * s) then ! yes, so do the scaling.
     508             : 
     509         312 :                     g = real(ONE, TKC) / scaleFac
     510             :                     normReductionEnabled = .true.
     511             : 
     512             :                     ! scale row `i`
     513             : 
     514         312 :                     if (i == 1_IK) then
     515         324 :                         do j = 1_IK, degree
     516         324 :                             workspace(1, j) = workspace(1, j) * g
     517             :                         end do
     518             :                     else
     519         274 :                         workspace(i, i - 1) = workspace(i, i - 1) * g
     520             :                     end if
     521             : 
     522             :                     ! Scale column `i`.
     523             : 
     524         312 :                     workspace(1, i) = workspace(1, i) * scaleFac
     525         312 :                     if (i /= degree) workspace(i + 1, i) = workspace(i + 1, i) * scaleFac
     526             : 
     527             :                 end if
     528             : 
     529             :             end do
     530             : 
     531          92 :             if (normReductionEnabled) cycle loopNormReduction
     532          63 :             exit loopNormReduction
     533             : 
     534             :         end do loopNormReduction
     535             : 
     536             : #if     RK_CK_ENABLED
     537             :         !   ***************** QR eigenvalue algorithm ***********************
     538             :         !   This is the EISPACK subroutine hqr that uses the QR
     539             :         !   algorithm to compute all eigenvalues of an upper
     540             :         !   hessenberg matrix. original algol code was due to Martin,
     541             :         !   Peters, and Wilkinson, numer. math., 14, 219-231(1970).
     542          10 :         count = degree
     543             :         low = 1_IK
     544           3 :         t = ZERO
     545             :         !   ********** search for next eigenvalues **********
     546             :         loopNextEigen: do
     547          67 :             if (count < low) exit loopNextEigen
     548             :             niter = 0_IK
     549          54 :             na = count - 1_IK
     550          54 :             enm2 = na - 1_IK
     551             :             !   ********** look for single small sub-diagonal element for `l = count step -1` until `low` do -- **********
     552             :             do
     553        1191 :                 do ll = low, count
     554        1191 :                     l = count + low - ll
     555        1191 :                     if (l == low) exit
     556        1191 :                     if (abs(workspace(l, l - 1)) <= EPS * (abs(workspace(l - 1, l - 1)) + abs(workspace(l, l)))) exit
     557             :                 end do
     558             :                 !   ********** form shift **********
     559         261 :                 x = workspace(count, count)
     560         261 :                 if (l == count) exit
     561         227 :                 y = workspace(na,na)
     562         227 :                 w = workspace(count,na) * workspace(na,count)
     563         227 :                 if (l == na) then ! two roots found
     564          20 :                     p = (y - x) * .5_TKC
     565          20 :                     q = p * p + w
     566          20 :                     zz = sqrt(abs(q))
     567          20 :                     x = x + t
     568          20 :                     if (q < ZERO) then ! complex pair
     569          15 :                         root(na) = cmplx(x + p, zz, TKC)
     570          15 :                         root(count) = cmplx(x + p, -zz, TKC)
     571             :                     else ! pair of reals
     572           5 :                         zz = p + sign(zz, p)
     573           5 :                         root(na) = cmplx(x + zz, ZERO, TKC)
     574           5 :                         root(count) = root(na)
     575           5 :                         if (zz /= ZERO) root(count) = cmplx(x - w / zz, ZERO, TKC)
     576             :                     end if
     577          20 :                     count = enm2
     578          20 :                     cycle loopNextEigen
     579             :                 end if
     580             :                 ! increased iterations for quad-precision.
     581             :                !if (niter == 30_IK) exit loopNextEigen ! failed. No convergence to an eigenvalue after 30 iterations.
     582         207 :                 if (niter == 90_IK) exit loopNextEigen ! failed. No convergence to an eigenvalue after 30 iterations.
     583         207 :                 if (niter == 10_IK .or. niter == 20_IK) then ! form exceptional shift.
     584           7 :                     t = t + x
     585          42 :                     do i = low, count
     586          42 :                         workspace(i,i) = workspace(i,i) - x
     587             :                     end do
     588           7 :                     s = abs(workspace(count, na)) + abs(workspace(na, enm2))
     589           7 :                     x = .75_TKC * s
     590           2 :                     y = x
     591           7 :                     w = -.4375_TKC * s * s
     592             :                 end if
     593         207 :                 niter = niter + 1_IK
     594             :                 ! Look for two consecutive small sub-diagonal elements. for `m = count - 2 step -1` until l do.
     595         647 :                 do mm = l, enm2
     596         647 :                     m = enm2 + l - mm
     597         647 :                     zz = workspace(m, m)
     598         647 :                     r = x - zz
     599         647 :                     s = y - zz
     600         647 :                     p = (r * s - w) / workspace(m + 1,m) + workspace(m, m + 1)
     601         647 :                     q = workspace(m + 1, m + 1) - zz - r - s
     602         647 :                     r = workspace(m + 2, m + 1)
     603         647 :                     s = abs(p) + abs(q) + abs(r)
     604         647 :                     p = p / s
     605         647 :                     q = q / s
     606         647 :                     r = r / s
     607         647 :                     if (m == l) exit
     608         647 :                     if (abs(workspace(m, m - 1)) * (abs(q) + abs(r)) <= EPS * abs(p) * (abs(workspace(m - 1, m - 1)) + abs(zz) + abs(workspace(m + 1, m + 1)))) exit
     609             :                 end do
     610         207 :                 mp2 = m + 2_IK
     611         854 :                 do i = mp2, count
     612         647 :                     workspace(i, i - 2) = ZERO
     613         647 :                     if (i == mp2) cycle
     614         854 :                     workspace(i, i - 3) = ZERO
     615             :                 end do
     616             :                 ! Double QR step involving rows l to count and columns m to count.
     617        1095 :                 do k = m, na
     618             :                     notlas = k /= na
     619         854 :                     if (k /= m) then
     620         647 :                         p = workspace(k, k - 1)
     621         647 :                         q = workspace(k + 1, k - 1)
     622         260 :                         r = ZERO
     623         647 :                         if (notlas) r = workspace(k + 2, k - 1)
     624         647 :                         x = abs(p) + abs(q) + abs(r)
     625         647 :                         if (x == ZERO) cycle
     626         647 :                         p = p / x
     627         647 :                         q = q / x
     628         647 :                         r = r / x
     629             :                     end if
     630         854 :                     s = sign(sqrt(p * p + q * q + r * r), p)
     631         854 :                     if (k /= m) then
     632         647 :                         workspace(k, k - 1) = -s * x
     633         207 :                     elseif (l /= m) then
     634          53 :                         workspace(k, k - 1) = -workspace(k, k - 1)
     635             :                     end if
     636         854 :                     p = p + s
     637         854 :                     x = p / s
     638         854 :                     y = q / s
     639         854 :                     zz = r / s
     640         854 :                     q = q / p
     641         508 :                     r = r / p
     642             :                     ! row modification.
     643        4287 :                     do j = k, count
     644        3433 :                         p = workspace(k, j) + q * workspace(k + 1, j)
     645        3433 :                         if (notlas) then
     646        3019 :                             p = p + r * workspace(k + 2, j)
     647        3019 :                             workspace(k + 2, j) = workspace(k + 2, j) - p * zz
     648             :                         end if
     649        3433 :                         workspace(k + 1, j) = workspace(k + 1, j) - p * y
     650        4287 :                         workspace(k, j) = workspace(k, j) - p * x
     651             :                     end do
     652         854 :                     j = min(count, k + 3)
     653             :                     ! column modification.
     654        5742 :                     do i = l, j
     655        4681 :                         p = x * workspace(i,k) + y * workspace(i, k + 1)
     656        4681 :                         if (notlas) then
     657        3564 :                             p = p + zz * workspace(i, k + 2)
     658        3564 :                             workspace(i, k + 2) = workspace(i, k + 2) - p * r
     659             :                         end if
     660        4681 :                         workspace(i, k + 1) = workspace(i, k + 1) - p * q
     661        5535 :                         workspace(i,k) = workspace(i,k) - p
     662             :                     end do
     663             :                 end do
     664             :             end do
     665             :             !   ********** ONE root found **********
     666          34 :             root(count) = cmplx(x + t, ZERO, TKC)
     667          34 :             count = na
     668             :         end do loopNextEigen
     669          13 :         count = count + 1_IK
     670             : #elif   CK_CK_ENABLED
     671          16 :         call dcomqr(1_IK, degree, workspace(:, 1 : degree), root(1 : degree), count)
     672             : #else
     673             : #error  "Unrecognized interface."
     674             : #endif
     675             :         !   This block reverses the ordering of the identified roots, such that `root(1:count)` contains it all.
     676             :         !   \todo
     677             :         !   This ordering reversal could be merged with the rest of the algorithm to avoid the extra final reversal copy below.
     678             :         !   However, given that most polynomials are of low degree, the final reversal copy cost should generally be quite negligible.
     679             :         !   Because of the complexity of the rest of the algorithm, a final copy was the preferred approach over merging the reversal with the algorithm, for now.
     680             :         block
     681             :             complex(TKC) :: temp
     682             :             integer(IK) :: lenRoot
     683             :             lenRoot = size(root, 1, IK)
     684         238 :             do i = lenRoot, count, -1_IK
     685         209 :                 temp = root(i)
     686         209 :                 root(i) = root(lenRoot - i + 1_IK)
     687         238 :                 root(lenRoot - i + 1_IK) = temp
     688             :             end do
     689          29 :             count = lenRoot - count + 1_IK
     690             :         end block
     691             : #if CK_CK_ENABLED
     692             :     contains
     693             :         !   This subroutine is a translation of a unitary analogue of the algol
     694             :         !   procedure comlr, num. math. 12, 369-376(1968) by Martin and Wilkinson.
     695             :         !   Handbook for auto. comp., vol.ii-linear algebra, 396-403(1971).
     696             :         !   the unitary analogue substitutes the QR algorithm of Francis
     697             :         !   (comp. jour. 4, 332-345(1962)) for the LR algorithm.
     698             :         !   This subroutine finds the eigenvalues of a complex
     699             :         !   upper hessenberg matrix by the QR method.
     700             :         !   `low` and `igh` are integers determined by the balancing subroutine `cbal`.
     701             :         !   if `cbal` has not been used, set `low = 1, igh = order`.
     702             :         !   `hessen` contains the complex upper hessenberg matrix.
     703             :         !   The lower triangle of `hessen` below the subdiagonal contains
     704             :         !   information about the unitary transformations used in the reduction by `corth`, if performed.
     705             :         !   ON OUTPUT:
     706             :         !       The upper hessenberg portions of `hessen` are destroyed.
     707             :         !       Therefore, they must be saved before calling `comqr`
     708             :         !       if subsequent calculation of eigenvectors is to be performed.
     709             :         !
     710             :         !       `root` contains the eigenvalues.
     711             :         !       If an error exit is made, the eigenvalues should be correct for indices `first+1,...,order`,
     712             :         !       `first` is set to,
     713             :         !           zero       for normal return,
     714             :         !           j          if the j-th eigenvalue has not been
     715             :         !                      determined after 30 iterations.
     716             :         !
     717             :         !   arithmetic is real except for the replacement of the algol
     718             :         !   procedure cdiv by complex division and use of the subroutines
     719             :         !   sqrt and cmplx in computing complex square roots.
     720          16 :         pure subroutine dcomqr(low, igh, hessen, eigen, first)
     721             :             complex(TKC)    , intent(out)   :: eigen(:)
     722             :             complex(TKC)    , intent(inout) :: hessen(:,:) ! hessen%im(nm, order),hessen%re(nm,order)
     723             :             integer(IK)     , intent(in)    :: low, igh
     724             :             integer(IK)     , intent(out)   :: first
     725             :             complex(TKC)                    :: s, t, x, y, z3, zz
     726             :             integer(IK)                     :: enm1, i, niter, j, l, ll, lp1, order
     727             :             real(TKC)                       :: norm
     728          16 :             order = size(eigen, 1, IK) ! The order of the Hessenberg matrix.
     729          16 :             if (low /= igh) then ! 180
     730             :                 !   create real subdiagonal elements
     731          16 :                 l = low + 1_IK
     732         135 :                 do i = l, igh
     733         135 :                     if (hessen(i, i - 1)%im /= 0._TKC) then
     734           0 :                         norm = abs(hessen(i, i - 1))
     735           0 :                         y = hessen(i, i - 1) / norm
     736           0 :                         hessen(i, i - 1) = cmplx(norm, 0._TKC, TKC)
     737           0 :                         do j = i, igh
     738           0 :                             s%im = y%re * hessen(i, j)%im - y%im * hessen(i, j)%re
     739           0 :                             hessen(i, j)%re = y%re * hessen(i, j)%re + y%im * hessen(i, j)%im
     740           0 :                             hessen(i, j)%im = s%im
     741             :                         end do
     742           0 :                         do j = low, min(i + 1_IK, igh)
     743           0 :                             s%im = y%re * hessen(j, i)%im + y%im * hessen(j, i)%re
     744           0 :                             hessen(j, i)%re = y%re * hessen(j, i)%re - y%im * hessen(j, i)%im
     745           0 :                             hessen(j, i)%im = s%im
     746             :                         end do
     747             :                     end if
     748             :                 end do
     749             :             end if
     750             :             !   Store roots isolated by cbal.
     751         151 :             do i = 1_IK, order
     752         135 :                 if (low <= i .and. i <= igh) cycle
     753         151 :                 eigen(i) = hessen(i, i)
     754             :             end do
     755          16 :             first = igh
     756          11 :             t = (0._TKC, 0._TKC)
     757             :             !   Search for next eigenvalue.
     758         135 :             loopNextEigen: do ! 220
     759         151 :                 if (first < low) then ! convergence achieved.
     760          16 :                     first = low
     761          16 :                     return
     762             :                 end if
     763             :                 niter = 0_IK
     764         135 :                 enm1 = first - 1_IK
     765             :                 !   Look for single small sub-diagonal element for `l = first` step `-1` until `low`.
     766             :                 loop240: do
     767        3514 :                     do ll = low, first
     768        3514 :                         l = first + low - ll
     769        3514 :                         if (l == low) exit
     770             :                         if (abs(hessen(l, l - 1)%re) <= EPS * & ! LCOV_EXCL_LINE
     771             :                                                             ( abs(hessen(l - 1, l - 1)%re) & ! LCOV_EXCL_LINE
     772             :                                                             + abs(hessen(l - 1, l - 1)%im) & ! LCOV_EXCL_LINE
     773             :                                                             + abs(hessen(l, l)%re) & ! LCOV_EXCL_LINE
     774             :                                                             + abs(hessen(l, l)%im) & ! LCOV_EXCL_LINE
     775         661 :                                                             ) ) exit
     776             :                     end do
     777             :                     !   Form shift. 300
     778         661 :                     if (l == first) then ! 660 : a root found.
     779             :                         ! A root found ! 660
     780         135 :                         eigen(first) = hessen(first, first) + t
     781         135 :                         first = enm1
     782             :                         cycle loopNextEigen
     783             :                     end if
     784             :                     ! amir: increased maximum iteration to allow for quad-precision convergence.
     785         526 :                     if (niter == 90_IK) then ! No convergence to an eigenvalue after 30 iterations.
     786           0 :                         first = first + 1_IK
     787           0 :                         return
     788             :                     end if
     789         526 :                     if (niter == 10_IK .or. niter == 20_IK) then ! 320 Form exceptional shift.
     790          11 :                         s = cmplx(abs(hessen(first, enm1)%re) + abs(hessen(enm1, first - 2)%re), 0._TKC, TKC)
     791             :                     else
     792         515 :                         s = hessen(first, first)
     793         515 :                         x%re = hessen(enm1, first)%re * hessen(first, enm1)%re
     794         515 :                         x%im = hessen(enm1, first)%im * hessen(first, enm1)%re
     795         515 :                         if (x%re /= 0._TKC .or. x%im /= 0._TKC) then ! 340 ! xx z3 and zz can be replaced with a single variable `z`.
     796         499 :                             y = 0.5_TKC * (hessen(enm1, enm1) - s)
     797         499 :                             z3 = sqrt(cmplx(y%re**2 - y%im**2 + x%re, 2._TKC * y%re * y%im + x%im, TKC))
     798         393 :                             zz = z3
     799         499 :                             if (y%re * zz%re + y%im * zz%im < 0._TKC) zz = -zz ! 310
     800         499 :                             z3 = x / (y + zz)
     801         499 :                             s = s - z3
     802             :                         end if
     803             :                     end if
     804        4402 :                     do i = low, first ! 340
     805        4402 :                         hessen(i,i) = hessen(i,i) - s
     806             :                     end do
     807         526 :                     t = t + s
     808         526 :                     niter = niter + 1_IK
     809             :                     ! Reduce to triangle (rows).
     810         526 :                     lp1 = l + 1_IK
     811        3379 :                     do i = lp1, first ! 500
     812        2853 :                         s%re = hessen(i, i - 1)%re
     813        2853 :                         hessen(i, i - 1)%re = 0._TKC
     814        2853 :                         norm = sqrt(s%re**2 + hessen(i - 1, i - 1)%re**2 + hessen(i - 1, i - 1)%im**2)
     815        2853 :                         x = hessen(i - 1, i - 1) / norm
     816        2853 :                         eigen(i - 1) = x
     817        2853 :                         hessen(i - 1, i - 1) = cmplx(norm, 0._TKC, TKC)
     818        2853 :                         hessen(i, i - 1)%im = s%re / norm
     819       15106 :                         do j = i, first ! 490
     820       11727 :                             y = hessen(i - 1, j)
     821       11727 :                             zz = hessen(i, j)
     822       11727 :                             hessen(i - 1, j)%re = x%re * y%re + x%im * y%im + hessen(i, i - 1)%im * zz%re
     823       11727 :                             hessen(i - 1, j)%im = x%re * y%im - x%im * y%re + hessen(i, i - 1)%im * zz%im
     824       11727 :                             hessen(i, j)%re = x%re * zz%re - x%im * zz%im - hessen(i, i - 1)%im * y%re
     825       14580 :                             hessen(i, j)%im = x%re * zz%im + x%im * zz%re - hessen(i, i - 1)%im * y%im
     826             :                         end do
     827             :                     end do
     828         526 :                     s%im = hessen(first, first)%im
     829         526 :                     if (s%im /= 0._TKC) then
     830         503 :                         norm = abs(cmplx(hessen(first, first)%re, s%im, TKC))
     831         503 :                         s%re = hessen(first, first)%re / norm
     832         503 :                         s%im = s%im / norm
     833         503 :                         hessen(first, first) = cmplx(norm, 0._TKC, TKC)
     834             :                     end if
     835             :                     ! Inverse operation (columns).
     836        3379 :                     do j = lp1, first ! 540
     837        2853 :                         x = eigen(j - 1)
     838       17959 :                         do i = l, j
     839       14580 :                             y = cmplx(hessen(i, j - 1)%re, 0._TKC, TKC)
     840       14580 :                             zz = hessen(i, j)
     841       14580 :                             if (i /= j) then ! 560
     842       11727 :                                 y%im = hessen(i, j - 1)%im
     843       11727 :                                 hessen(i, j - 1)%im = x%re * y%im + x%im * y%re + hessen(j, j - 1)%im * zz%im
     844             :                             end if
     845       14580 :                             hessen(i, j - 1)%re = x%re * y%re - x%im * y%im + hessen(j, j - 1)%im * zz%re
     846       14580 :                             hessen(i, j)%re = x%re * zz%re + x%im * zz%im - hessen(j, j - 1)%im * y%re
     847       20197 :                             hessen(i, j)%im = x%re * zz%im - x%im * zz%re - hessen(j, j - 1)%im * y%im
     848             :                         end do
     849             :                     end do
     850         526 :                     if (s%im == 0._TKC) cycle loop240
     851        3745 :                     do i = l, first
     852        3242 :                         y = hessen(i,first)
     853        3242 :                         hessen(i,first)%re = s%re * y%re - s%im * y%im
     854        3768 :                         hessen(i,first)%im = s%re * y%im + s%im * y%re
     855             :                     end do
     856             :                 end do loop240
     857             :             end do loopNextEigen
     858             :         end subroutine
     859             : #endif
     860             : #undef  GET_ABS
     861             : 
     862             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     863             : #elif   setPolyRoot_ENABLED && Jen_ENABLED && CK_CK_ENABLED
     864             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     865             : 
     866             :         ! the program has been written to reduce the chance of overflow occurring.
     867             :         ! if it does occur, there is still a possibility that the zerofinder will work
     868             :         ! provided the overflowed quantity is replaced by a large number.
     869             : 
     870             :         ! Global variables.
     871             :         real(TKC)   , parameter     :: BASE = radix(0._TKC), EPS = epsilon(0._TKC), TIN = tiny(0._TKC), INF = huge(0._TKC)
     872             :         real(TKC)   , parameter     :: SINR = SIND(94._TKC), COSR = COSD(94._TKC) ! rotation by 94 degrees.
     873             :         real(TKC)   , parameter     :: MRE = 2._TKC * sqrt(2._TKC) * EPS ! error bound on complex multiplication.
     874             :         real(TKC)   , parameter     :: ARE = EPS ! error bound on complex addition.
     875             :         real(TKC)   , parameter     :: HALF_SQRT2 = 0.5_TKC * sqrt(2._TKC) ! cos(45d)
     876             :         complex(TKC), allocatable   :: h(:), qp(:), qh(:), sh(:), workspace(:)
     877             :         complex(TKC)                :: s, t, pv
     878             :         integer(IK)                 :: degree
     879             :         integer(IK)                 :: nn
     880             : 
     881             :         ! Local variables.
     882             :         complex(TKC)                :: temp
     883             :         real(TKC)   , parameter     :: HIGH = sqrt(INF), LOW = TIN / EPS, INV_LOG_BASE = 1._TKC / log(BASE)
     884             :         real(TKC)   , parameter     :: NEG_HALF_INV_LOG_BASE = -.5_TKC * INV_LOG_BASE
     885             :         real(TKC)                   :: xx, yy, xxx, bnd, max, min
     886             :         real(TKC)                   :: x, xm, f, dx, df, xni ! cauchy, noshft routines
     887             :         integer(IK)                 :: cnt1, cnt2, i, n, j, jj, nm1
     888             :         logical(LK)                 :: converged
     889             : 
     890          14 :         nn = size(coef, 1, IK)
     891          14 :         degree = nn - 1_IK
     892           5 :         xx = +HALF_SQRT2
     893           5 :         yy = -HALF_SQRT2
     894             : 
     895          14 :         CHECK_ASSERTION(__LINE__, 1_IK < nn, SK_"@setPolyRoot(): The condition `1 < size(coef)` must hold. size(coef) = "//getStr(nn))
     896          14 :         CHECK_ASSERTION(__LINE__, coef(degree) /= ZERO, SK_"@setPolyRoot(): The condition `coef(size(coef)) /= 0.` must hold. coef = "//getStr(coef))
     897          42 :         CHECK_ASSERTION(__LINE__, size(root, 1, IK) == degree, SK_"@setPolyRoot(): The condition `size(root) == size(coef) - 1` must hold. size(root), size(coef) - 1 = "//getStr([size(root, 1, IK), degree]))
     898             : 
     899             :         ! Algorithm fails if the leading coefficient is zero.
     900          14 :         if (coef(degree) == ZERO) then
     901           0 :             count = 0_IK
     902           0 :             return
     903             :         end if
     904             : 
     905             :         ! Allocate arrays.
     906             : #if     __GFORTRAN__
     907          14 :         if (allocated(workspace)) deallocate(workspace)
     908          14 :         if (allocated(qp)) deallocate(qp)
     909          14 :         if (allocated(qh)) deallocate(qh)
     910          14 :         if (allocated(sh)) deallocate(sh)
     911          14 :         if (allocated(h)) deallocate(h)
     912             : #endif
     913          14 :         allocate(h(nn), qp(nn), qh(nn), sh(nn), workspace(nn)) ! xxx this should be moved down once cleaning is complete.
     914             : 
     915             :         ! Extract any exact ZERO roots and set count = degree of remaining polynomial.
     916          14 :         do count = 1_IK, degree ! 10
     917          14 :             if (coef(count - 1) /= ZERO) exit
     918           0 :             root(count) = ZERO
     919          14 :             nn = nn - 1_IK
     920             :         end do
     921             : 
     922             :         ! Make a copy of the coefficients.
     923         155 :         do i = 1_IK, nn
     924         141 :             workspace(i) = coef(nn - i)
     925         155 :             sh(i)%re = GET_ABS(workspace(i)) ! modulus of coefficients of `p`.
     926             :         end do
     927             : 
     928             :         ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     929             :         ! Compute a scale factor to multiply the coefficients of the polynomial.
     930             :         ! The scaling is done to avoid overflow and to avoid undetected underflow interfering with the convergence criterion.
     931             :         ! The factor is a power of the BASE.
     932             : 
     933             :         ! Find largest and smallest moduli of coefficients.
     934           5 :         min = INF
     935           5 :         max = 0._TKC
     936         155 :         do i = 1_IK, nn
     937         141 :             if (sh(i)%re > max) max = sh(i)%re
     938         155 :             if (sh(i)%re /= 0._TKC .and. sh(i)%re < min) min = sh(i)%re
     939             :         end do
     940             : 
     941             :         ! Scale only if there are very large or very small components.
     942          14 :         if (LOW <= min .and. max <= HIGH) then
     943           5 :             bnd = 1._TKC
     944             :         else
     945           0 :             bnd = LOW / min
     946           0 :             if (bnd <= 1._TKC) then
     947           0 :                 bnd = BASE ** int((log(max) + log(min)) * NEG_HALF_INV_LOG_BASE + .5_TKC)
     948           0 :             elseif (max < INF / bnd) then
     949           0 :                 bnd = 1._TKC
     950             :             else
     951           0 :                 bnd = BASE ** int(log(bnd) * INV_LOG_BASE + .5_TKC)
     952             :             end if
     953           0 :             if (bnd /= 1._TKC) then
     954             :                 ! Scale the polynomial.
     955           0 :                 do i = 1_IK, nn
     956           0 :                     workspace(i) = bnd * workspace(i)
     957             :                 end do
     958             :             end if
     959             :         end if
     960             : 
     961             :         ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     962             : 
     963             :         ! Start the algorithm for one zero.
     964             :         loopIter: do ! 40
     965             : 
     966         127 :             if (nn <= 2) then
     967             :                 ! Calculate the final zero and return.
     968          14 :                 count = degree
     969          14 :                 root(degree) = GET_RATIO(-workspace(2), workspace(1))
     970          14 :                 return
     971             :             end if
     972             : 
     973             :             ! Calculate bnd, a lower bound on the modulus of the zeros.
     974         913 :             do i = 1, nn
     975         913 :                 sh(i)%re = GET_ABS(workspace(i)) ! hypot
     976             :             end do
     977             : 
     978             :             ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     979             :             ! call cauchy(nn, sh, bnd)
     980             :             ! Cauchy computes a lower bound on the moduli of the zeros of a polynomial -
     981             :             ! the real component of `sh` is the modulus of the coefficients.
     982             :             ! Compute upper estimate of bound.
     983         113 :             n = nn - 1_IK
     984         113 :             sh(nn)%re = -sh(nn)%re
     985         113 :             x = exp((log(-sh(nn)%re) - log(sh(1)%re)) / n)
     986         113 :             if (sh(n)%re /= 0._TKC) then
     987             :                 ! if newton step at the origin is better, use it.
     988         113 :                 xm = -sh(nn)%re / sh(n)%re
     989         113 :                 if (xm < x) x = xm
     990             :             end if
     991             :             ! Chop the interval (0,x) until `f <= 0`.
     992           0 :             do ! 10
     993          73 :                 xm = x * .1_TKC
     994          40 :                 f = sh(1)%re
     995         800 :                 do i = 2_IK, nn
     996         800 :                     f = f * xm + sh(i)%re
     997             :                 end do
     998         113 :                 if (f > 0._TKC) then
     999           0 :                     x = xm
    1000             :                     cycle ! 10
    1001             :                 end if
    1002             :                 exit
    1003             :             end do
    1004          40 :             dx = x
    1005             :             ! Do newton iteration until x converges to two decimal places.
    1006         329 :             do ! 30
    1007         442 :                 if (abs(dx / x) > .005_TKC) then
    1008         329 :                     sh(1)%im = sh(1)%re
    1009        2366 :                     do i = 2_IK, nn
    1010        2366 :                         sh(i)%im = sh(i - 1)%im * x + sh(i)%re
    1011             :                     end do
    1012         329 :                     f = sh(nn)%im
    1013         329 :                     df = sh(1)%im
    1014        2037 :                     do i = 2_IK, n
    1015        2037 :                         df = df * x + sh(i)%im
    1016             :                     end do
    1017         329 :                     dx = f / df
    1018         329 :                     x = x - dx
    1019             :                     cycle
    1020             :                 end if
    1021             :                 exit
    1022             :             end do
    1023          40 :             bnd = x
    1024             :             ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1025             : 
    1026             :             ! The outer loop to control two major passes with different sequences of shifts.
    1027         113 :             do cnt1 = 1_IK, 2_IK
    1028             :                 ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1029             :                 ! First stage calculation, no shift.
    1030             :                 ! Compute the derivative polynomial as the initial `h`
    1031             :                 ! polynomial and compute `l1` no-shift `h` polynomials.
    1032             :                 ! call noshft(5_IK)
    1033          33 :                 n = nn - 1_IK
    1034         113 :                 nm1 = n - 1_IK
    1035         800 :                 do i = 1_IK, n
    1036         687 :                     xni = nn - i
    1037         800 :                     h(i) = xni * workspace(i) / real(n, TKC)
    1038             :                 end do
    1039         678 :                 do jj = 1_IK, 5_IK
    1040         678 :                     if (GET_ABS(h(n)) > 10._TKC * EPS * GET_ABS(workspace(n))) then ! hypot
    1041         565 :                         t = GET_RATIO(-workspace(nn), h(n))
    1042        3435 :                         do i = 1, nm1
    1043        2870 :                             j = nn - i
    1044        2870 :                             temp = h(j - 1)
    1045        2870 :                             h(j)%re = t%re * temp%re - t%im * temp%im + workspace(j)%re
    1046        3435 :                             h(j)%im = t%re * temp%im + t%im * temp%re + workspace(j)%im
    1047             :                         end do
    1048         565 :                         h(1) = workspace(1)
    1049             :                     else
    1050             :                         ! If the constant term is essentially zero, shift `h` coefficients.
    1051           0 :                         do i = 1, nm1
    1052           0 :                             j = nn - i
    1053           0 :                             h(j) = h(j - 1)
    1054             :                         end do
    1055           0 :                         h(1) = ZERO
    1056             :                     end if
    1057             :                 end do
    1058             :                 ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1059             :                 ! Inner loop to select a shift.
    1060         115 :                 do cnt2 = 1_IK, 9_IK
    1061             :                     ! Shift is chosen with modulus `bnd` and amplitude rotated by 94 degrees from the previous shift.
    1062         115 :                     xxx = COSR * xx - SINR * yy
    1063         115 :                     yy = SINR * xx + COSR * yy
    1064          41 :                     xx = xxx
    1065         115 :                     s%re = bnd * xx
    1066         115 :                     s%im = bnd * yy
    1067             :                     ! Second stage calculation, fixed shift.
    1068         115 :                     count = degree - nn + 2_IK
    1069         115 :                     call fxshft(10_IK * cnt2, root(count), converged)
    1070         115 :                     if (converged) then
    1071             :                         ! The second stage jumps directly to the third stage iteration.
    1072             :                         ! If successful the zero is stored and the polynomial deflated.
    1073         113 :                         nn = nn - 1_IK
    1074         800 :                         do i = 1_IK, nn
    1075         800 :                             workspace(i) = qp(i)
    1076             :                         end do
    1077             :                         cycle loopIter ! 40
    1078             :                     end if
    1079             :                     ! if the iteration is unsuccessful another shift is chosen.
    1080             :                 end do
    1081             :                 ! if 9 shifts fail, the outer loop is repeated with another sequence of shifts.
    1082             :             end do
    1083             :             ! The root finder has failed on two major passes. Return empty handed.
    1084           0 :             count = count - 1_IK
    1085           0 :             return
    1086             :         end do loopIter
    1087             : 
    1088             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1089             : 
    1090             :     contains
    1091             : 
    1092             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1093             : 
    1094         230 :         subroutine fxshft(l2, z, converged)
    1095             :             ! Computes l2 fixed-shift h polynomials and tests for convergence.
    1096             :             ! Initiates a variable-shift iteration and returns with the approximate zero if successful.
    1097             :             ! l2 - limit of fixed shift steps.
    1098             :             ! z - the output approximate zero if `converged == .true._LK`.
    1099             :             ! converged  - logical indicating convergence of stage 3 iteration.
    1100             :             integer(IK) , intent(in)    :: l2
    1101             :             complex(TKC), intent(out)   :: z
    1102             :             logical(LK) , intent(out)   :: converged
    1103             :             complex(TKC)                :: ot, svs
    1104             :             logical(LK)                 :: test, pasd, bool
    1105             :             integer(LK)                 :: i, j, n
    1106         115 :             n = nn - 1_IK
    1107             :             ! Evaluate `p` at `s`.
    1108          82 :             call polyev(nn, s, workspace, qp, pv)
    1109             :             test = .true._LK
    1110             :             pasd = .false._LK
    1111             :             ! calculate first t = -p(s)/h(s).
    1112         115 :             call calct(bool)
    1113             :             ! main loop for one second stage step.
    1114         342 :             do j = 1_IK, l2
    1115         333 :                 ot = t
    1116             :                 ! Compute next `h` polynomial and new `t`.
    1117         333 :                 call nexth(bool)
    1118         333 :                 call calct(bool)
    1119         333 :                 z = s + t
    1120             :                 ! Test for convergence unless stage 3 has failed once or this is the last h polynomial.
    1121         342 :                 if (.not. (bool .or. .not. test .or. j == l2)) then
    1122         261 :                     if (GET_ABS(t - ot) < .5_TKC * GET_ABS(z)) then
    1123         232 :                         if (pasd) then
    1124             :                             ! The weak convergence test has been passed twice, start the third stage iteration,
    1125             :                             ! after saving the current h polynomial and shift.
    1126         806 :                             do i = 1, n
    1127         806 :                                 sh(i) = h(i)
    1128             :                             end do
    1129         115 :                             svs = s
    1130         115 :                             call vrshft(10_IK, z, converged)
    1131         115 :                             if (converged) return
    1132             :                             ! The iteration failed to converge. turn off testing and restore `h, s, pv, t`.
    1133             :                             test = .false._LK
    1134          70 :                             do i = 1_IK, n
    1135          70 :                                 h(i) = sh(i)
    1136             :                             end do
    1137           9 :                             s = svs
    1138           7 :                             call polyev(nn, s, workspace, qp, pv)
    1139           9 :                             call calct(bool)
    1140           9 :                             cycle
    1141             :                         end if
    1142             :                         pasd = .true._LK
    1143             :                     else
    1144             :                         pasd = .false._LK
    1145             :                     end if
    1146             :                 end if
    1147             :             end do
    1148             :             ! Attempt an iteration with final `h` polynomial from the second stage.
    1149           9 :             call vrshft(10_IK, z, converged)
    1150             :         end subroutine fxshft
    1151             : 
    1152             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1153             : 
    1154         124 :         subroutine vrshft(limss3, z, converged)
    1155             :             ! carries out the third stage iteration.
    1156             :             ! limss3:       limit of steps in stage 3.
    1157             :             ! z:            on entry contains the initial iterate, if the iteration converges it contains the final iterate on exit.
    1158             :             ! converged:    `.true.` if iteration converges.
    1159             :             integer(IK) , intent(in)        :: limss3
    1160             :             complex(TKC), intent(inout)     :: z
    1161             :             logical(LK) , intent(out)       :: converged
    1162             :             real(TKC)                       :: mp, ms, omp, relstp, r1, r2, tp
    1163             :             logical(LK)                     :: b, bool
    1164             :             integer(IK)                     :: i, j
    1165         124 :             converged = .false._LK
    1166             :             b = .false._LK
    1167         124 :             s = z
    1168             :             ! main loop for stage three.
    1169         483 :             do i = 1_IK, limss3
    1170             :                 ! Evaluate p at s and test for convergence.
    1171         397 :                 call polyev(nn, s, workspace, qp, pv)
    1172         482 :                 mp = GET_ABS(pv)
    1173         482 :                 ms = GET_ABS(s)
    1174         482 :                 if (mp <= 20._TKC * getErrHorner(nn, qp, ms, mp)) then
    1175             :                     ! Polynomial value is smaller in value than a bound on the error in evaluating p, terminate the iteration.
    1176         113 :                     converged = .true._LK
    1177         113 :                     z = s
    1178         123 :                     return
    1179             :                 end if
    1180         369 :                 if (i /= 1_IK) then
    1181         253 :                     if (.not. (b .or. mp < omp .or. relstp >= .05_TKC)) then
    1182             :                         ! Iteration has stalled. probably a cluster of zeros.
    1183             :                         ! Do 5 fixed shift steps into the cluster to force one zero to dominate.
    1184           3 :                         tp = relstp
    1185             :                         b = .true._LK
    1186           6 :                         if (relstp < EPS) tp = EPS
    1187           6 :                         r1 = sqrt(tp)
    1188           6 :                         r2 = s%re * (1._TKC + r1) - s%im * r1
    1189           6 :                         s%im = s%re * r1 + s%im * (1._TKC + r1)
    1190           6 :                         s%re = r2
    1191           5 :                         call polyev(nn, s, workspace, qp, pv)
    1192          36 :                         do j = 1_IK, 5_IK
    1193          30 :                             call calct(bool)
    1194          36 :                             call nexth(bool)
    1195             :                         end do
    1196           3 :                         omp = INF
    1197           3 :                         goto 20
    1198             :                     end if
    1199             :                     ! Exit if polynomial value increases significantly.
    1200         247 :                     if (omp < .1_TKC * mp) return
    1201             :                 end if
    1202         179 :                 omp = mp
    1203             :                 ! Calculate the next iterate.
    1204         359 :                 20 call calct(bool)
    1205         359 :                 call nexth(bool)
    1206         359 :                 call calct(bool)
    1207        1201 :                 if (.not. bool) then
    1208         359 :                     relstp = GET_ABS(t) / GET_ABS(s)
    1209         359 :                     s = s + t
    1210             :                 end if
    1211             :             end do
    1212             :         end subroutine vrshft
    1213             : 
    1214             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1215             : 
    1216        1205 :         subroutine calct(bool)
    1217             :             ! Computes  t = -p(s) / h(s).
    1218             :             ! bool: logical(LK) , set true if h(s) is essentially zero.
    1219             :             logical(LK) , intent(out)   :: bool
    1220             :             complex(TKC)                :: hv
    1221             :             integer(IK)                 :: n
    1222        1205 :             n = nn - 1_IK
    1223             :             ! Evaluate h(s).
    1224        1205 :             call polyev(n, s, h, qh, hv)
    1225        1205 :             bool = GET_ABS(hv) <= 10._TKC * ARE * GET_ABS(h(n))
    1226        1205 :             if (.not. bool) then
    1227        1205 :                 t = GET_RATIO(-pv, hv)
    1228        1205 :                 return
    1229             :             end if
    1230           0 :             t = ZERO
    1231             :         end subroutine calct
    1232             : 
    1233             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1234             : 
    1235         722 :         subroutine nexth(bool)
    1236             :             ! Compute the next shifted `h` polynomial.
    1237             :             ! bool: logical(LK) , if .true._LK h(s) is essentially zero
    1238             :             logical(LK) , intent(in)    :: bool
    1239             :             complex(TKC)                :: temp
    1240             :             integer(IK)                 :: j,n
    1241         722 :             n = nn - 1_IK
    1242         722 :             if (.not. bool) then
    1243        4210 :                 do j = 2_IK, n
    1244        3488 :                     temp = qh(j - 1)
    1245        3488 :                     h(j)%re = t%re * temp%re - t%im * temp%im + qp(j)%re
    1246        4210 :                     h(j)%im = t%re * temp%im + t%im * temp%re + qp(j)%im
    1247             :                 end do
    1248         722 :                 h(1) = qp(1)
    1249         722 :                 return
    1250             :             end if
    1251             :             ! If `h(s) == zero`, replace `h` with `qh`.
    1252           0 :             do j = 2_IK, n
    1253           0 :                 h(j) = qh(j - 1)
    1254             :             end do
    1255           0 :             h(1) = ZERO
    1256             :         end subroutine nexth
    1257             : 
    1258             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1259             : 
    1260        1817 :         pure subroutine polyev(nn, s, workspace, q, pv)
    1261             :             ! Evaluate a polynomial  p  at  s  by the horner recurrence placing the partial sums in q and the computed value in pv.
    1262             :             integer(IK) , intent(in)                    :: nn
    1263             :             complex(TKC), intent(in)                    :: s
    1264             :             complex(TKC), intent(in)    , contiguous    :: workspace(:)
    1265             :             complex(TKC), intent(out)   , contiguous    :: q(:)
    1266             :             complex(TKC), intent(out)                   :: pv
    1267             :             real(TKC)   :: tempo
    1268             :             integer(IK) :: i
    1269        1817 :             q(1) = workspace(1)
    1270        1817 :             pv = q(1)
    1271       11296 :             do i = 2_IK, nn
    1272        9479 :                 tempo = pv%re * s%re - pv%im * s%im + workspace(i)%re
    1273        9479 :                 pv%im = pv%re * s%im + pv%im * s%re + workspace(i)%im
    1274        9479 :                 pv%re = tempo
    1275       11296 :                 q(i) = pv
    1276             :             end do
    1277        1817 :         end subroutine polyev
    1278             : 
    1279             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1280             : 
    1281         482 :         pure function getErrHorner(nn, q, ms, mp) result(errHorner)
    1282             :             ! Bound the error in evaluating the polynomial by the horner recurrence.
    1283             :             ! q:    the partial sums.
    1284             :             ! ms:   modulus of the point.
    1285             :             ! mp:   modulus of polynomial value.
    1286             :             integer(IK) , intent(in)    :: nn
    1287             :             complex(TKC), intent(in)    :: q(:)
    1288             :             real(TKC)   , intent(in)    :: ms
    1289             :             real(TKC)   , intent(in)    :: mp
    1290             :             real(TKC)                   :: errHorner
    1291             :             real(TKC)                   :: e
    1292             :             integer                     :: i
    1293         482 :             e = GET_ABS(q(1)) * MRE / (ARE + MRE)
    1294        3805 :             do i = 1_IK, nn
    1295        3805 :                 e = e * ms + GET_ABS(q(i))
    1296             :             end do
    1297         482 :             errHorner = e * (ARE + MRE) - mp * MRE
    1298         482 :         end function
    1299             : 
    1300             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1301             : #elif   setPolyRoot_ENABLED && Jen_ENABLED && RK_CK_ENABLED
    1302             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1303             : 
    1304             :         ! Global variables.
    1305             : 
    1306             :         integer(IK)     , parameter     :: MAX_ITER = 30_IK
    1307             :         integer         , parameter     :: RKR = TKC ! SELECTED_REAL_KIND(int(precision(0._TKC) / 3.))
    1308             :         real(RKR)       , parameter     :: BASE = radix(0._RKR)
    1309             :         real(RKR)       , parameter     :: EPS = epsilon(0._TKC) ! important to ask for the `TKC` precision.
    1310             :         real(RKR)       , parameter     :: TIN = tiny(0._RKR)
    1311             :         real(RKR)       , parameter     :: INF = huge(0._RKR)
    1312             :         real(RKR)       , parameter     :: MRE = EPS ! error bound on complex multiplication.
    1313             :         real(RKR)       , parameter     :: ARE = EPS ! The error bound on `+` operation.
    1314             :         real(TKC)                       :: u, v, a, b, c, d, a1, a3, a7, e, f, g, h ! , a2, a6
    1315             :         real(TKC)       , allocatable   :: qp(:), k(:), qk(:), svk(:), workspace(:)
    1316             :         complex(TKC)                    :: s, sz, lz
    1317             :         integer(IK)                     :: n, nn
    1318             : 
    1319             :         ! Local variables.
    1320             : 
    1321             :         real(RKR)                       :: max, min, xx, yy, xxx, x, sc, bnd, xm, ff, df, dx
    1322             :         real(RKR)       , parameter     :: SINR = SIND(94._RKR), COSR = COSD(94._RKR) ! rotation by 94 degrees.
    1323             :         real(RKR)       , parameter     :: LOW = TIN / EPS
    1324             :         real(RKR)       , allocatable   :: pt(:)
    1325             :         real(TKC)       , allocatable   :: temp(:)
    1326             :         real(TKC)                       :: t, aa, bb, cc, factor
    1327             :         integer(IK)                     :: cnt, nz, i, j, jj, nm1
    1328             :         logical(LK)                     :: zerok, scalingEnabled
    1329             : 
    1330           9 :         nn = size(coef, 1, IK)
    1331           9 :         count = nn - 1_IK ! degree of the polynomial.
    1332           9 :         n = count
    1333             : 
    1334           9 :         CHECK_ASSERTION(__LINE__, 1_IK < nn, SK_"@setPolyRoot(): The condition `1 < size(coef)` must hold. size(coef) = "//getStr(nn))
    1335           9 :         CHECK_ASSERTION(__LINE__, coef(count) /= 0._TKC, SK_"@setPolyRoot(): The condition `coef(size(coef)) /= 0.` must hold. coef = "//getStr(coef))
    1336          27 :         CHECK_ASSERTION(__LINE__, size(root, 1, IK) == count, SK_"@setPolyRoot(): The condition `size(root) == size(coef) - 1` must hold. size(root), size(coef) - 1 = "//getStr([size(root, 1, IK), count]))
    1337             : 
    1338             :         ! Initialization of constants for shift rotation.
    1339           2 :         xx = sqrt(.5_RKR)
    1340           2 :         yy = -xx
    1341             : 
    1342             :         ! Algorithm fails if the leading coefficient is zero.
    1343           9 :         if (coef(count) == 0._TKC) then
    1344           0 :             count = 0_IK
    1345           0 :             return
    1346             :         end if
    1347             : 
    1348             :         ! Extract any exact ZERO roots and set count = degree of remaining polynomial.
    1349           9 :         do j = 1_IK, count
    1350           9 :             if (coef(j - 1) /= 0._TKC) exit
    1351           0 :             root(j) = (0._TKC, 0._TKC)
    1352           0 :             nn = nn - 1_IK
    1353           9 :             n = n - 1_IK
    1354             :             !count = count - 1_IK
    1355             :         end do
    1356             : 
    1357             :         ! bypass gfortran bug for heap allocations.
    1358             : #if     __GFORTRAN__
    1359           9 :         if (allocated(k))   deallocate(k)
    1360           9 :         if (allocated(pt))  deallocate(pt)
    1361           9 :         if (allocated(qp))  deallocate(qp)
    1362           9 :         if (allocated(qk))  deallocate(qk)
    1363           9 :         if (allocated(svk)) deallocate(svk)
    1364           9 :         if (allocated(temp)) deallocate(temp)
    1365           9 :         if (allocated(workspace)) deallocate(workspace)
    1366             : #endif
    1367           9 :         allocate(k(nn), pt(nn), qp(nn), qk(nn), svk(nn), temp(nn), workspace(nn))
    1368             : 
    1369             :         ! Make a copy of the coefficients.
    1370          76 :         do j = 1_IK, nn
    1371          76 :             workspace(j) = coef(nn - j)
    1372             :         end do
    1373             : 
    1374             :         !write(*,*) "nn, workspace", nn, workspace
    1375             : 
    1376             :         ! Start the algorithm for one zero.
    1377             :         loopIter: do ! 30
    1378             : 
    1379          44 :             if (n <= 2_IK) then
    1380           9 :                 if (n < 1_IK) return
    1381             :                 ! Compute the final zero or pair of zeros.
    1382           9 :                 if (n /= 2_IK) then
    1383           6 :                     root(count)%re = -workspace(2) / workspace(1)
    1384           6 :                     root(count)%im = 0._TKC
    1385           6 :                     return
    1386             :                 end if
    1387           3 :                 call quad(workspace(1), workspace(2), workspace(3), root(count - 1), root(count))
    1388           3 :                 return
    1389             :             end if
    1390             : 
    1391             :             ! Find largest and smallest moduli of coefficients.
    1392          10 :             max = 0._RKR
    1393          10 :             min = INF
    1394         269 :             do i = 1_IK, nn
    1395         234 :                 x = abs(real(workspace(i), RKR))
    1396         234 :                 if (x > max) max = x
    1397         269 :                 if (x /= 0._RKR .and. x < min) min = x
    1398             :             end do
    1399             : 
    1400             :             ! Scale if there are large or very small coefficients.
    1401             :             ! Computes a scale factor to multiply the coefficients of the polynomial.
    1402             :             ! The scaling is done to avoid overflow and to avoid undetected underflow interfering with the convergence criterion.
    1403             :             ! The factor is a power of the `BASE`.
    1404          35 :             sc = LOW / min
    1405          35 :             if (sc <= 1._RKR) then
    1406          35 :                 scalingEnabled = logical(max >= 10._RKR, LK)
    1407             :             else
    1408           0 :                 scalingEnabled = logical(INF / sc >= max, LK)
    1409             :             end if
    1410          35 :             if (scalingEnabled) then
    1411           8 :                 if (sc == 0._RKR) sc = TIN
    1412           8 :                 factor = real(BASE, TKC) ** int(log(sc) / log(BASE) + .5_RKR, IK)
    1413           8 :                 if (factor /= 1._TKC) then
    1414             :                     do concurrent(i = 1_IK : nn)
    1415          71 :                         workspace(i) = factor * workspace(i)
    1416             :                     end do
    1417             :                 end if
    1418             :             end if
    1419             : 
    1420             :             ! Compute lower bound on moduli of zeros.
    1421             :             do concurrent(i = 1_IK : nn)
    1422         269 :                 pt(i) = real(abs(workspace(i)), RKR)
    1423             :             end do
    1424          35 :             pt(nn) = -pt(nn)
    1425             : 
    1426             :             ! Compute upper estimate of bound.
    1427          35 :             x = exp((log(-pt(nn)) - log(pt(1))) / n)
    1428          35 :             if (pt(n) /= 0._RKR) then
    1429             :                 ! If newton step at the origin is better, use it.
    1430          35 :                 xm = -pt(nn) / pt(n)
    1431          35 :                 if (xm < x) x = xm
    1432             :             end if
    1433             : 
    1434             :             ! Chop the interval `(0, x)` until `ff <= 0`.
    1435           0 :             do
    1436          25 :                 xm = x * .1_RKR
    1437          10 :                 ff = pt(1)
    1438         234 :                 do i = 2_IK, nn
    1439         234 :                     ff = ff * xm + pt(i)
    1440             :                 end do
    1441          35 :                 if (ff <= 0._RKR) exit
    1442          25 :                 x = xm
    1443             :             end do
    1444          10 :             dx = x
    1445             : 
    1446             :             ! Do newton iteration until `x` converges to two decimal places.
    1447         118 :             do
    1448         153 :                 if (abs(dx / x) <= .005_RKR) exit
    1449          33 :                 ff = pt(1)
    1450          33 :                 df = ff
    1451         652 :                 do i = 2_IK, n
    1452         534 :                     ff = ff * x + pt(i)
    1453         652 :                     df = df * x + ff
    1454             :                 end do
    1455         118 :                 ff = ff * x + pt(nn)
    1456         118 :                 dx = ff / df
    1457         118 :                 x = x - dx
    1458             :             end do
    1459          10 :             bnd = x
    1460             : 
    1461             :             ! Compute the derivative as the initial `k` polynomial and do `5` steps with no shift.
    1462          35 :             nm1 = n - 1_IK
    1463         199 :             do i = 2_IK, n
    1464         199 :                 k(i) = (nn - i) * workspace(i) / n
    1465             :             end do
    1466          35 :             k(1) = workspace(1)
    1467          35 :             aa = workspace(nn)
    1468          35 :             bb = workspace(n)
    1469          35 :             zerok = logical(k(n) == 0._TKC, LK)
    1470         210 :             do jj = 1_IK, 5_IK
    1471         175 :                 cc = k(n)
    1472         210 :                 if (.not. zerok) then
    1473             :                     ! Use scaled form of recurrence if value of k at 0 is nonzero
    1474         175 :                     t = -aa / cc
    1475         995 :                     do i = 1_IK, nm1
    1476         820 :                         j = nn - i
    1477         995 :                         k(j) = t * k(j - 1) + workspace(j)
    1478             :                     end do
    1479         175 :                     k(1) = workspace(1)
    1480         175 :                     zerok = abs(k(n)) <= abs(bb) * EPS * 10._RKR
    1481             :                 else
    1482             :                     ! Use unscaled form of recurrence.
    1483           0 :                     do i = 1_IK, nm1
    1484           0 :                         j = nn - i
    1485           0 :                         k(j) = k(j - 1)
    1486             :                     end do
    1487           0 :                     k(1) = 0._TKC
    1488           0 :                     zerok = logical(k(n) == 0._TKC, LK)
    1489             :                 end if
    1490             :             end do
    1491             : 
    1492             :             ! Save k for restarts with new shifts.
    1493         234 :             temp(1 : n) = k(1 : n)
    1494             : 
    1495             :             ! Loop to select the quadratic corresponding to each new shift.
    1496          35 :             do cnt = 1_IK, MAX_ITER
    1497             :                 ! Quadratic corresponds to a double shift to a non-real point and niter complex conjugate.
    1498             :                 ! The point has modulus bnd and amplitude rotated by 94 degrees from the previous shift.
    1499          35 :                 xxx = COSR * xx - SINR * yy
    1500          35 :                 yy = SINR * xx + COSR * yy
    1501          10 :                 xx = xxx
    1502          35 :                 s%re = bnd * xx
    1503          35 :                 s%im = bnd * yy
    1504          35 :                 u = -2._TKC * s%re
    1505          35 :                 v = bnd
    1506             :                 ! Second stage calculation, fixed quadratic.
    1507          35 :                 call fxshfr(MAX_ITER * cnt, nz)
    1508          35 :                 if (nz /= 0_IK) then
    1509             :                     ! The second stage jumps directly to one of the third stage iterations and returns here if successful.
    1510             :                     ! Deflate the polynomial, store the zero or zeros and return to the main algorithm.
    1511          35 :                     j = count - n + 1_IK
    1512          35 :                     root(j) = sz
    1513             :                     !write(*,*) "j", j, count, n, nn, nz
    1514          35 :                     nn = nn - nz
    1515          35 :                     n = nn - 1_IK
    1516         223 :                     workspace(1 : nn) = qp(1 : nn)
    1517          35 :                     if (nz /= 1_IK) root(j + 1) = lz
    1518             :                     cycle loopIter
    1519             :                 end if
    1520             :                 ! If the iteration is unsuccessful another quadratic is chosen after restoring `k`.
    1521           0 :                 k(1 : nn) = temp(1 : nn)
    1522             :             end do
    1523             :             ! Return with failure if no convergence with `20` shifts.
    1524           0 :             count = count - n
    1525           0 :             return
    1526             :         end do loopIter
    1527             : 
    1528             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1529             : 
    1530             :     contains
    1531             : 
    1532             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1533             : 
    1534          70 :         subroutine fxshfr(l2, nz)
    1535             :             ! Compute up to `l2` fixed shift `k`-polynomials, testing for convergence in the linear or quadratic case.
    1536             :             ! Initiate one of the variable shift iterations and returns with the number of zeros found.
    1537             :             ! l2:   limit of fixed shift steps
    1538             :             ! nz:   number of zeros found
    1539             :             integer(IK) , intent(in)    :: l2
    1540             :             integer(IK) , intent(out)   :: nz
    1541             :             real(TKC)                   :: svu, svv, ui, vi, slocal
    1542             :             real(RKR)                   :: betas, betav, oss, ovv, ss, vv, ts, tv, ots, otv, tvv, tss
    1543             :             logical(LK)                 :: vpass, spass, vtry, stry
    1544             :             integer(IK)                 :: itype, j, iflag
    1545          35 :             nz = 0_IK
    1546          10 :             betav = .25_RKR
    1547          10 :             betas = .25_RKR
    1548          35 :             oss = real(s%re, RKR)
    1549          35 :             ovv = real(v, RKR)
    1550             :             ! Evaluate polynomial by synthetic division.
    1551             :             !write(*,*) "quadsd1, nn, u, v, workspace, qp, a, b", nn, u, v, workspace, qp, a, b
    1552          35 :             call quadsd(nn, u, v, workspace, qp, a, b)
    1553             :             !write(*,*) "quadsd2, nn, u, v, workspace, qp, a, b", nn, u, v, workspace, qp, a, b
    1554             :             !write(*,*) "calcsc1, itype", itype
    1555          35 :             call calcsc(itype)
    1556             :             !write(*,*) "calcsc2, itype", itype
    1557          84 :             do j = 1_IK, l2
    1558             :                 ! Compute the next `k` polynomial and estimate `v`.
    1559          84 :                 call nextk(itype)
    1560          84 :                 call calcsc(itype)
    1561          84 :                 call newest(itype, ui, vi)
    1562          84 :                 vv = real(vi, RKR)
    1563             :                 ! Estimate `s`.
    1564          23 :                 ss = 0._RKR
    1565          84 :                 if (k(n) /= 0._TKC) ss = real(-workspace(nn) / k(n), RKR)
    1566          23 :                 tv = 1._RKR
    1567          23 :                 ts = 1._RKR
    1568             :                 !write(*,*) "BLOCK: ", j, itype
    1569          84 :                 if (j /= 1_IK .and. itype /= 3_IK) then
    1570             :                     ! Compute relative measures of convergence of `s` and `v` sequences.
    1571          49 :                     if (vv /= 0._RKR) tv = abs((vv - ovv) / vv)
    1572          49 :                     if (ss /= 0._RKR) ts = abs((ss - oss) / ss)
    1573             :                     ! If decreasing, multiply two most recent convergence measures.
    1574          13 :                     tvv = 1._RKR
    1575          49 :                     if (tv < otv) tvv = tv * otv
    1576          13 :                     tss = 1._RKR
    1577          49 :                     if (ts < ots) tss = ts * ots
    1578             :                     ! Compare with convergence criteria.
    1579          49 :                     vpass = tvv < betav
    1580          49 :                     spass = tss < betas
    1581          49 :                     if (spass .or. vpass) then
    1582             :                         ! At least one sequence has passed the convergence test. Store variables before iterating.
    1583          37 :                         svu = u
    1584          37 :                         svv = v
    1585         242 :                         svk(1 : n) = k(1 : n)
    1586          37 :                         slocal = ss
    1587             :                         ! Choose iteration according to the fastest converging sequence.
    1588             :                         vtry = .false._LK
    1589             :                         stry = .false._LK
    1590          37 :                         if (spass .and. ((.not. vpass) .or. tss < tvv)) goto 40
    1591             :                         !write(*,*) "quadit1", ui, vi, nz
    1592          19 :                         20 call quadit(ui, vi, nz)
    1593             :                         !write(*,*) "quadit2", ui, vi, nz
    1594          43 :                         if (nz > 0_IK) return
    1595             :                         ! Quadratic iteration has failed. flag that it has been tried and decrease the convergence criterion.
    1596             :                         vtry = .true._LK
    1597           8 :                         betav = betav * .25_RKR
    1598             :                         ! Try linear iteration if it has not been tried and the `s` sequence is converging.
    1599           8 :                         if (stry .or. (.not. spass)) goto 50
    1600          48 :                         k(1 : n) = svk(1 : n)
    1601          25 :                         40 call realit(slocal, nz, iflag)
    1602          25 :                         if (nz > 0_IK) return
    1603             :                         ! Linear iteration has failed.  flag that it has been tried and decrease the convergence criterion
    1604             :                         stry = .true.
    1605           1 :                         betas = betas * .25_RKR
    1606           1 :                         if (iflag /= 0_IK) then
    1607             :                             ! if linear iteration signals an almost double real zero attempt quadratic interation
    1608           0 :                             ui = -(slocal + slocal)
    1609           0 :                             vi = slocal * slocal
    1610           0 :                             goto 20
    1611             :                         end if
    1612             :                         ! restore variables
    1613           3 :                         50 u = svu
    1614           3 :                         v = svv
    1615          12 :                         k(1 : n) = svk(1 : n)
    1616             :                         ! try quadratic iteration if it has not been tried and the v sequence is converging
    1617           3 :                         if (vpass .and. .not. vtry) goto 20
    1618             :                         ! recompute qp and scalar values to continue the second stage
    1619           2 :                         call quadsd(nn, u, v, workspace, qp, a, b)
    1620           2 :                         call calcsc(itype)
    1621             :                     end if
    1622             :                 end if
    1623          13 :                 ovv = vv
    1624          13 :                 oss = ss
    1625          13 :                 otv = tv
    1626          97 :                 ots = ts
    1627             :             end do
    1628             :         end subroutine fxshfr
    1629             : 
    1630             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1631             : 
    1632          19 :         subroutine quadit(uu, vv, nz)
    1633             :             ! Variable-shift `k`-polynomial iteration for a quadratic factor, converges only if the zeros are equimodular or nearly so.
    1634             :             ! uu, vv:   coefficients of starting quadratic
    1635             :             ! nz:       number of zero found
    1636             :             real(TKC)   , intent(in)    :: uu
    1637             :             real(TKC)   , intent(in)    :: vv
    1638             :             integer(IK) , intent(out)   :: nz
    1639             :             real(TKC)                   :: ui, vi
    1640             :             real(RKR)                   :: mp, omp, ee, relstp, t, zm
    1641             :             integer(IK)                 :: itype, i, j
    1642             :             logical(LK)                 :: tried
    1643          19 :             nz = 0_IK
    1644             :             tried = .false._LK
    1645          19 :             u = uu
    1646          19 :             v = vv
    1647             :             j = 0_IK
    1648             :             ! main loop
    1649          43 :             10 call quad(1._TKC, u, v, sz, lz)
    1650             :             ! Return if roots of the quadratic are real and not close to multiple or nearly equal and  of opposite sign.
    1651          43 :             if (abs(abs(sz%re) - abs(lz%re)) > .01_TKC * abs(lz%re)) return
    1652             :             ! Evaluate polynomial by quadratic synthetic division.
    1653          35 :             call quadsd(nn, u, v, workspace, qp, a, b)
    1654          35 :             mp = real(abs(a - sz%re * b) + abs(sz%im * b), RKR)
    1655             :             ! Compute a rigorous  bound on the rounding error in evaluating P (`workspace`).
    1656          35 :             zm = sqrt(abs(real(v, RKR)))
    1657          35 :             ee = 2._RKR * abs(real(qp(1), RKR))
    1658          10 :             t = real(-sz%re * b, RKR)
    1659         139 :             do i = 2_IK, n
    1660         139 :                 ee = ee * zm + abs(real(qp(i), RKR))
    1661             :             end do
    1662          35 :             ee = ee * zm + abs(real(a, RKR) + t)
    1663          35 :             ee = (5._RKR * MRE + 4._RKR * ARE) * ee - (5._RKR * MRE + 2._RKR * ARE) * (abs(real(a, RKR) + t) + abs(real(b, RKR)) * zm) + 2._RKR * ARE * abs(t)
    1664             :             ! Iteration has converged sufficiently if the polynomial value is less than 20 times this bound.
    1665          35 :             if (mp <= MAX_ITER * ee) then
    1666          11 :                 nz = 2_IK
    1667          11 :                 return
    1668             :             end if
    1669          24 :             j = j + 1_IK
    1670             :             ! Stop iteration after 20 steps.
    1671          24 :             if (j > MAX_ITER) return
    1672          24 :             if (j >= 2_IK) then
    1673          14 :                 if (.not. (relstp > .01_RKR .or. mp < omp .or. tried)) then
    1674             :                     ! A cluster appears to be stalling the convergence. Five fixed shift steps are taken with a `u, v` close to the cluster.
    1675           0 :                     if (relstp < EPS) relstp = EPS
    1676           0 :                     relstp = sqrt(relstp)
    1677           0 :                     u = u - u * relstp
    1678           0 :                     v = v + v * relstp
    1679           0 :                     call quadsd(nn, u, v, workspace, qp, a, b)
    1680           0 :                     do i = 1_IK, 5_IK
    1681           0 :                         call calcsc(itype)
    1682           0 :                         call nextk(itype)
    1683             :                     end do
    1684             :                     tried = .true._LK
    1685             :                     j = 0_IK
    1686             :                 end if
    1687             :             end if
    1688           8 :             omp = mp
    1689             :             ! Calculate next k polynomial and new u and v.
    1690          24 :             call calcsc(itype)
    1691          24 :             call nextk(itype)
    1692          24 :             call calcsc(itype)
    1693          24 :             call newest(itype, ui, vi)
    1694             :             ! If vi is zero the iteration is not converging.
    1695          24 :             if (vi == 0._TKC) return
    1696          24 :             relstp = real(abs((vi - v) / vi), RKR)
    1697          24 :             u = ui
    1698          24 :             v = vi
    1699          24 :             goto 10
    1700          48 :         end subroutine quadit
    1701             : 
    1702             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1703             : 
    1704          25 :         subroutine realit(sss,nz,iflag)
    1705             :             ! Variable-shift `h` polynomial iteration for a real zero.
    1706             :             ! sss  : starting iterate.
    1707             :             ! nz   : number of zero found.
    1708             :             ! iflag: flag to indicate a pair of zeros near real axis.
    1709             :             real(TKC)   , intent(inout) :: sss
    1710             :             integer(IK) , intent(out)   :: nz, iflag
    1711             :             real(TKC)                   :: pv, kv, t, s
    1712             :             real(RKR)                   :: ms, mp, omp, ee
    1713             :             integer(IK)                 :: i, j
    1714          25 :             nz = 0_IK
    1715          25 :             s = sss
    1716          25 :             iflag = 0_IK
    1717             :             j = 0_IK
    1718             :             ! main loop
    1719          76 :             do ! 10
    1720         101 :                 pv = workspace(1)
    1721             :                 ! Evaluate P (`workspace`) at s.
    1722         101 :                 qp(1) = pv
    1723         688 :                 do i = 2_IK, nn
    1724         587 :                     pv = pv * s + workspace(i)
    1725         688 :                     qp(i) = pv
    1726             :                 end do
    1727         101 :                 mp = real(abs(pv), RKR)
    1728             :                 !write(*,*) "workspace", workspace
    1729             :                 !write(*,*) "mp, pv, abs(pv)", mp, pv, abs(pv)
    1730             :                 ! Compute a rigorous bound on the error in evaluating P (`workspace`).
    1731         101 :                 ms = abs(real(s, RKR))
    1732         101 :                 ee = (MRE / (ARE + MRE)) * abs(real(qp(1), RKR))
    1733         688 :                 do i = 2_IK, nn
    1734         688 :                     ee = ee * ms + abs(real(qp(i), RKR))
    1735             :                 end do
    1736             :                 ! Iteration has converged sufficiently if the polynomial value is less than 20 times this bound.
    1737         101 :                 if (mp <= MAX_ITER * ((ARE + MRE) * ee - MRE * mp)) then
    1738          24 :                     sz%re = s
    1739          24 :                     sz%im = 0._TKC
    1740          24 :                     nz = 1_IK
    1741          24 :                     return
    1742             :                 end if
    1743          77 :                 j = j + 1_IK
    1744             :                 ! Stop iteration after `10` steps.
    1745          77 :                 if (j > 10_IK) return
    1746          76 :                 if (j >= 2_IK) then
    1747          52 :                     if (abs(t) <= .001_TKC * abs(s - t) .and. mp > omp) then
    1748             :                         ! A cluster of zeros near the real axis has been encountered, return with iflag set to initiate a quadratic iteration.
    1749           0 :                         iflag = 1_IK
    1750           0 :                         sss = s
    1751           0 :                         return
    1752             :                     end if
    1753             :                 end if
    1754             :                 ! Return if the polynomial value has increased significantly.
    1755          33 :                 omp = mp
    1756             :                 ! Compute t, the next polynomial, and the new iterate.
    1757          76 :                 kv = k(1)
    1758          76 :                 qk(1) = kv
    1759         428 :                 do i = 2_IK, n
    1760         352 :                     kv = kv * s + k(i)
    1761         428 :                     qk(i) = kv
    1762             :                 end do
    1763          76 :                 if (abs(kv) > abs(k(n)) * EPS * 10._TKC) then
    1764             :                     ! Use the scaled form of the recurrence if the value of k at s is nonzero.
    1765          76 :                     t = -pv / kv
    1766          76 :                     k(1) = qp(1)
    1767         428 :                     do i = 2_IK, n
    1768         428 :                         k(i) = t * qk(i - 1) + qp(i)
    1769             :                     end do
    1770             :                 else
    1771             :                     ! Use unscaled form.
    1772           0 :                     k(1) = 0._TKC
    1773           0 :                     do i = 2_IK, n
    1774           0 :                         k(i) = qk(i - 1)
    1775             :                     end do
    1776             :                 end if
    1777          76 :                 kv = k(1)
    1778         428 :                 do i = 2_IK, n
    1779         428 :                     kv = kv * s + k(i)
    1780             :                 end do
    1781          33 :                 t = 0._TKC
    1782          76 :                 if (abs(kv) > abs(k(n)) * EPS * 10._TKC) t = -pv / kv
    1783          76 :                 s = s + t
    1784             :             end do ! goto 10
    1785             :         end subroutine realit
    1786             : 
    1787             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1788             : 
    1789         169 :         subroutine calcsc(itype) ! checked
    1790             :             ! Compute scalar quantities need for the next `k` polynomial and new estimates of the quadratic coefficients.
    1791             :             ! itype: integer variable that indicates how the calculations are normalized to avoid overflow.
    1792             :             integer(IK), intent(out) :: itype
    1793             :             ! Synthetic division of k by the quadratic 1, u, v.
    1794         169 :             call quadsd(n, u, v, k, qk, c, d)
    1795         169 :             if (abs(c) <= abs(k(n)) * EPS * 100._TKC) then
    1796           0 :                 if (abs(d) <= abs(k(n - 1)) * EPS * 100._TKC) then
    1797           0 :                     itype = 3_IK ! Indicates the quadratic is almost a factor of `k`.
    1798           0 :                     return
    1799             :                 end if
    1800             :             end if
    1801         169 :             if (abs(d) >= abs(c)) then
    1802          80 :                 itype = 2_IK ! Indicates that all formulas are divided by `d`.
    1803          80 :                 e = a / d
    1804          80 :                 f = c / d
    1805          80 :                 g = u * b
    1806          80 :                 h = v * b
    1807          80 :                 a3 = (a + g) * e + h * (b / d)
    1808          80 :                 a1 = b * f - a
    1809          80 :                 a7 = (f + u) * a + h
    1810          80 :                 return
    1811             :             end if
    1812          89 :             itype = 1_IK ! Indicates that all formulas are divided by `c`.
    1813          89 :             e = a / c
    1814          89 :             f = d / c
    1815          89 :             g = u * e
    1816          89 :             h = v * b
    1817          89 :             a3 = a * e + (h / c + g) * b
    1818          89 :             a1 = b - a * (d / c)
    1819          89 :             a7 = a + g * d + h * f
    1820          89 :             return
    1821             :         end subroutine calcsc
    1822             : 
    1823             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1824             : 
    1825         108 :         subroutine nextk(itype) ! checked
    1826             :             ! Compute the next `k` polynomials using scalars computed in `calcsc()`.
    1827             :             integer(IK) , intent(in)    :: itype
    1828             :             real(TKC)                   :: temp
    1829             :             integer(IK)                 :: i
    1830         108 :             if (itype /= 3_IK) then
    1831         108 :                 temp = a
    1832         108 :                 if (itype == 1_IK) temp = b
    1833         108 :                 if (abs(a1) <= abs(temp) * EPS * 10._TKC) then
    1834             :                     ! If `a1` is nearly zero then use a special form of the recurrence.
    1835           0 :                     k(1) = 0._TKC
    1836           0 :                     k(2) = -a7 * qp(1)
    1837           0 :                     do i = 3_IK, n
    1838           0 :                         k(i) = a3 * qk(i - 2) - a7 * qp(i - 1)
    1839             :                     end do
    1840             :                     return
    1841             :                 end if
    1842             :                 ! Use scaled form of the recurrence.
    1843         108 :                 a7 = a7 / a1
    1844         108 :                 a3 = a3 / a1
    1845         108 :                 k(1) = qp(1)
    1846         108 :                 k(2) = qp(2) - a7 * qp(1)
    1847         452 :                 do i = 3_IK, n
    1848         452 :                     k(i) = a3 * qk(i - 2) - a7 * qp(i - 1) + qp(i)
    1849             :                 end do
    1850             :                 return
    1851             :             end if
    1852             :             ! Use unscaled form of the recurrence if itype is 3.
    1853           0 :             k(1) = 0._TKC
    1854           0 :             k(2) = 0._TKC
    1855           0 :             do i = 3_IK, n
    1856           0 :                 k(i) = qk(i - 2)
    1857             :             end do
    1858             :         end subroutine nextk
    1859             : 
    1860             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1861             : 
    1862         108 :         subroutine newest(itype, uu, vv)
    1863             :             ! Compute new estimates of the quadratic coefficients using the scalars computed in calcsc.
    1864             :             integer(IK) , intent(in)    :: itype
    1865             :             real(TKC)   , intent(out)   :: uu
    1866             :             real(TKC)   , intent(out)   :: vv
    1867             :             real(TKC)                   :: a4, a5, b1, b2, c1, c2, c3, c4, temp
    1868             :             ! Use formulas appropriate to setting of itype.
    1869         108 :             if (itype /= 3_IK) then
    1870         108 :                 if (itype /= 2_IK) then
    1871          54 :                     a4 = a + u * b + h * f
    1872          54 :                     a5 = c + (u + v * f) * d
    1873             :                 else
    1874          54 :                     a4 = (a + g) * f + h
    1875          54 :                     a5 = (f + u) * c + v * d
    1876             :                 end if
    1877             :                 ! Evaluate new quadratic coefficients.
    1878         108 :                 b1 = -k(n) / workspace(nn)
    1879         108 :                 b2 = -(k(n - 1) + b1 * workspace(n)) / workspace(nn)
    1880         108 :                 c1 = v * b2 * a1
    1881         108 :                 c2 = b1 * a7
    1882         108 :                 c3 = b1 * b1 * a3
    1883         108 :                 c4 = c1 - c2 - c3
    1884         108 :                 temp = a5 + b1 * a4 - c4
    1885         108 :                 if (temp /= 0._TKC) then
    1886         108 :                     uu = u - (u * (c3 + c2) + v * (b1 * a1 + b2 * a7)) / temp
    1887         108 :                     vv = v * (1._TKC + c4 / temp)
    1888         108 :                     return
    1889             :                 end if
    1890             :             end if
    1891             :             ! If itype = 3 the quadratic is zeroed.
    1892           0 :             uu = 0._TKC
    1893           0 :             vv = 0._TKC
    1894             :         end subroutine newest
    1895             : 
    1896             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1897             : 
    1898         241 :         pure subroutine quadsd(nn, u, v, workspace, q, a, b)
    1899             :             ! Divide P (`workspace`) by the quadratic `1, u, v` placing the quotient in `q` and the remainder in `a, b`.
    1900             :             integer(IK) , intent(in)    :: nn
    1901             :             real(TKC)   , intent(in)    :: u, v, workspace(nn)
    1902             :             real(TKC)   , intent(out)   :: q(nn), a, b
    1903             :             real(TKC)                   :: c
    1904             :             integer(IK)                 :: i
    1905         241 :             b = workspace(1)
    1906         241 :             q(1) = b
    1907         241 :             a = workspace(2) - u * b
    1908         241 :             q(2) = a
    1909        1036 :             do i = 3_IK, nn
    1910         795 :                 c = workspace(i) - u * a - v * b
    1911         795 :                 q(i) = c
    1912         795 :                 b = a
    1913        1036 :                 a = c
    1914             :             end do
    1915             :         end subroutine quadsd
    1916             : 
    1917             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1918             : 
    1919          46 :         pure subroutine quad(a, b1, c, sroot, lroot)
    1920             :             ! Compute the zeros of the quadratic `a * z**2 + b1 * z + c`.
    1921             :             ! The quadratic formula, modified to avoid overflow, is used to find the larger zero if the zeros are real and both zeros are complex.
    1922             :             ! The smaller real zero is found directly from the product of the zeros `c / a`.
    1923             :             real(TKC)   , intent(in)    :: a, b1, c
    1924             :             complex(TKC), intent(out)   :: sroot, lroot
    1925             :             complex(TKC), parameter     :: ZERO = (0._TKC, 0._TKC)
    1926             :             real(TKC)                   :: b, d, e
    1927          46 :             if (a == 0._TKC) then
    1928           0 :                 lroot = ZERO
    1929           0 :                 sroot = ZERO
    1930           0 :                 if (b1 /= 0._TKC) sroot%re = -c / b1
    1931           0 :                 return
    1932             :             end if
    1933          46 :             if (c == 0._TKC) then
    1934           0 :                 lroot%re = -b1 / a
    1935           0 :                 lroot%im = 0._TKC
    1936           0 :                 sroot = ZERO
    1937           0 :                 return
    1938             :             end if
    1939             :             ! Compute discriminant avoiding overflow.
    1940          46 :             b = b1 * .5_TKC
    1941          46 :             if (abs(b) >= abs(c)) then
    1942           0 :                 e = 1._TKC - (a / b) * (c / b)
    1943           0 :                 d = sqrt(abs(e)) * abs(b)
    1944             :             else
    1945          13 :                 e = a
    1946          46 :                 if (c < 0._TKC) e = -a
    1947          46 :                 e = b * (b / abs(c)) - e
    1948          46 :                 d = sqrt(abs(e)) * sqrt(abs(c))
    1949             :             end if
    1950          46 :             if (e >= 0._TKC) then
    1951             :                 ! Real zeros.
    1952          11 :                 if (b >= 0._TKC) d = -d
    1953          11 :                 lroot%re = (-b + d) / a
    1954          11 :                 lroot%im = 0._TKC
    1955          11 :                 sroot = ZERO
    1956          11 :                 if (lroot%re /= 0._TKC) sroot%re = (c / lroot%re) / a
    1957          11 :                 return
    1958             :             end if
    1959             :             ! Complex conjugate zeros.
    1960          35 :             sroot%re = -b / a
    1961          35 :             lroot%re = sroot%re
    1962          35 :             sroot%im = abs(d / a)
    1963          35 :             lroot%im = -sroot%im
    1964             :         end subroutine
    1965             : 
    1966             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1967             : #elif   setPolyRoot_ENABLED && Lag_ENABLED
    1968             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1969             : 
    1970             :         integer(IK) :: ideg, jdeg, niter, degree
    1971             :         real(TKC), parameter :: EPS = 2 * epsilon(0._TKC) ! the estimated fractional roundoff error.
    1972          23 :         complex(TKC) :: temp, b, c, workspace(size(coef, 1, IK))
    1973          23 :         degree = size(coef, 1, IK) - 1_IK
    1974          23 :         CHECK_ASSERTION(__LINE__, 0_IK < degree, SK_"@setPolyRoot(): The condition `1 < size(coef)` must hold. size(coef) = "//getStr(size(coef, 1, IK)))
    1975          23 :         CHECK_ASSERTION(__LINE__, coef(degree) /= ZERO, SK_"@setPolyRoot(): The condition `coef(size(coef)) /= 0.` must hold. coef = "//getStr(coef))
    1976          69 :         CHECK_ASSERTION(__LINE__, size(root, 1, IK) == degree, SK_"@setPolyRoot(): The condition `size(root) == size(coef) - 1` must hold. size(root), size(coef) - 1 = "//getStr([size(root, 1, IK), degree + 1_IK]))
    1977          23 :         count = 0_IK
    1978         231 :         workspace = coef
    1979          23 :         if (degree < 1_IK) return
    1980         208 :         do ideg = degree, 1_IK, -1_IK
    1981         185 :             temp = ZERO
    1982         185 :             call setPolyRootPolished(temp, niter, workspace)
    1983         208 :             if (0_IK < niter) then
    1984         185 :                 if (abs(temp%im) <= 2._TKC * EPS**2 * abs(temp%re)) temp%im = 0._TKC
    1985         185 :                 count = count + 1_IK
    1986         185 :                 root(count) = temp
    1987             :                 ! deflate.
    1988         185 :                 b = workspace(ideg + 1)
    1989        1132 :                 do jdeg = ideg, 1_IK, -1_IK
    1990         947 :                     c = workspace(jdeg)
    1991         947 :                     workspace(jdeg) = b
    1992        1132 :                     b = temp * b + c
    1993             :                 end do
    1994             :             else
    1995             :                 exit
    1996             :             end if
    1997             :         end do
    1998             :         ! Polish the roots using the un-deflated coefficients.
    1999             :         ideg = 0_IK
    2000             :         do
    2001         208 :             ideg = ideg + 1_IK
    2002         208 :             if (count < ideg) exit
    2003         185 :             call setPolyRootPolished(root(ideg), niter, coef)
    2004         185 :             if (0_IK < niter) cycle
    2005           0 :             count = count - 1_IK
    2006         208 :             root(ideg : count) = root(ideg + 1 : count + 1)
    2007             :         end do
    2008             :         ! Sort roots by their real parts by straight insertion.
    2009             :         !do jdeg = 2_IK, degree
    2010             :         !    x = root(jdeg)
    2011             :         !    do ideg = jdeg - 1, 1, -1
    2012             :         !        if(root(ideg)%re < x%re) exit
    2013             :         !        root(ideg + 1) = root(ideg)
    2014             :         !    end do
    2015             :         !    root(ideg + 1) = x
    2016             :         !end do
    2017             : 
    2018             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2019             : #elif   setPolyRootPolished_ENABLED && Lag_ENABLED && RK_RK_ENABLED
    2020             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2021             : 
    2022             :         complex(TKC) :: croot
    2023           0 :         croot = root
    2024           0 :         call setPolyRootPolished(croot, niter, coef)
    2025           0 :         root = croot%re
    2026             : 
    2027             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2028             : #elif   setPolyRootPolished_ENABLED && Lag_ENABLED && (CK_CK_ENABLED || RK_CK_ENABLED)
    2029             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2030             : 
    2031             :         ! Given the complex polynomial coefficients `coef(1 : degree + 1)` of the polynomial in increasing order,
    2032             :         ! a complex root `x`, this routine improves `x` by the Laguerre method until it converges,
    2033             :         ! within the achievable roundoff limit, to a root of the given polynomial.<br>
    2034             :         ! The number of iterations taken is returned as `niter`.<br>
    2035             :         ! Break (rare) limit cycles with different fractional values once every `nstep` steps, for `nitermax` total allowed iterations.<br>
    2036             :         real(TKC), parameter :: EPS = 10_IK * epsilon(0._TKC) ! the estimated fractional roundoff error.
    2037             :         real(TKC), parameter :: fraction(8) = [.5_TKC, .25_TKC, .75_TKC, .13_TKC, .38_TKC, .62_TKC, .88_TKC, 1._TKC] ! Fractions used to break a limit cycle.
    2038             :         integer(IK) , parameter :: nstep = 10, nitermax = size(fraction, 1, IK) * nstep * 10000 ! amir: Extra 10000 was added to allow convergence for extremely awkward coefficients.
    2039             :         complex(TKC) :: droot, rootnew, der0, der1, der2, der12, der12sq, hterm, dterm, denom1, denom2
    2040             :         real(TKC) :: absroot, absdenom1, absdenom2, relerr
    2041             :         integer(IK) :: degree, id, ifrac, counter
    2042         376 :         degree = size(coef, 1, IK) - 1
    2043         376 :         CHECK_ASSERTION(__LINE__, 0_IK < degree, SK_"@setPolyRootPolished(): The condition `1 < size(coef)` must hold. size(coef) = "//getStr(size(coef, 1, IK)))
    2044             :         counter = 0_IK
    2045             :         ifrac = 0_IK
    2046         376 :         niter = 0_IK
    2047         376 :         if (degree < 1_IK) return
    2048             :         do
    2049      654938 :             niter = niter + 1_IK
    2050      654938 :             der2 = coef(degree)
    2051      654938 :             relerr = abs(der2)
    2052      654256 :             der0 = ZERO
    2053      654256 :             der1 = ZERO
    2054      654938 :             absroot = abs(root)
    2055     8507162 :             do id = degree - 1, 0, -1
    2056     7852224 :                 der0 = root * der0 + der1
    2057     7852224 :                 der1 = root * der1 + der2
    2058     7852224 :                 der2 = root * der2 + coef(id)
    2059     8507162 :                 relerr = abs(der2) + absroot * relerr
    2060             :             end do
    2061      654938 :             relerr = EPS * relerr
    2062      654938 :             if(abs(der2) <= relerr) return
    2063             :             ! Use the Laguerre method.
    2064      654562 :             der12 = der1 / der2
    2065      654562 :             der12sq = der12 * der12
    2066      654562 :             hterm = der12sq - 2 * der0 / der2
    2067      654562 :             dterm = sqrt((degree - 1) * (degree * hterm - der12sq))
    2068      654562 :             denom1 = der12 + dterm
    2069      654562 :             denom2 = der12 - dterm
    2070      654562 :             absdenom1 = abs(denom1)
    2071      654562 :             absdenom2 = abs(denom2)
    2072      654562 :             if(absdenom1 < absdenom2) then
    2073      215062 :                 absdenom1 = absdenom2
    2074      326986 :                 denom1 = denom2
    2075             :             end if
    2076      654562 :             if (absdenom1 /= 0._TKC) then
    2077      654546 :                 droot = degree / denom1
    2078             :             else
    2079          16 :                 droot = exp(cmplx(log(1._TKC + absroot), real(niter, TKC), TKC))
    2080             :             endif
    2081      654562 :             rootnew = root - droot
    2082      654562 :             if(root == rootnew) return
    2083      654562 :             counter = counter + 1
    2084      654562 :             if (counter /= nstep) then
    2085      589247 :                 root = rootnew
    2086             :             else
    2087             :                 counter = 0_IK
    2088       65315 :                 ifrac = ifrac + 1_IK
    2089       65315 :                 root = root - droot * fraction(ifrac)
    2090       65315 :                 if (ifrac == size(fraction)) ifrac = 0
    2091             :             end if
    2092      654562 :             if (niter == nitermax) exit
    2093             :         end do
    2094           0 :         niter = -niter
    2095             : 
    2096             : #else
    2097             :         !%%%%%%%%%%%%%%%%%%%%%%%%
    2098             : #error  "Unrecognized interface."
    2099             :         !%%%%%%%%%%%%%%%%%%%%%%%%
    2100             : #endif
    2101             : #undef  TYPE_KIND
    2102             : #undef  GET_RATIO
    2103             : #undef  GET_ABS
    2104             : #undef  COSD
    2105             : #undef  SIND

ParaMonte: Parallel Monte Carlo and Machine Learning Library 
The Computational Data Science Lab
© Copyright 2012 - 2024