#:include "common.fypp" #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES module stdlib_linalg_lapack_aux use stdlib_linalg_constants use stdlib_linalg_blas use ieee_arithmetic, only: ieee_support_inf, ieee_support_nan implicit none private public :: sp,dp,qp,lk,ilp,ilp64 #:for ik,it,ii in LINALG_INT_KINDS_TYPES public :: stdlib${ii}$_chla_transtype public :: stdlib${ii}$_ieeeck public :: stdlib${ii}$_iladiag public :: stdlib${ii}$_ilaenv public :: stdlib${ii}$_ilaenv2stage public :: stdlib${ii}$_ilaprec public :: stdlib${ii}$_ilatrans public :: stdlib${ii}$_ilauplo public :: stdlib${ii}$_iparam2stage public :: stdlib${ii}$_iparmq public :: stdlib${ii}$_lsamen public :: stdlib${ii}$_xerbla public :: stdlib${ii}$_xerbla_array #:for rk,rt,ri in REAL_KINDS_TYPES public :: stdlib${ii}$_${ri}$roundup_lwork #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES public :: stdlib${ii}$_i${ci}$max1 #:endfor #:for rk,rt,ri in RC_KINDS_TYPES public :: stdlib${ii}$_ila${ri}$lc public :: stdlib${ii}$_ila${ri}$lr #:endfor #:endfor #:for rk,rt,ri in RC_KINDS_TYPES public :: stdlib_select_${ri}$ public :: stdlib_selctg_${ri}$ #:endfor ! SELCTG is a LOGICAL FUNCTION of three DOUBLE PRECISION arguments ! used to select eigenvalues to sort to the top left of the Schur form. ! An eigenvalue (ALPHAR(j)+ALPHAI(j))/BETA(j) is selected if SELCTG is true, i.e., abstract interface #:for rk,rt,ri in REAL_KINDS_TYPES pure logical(lk) function stdlib_selctg_${ri}$(alphar,alphai,beta) import ${rk}$,lk implicit none real(${rk}$), intent(in) :: alphar,alphai,beta end function stdlib_selctg_${ri}$ pure logical(lk) function stdlib_select_${ri}$(alphar,alphai) import ${rk}$,lk implicit none real(${rk}$), intent(in) :: alphar,alphai end function stdlib_select_${ri}$ #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES pure logical(lk) function stdlib_selctg_${ci}$(alpha,beta) import ${ck}$,lk implicit none complex(${ck}$), intent(in) :: alpha,beta end function stdlib_selctg_${ci}$ pure logical(lk) function stdlib_select_${ci}$(alpha) import ${ck}$,lk implicit none complex(${ck}$), intent(in) :: alpha end function stdlib_select_${ci}$ #:endfor end interface contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure character function stdlib${ii}$_chla_transtype( trans ) !! This subroutine translates from a BLAST-specified integer constant to !! the character string specifying a transposition operation. !! CHLA_TRANSTYPE returns an CHARACTER*1. If CHLA_TRANSTYPE: is 'X', !! then input is not an integer indicating a transposition operator. !! Otherwise CHLA_TRANSTYPE returns the constant value corresponding to !! TRANS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: trans ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_no_trans = 111 integer(${ik}$), parameter :: blas_trans = 112 integer(${ik}$), parameter :: blas_conj_trans = 113 ! Executable Statements if( trans==blas_no_trans ) then stdlib${ii}$_chla_transtype = 'N' else if( trans==blas_trans ) then stdlib${ii}$_chla_transtype = 'T' else if( trans==blas_conj_trans ) then stdlib${ii}$_chla_transtype = 'C' else stdlib${ii}$_chla_transtype = 'X' end if return end function stdlib${ii}$_chla_transtype pure integer(${ik}$) function stdlib${ii}$_ieeeck( ispec, zero, one ) !! IEEECK is called from the ILAENV to verify that Infinity and !! possibly NaN arithmetic is safe (i.e. will not trap). ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: ispec real(sp), intent(in) :: one, zero ! ===================================================================== ! Executable Statements stdlib${ii}$_ieeeck = 1 ! Test support for infinity values if (.not.ieee_support_inf(one)) then stdlib${ii}$_ieeeck = 0 return end if ! return if we were only asked to check infinity arithmetic if (ispec == 0) return if (.not.ieee_support_nan(one)) then stdlib${ii}$_ieeeck = 0 return end if return end function stdlib${ii}$_ieeeck integer(${ik}$) function stdlib${ii}$_iladiag( diag ) !! This subroutine translated from a character string specifying if a !! matrix has unit diagonal or not to the relevant BLAST-specified !! integer constant. !! ILADIAG returns an INTEGER. If ILADIAG: < 0, then the input is not a !! character indicating a unit or non-unit diagonal. Otherwise ILADIAG !! returns the constant value corresponding to DIAG. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: diag ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_non_unit_diag = 131 integer(${ik}$), parameter :: blas_unit_diag = 132 ! Executable Statements if( stdlib_lsame( diag, 'N' ) ) then stdlib${ii}$_iladiag = blas_non_unit_diag else if( stdlib_lsame( diag, 'U' ) ) then stdlib${ii}$_iladiag = blas_unit_diag else stdlib${ii}$_iladiag = -1 end if return end function stdlib${ii}$_iladiag integer(${ik}$) function stdlib${ii}$_ilaprec( prec ) !! This subroutine translated from a character string specifying an !! intermediate precision to the relevant BLAST-specified integer !! constant. !! ILAPREC returns an INTEGER. If ILAPREC: < 0, then the input is not a !! character indicating a supported intermediate precision. Otherwise !! ILAPREC returns the constant value corresponding to PREC. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: prec ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_prec_single = 211 integer(${ik}$), parameter :: blas_prec_double = 212 integer(${ik}$), parameter :: blas_prec_indigenous = 213 integer(${ik}$), parameter :: blas_prec_extra = 214 ! Executable Statements if( stdlib_lsame( prec, 'S' ) ) then stdlib${ii}$_ilaprec = blas_prec_single else if( stdlib_lsame( prec, 'D' ) ) then stdlib${ii}$_ilaprec = blas_prec_double else if( stdlib_lsame( prec, 'I' ) ) then stdlib${ii}$_ilaprec = blas_prec_indigenous else if( stdlib_lsame( prec, 'X' ) .or. stdlib_lsame( prec, 'E' ) ) then stdlib${ii}$_ilaprec = blas_prec_extra else stdlib${ii}$_ilaprec = -1 end if return end function stdlib${ii}$_ilaprec integer(${ik}$) function stdlib${ii}$_ilatrans( trans ) !! This subroutine translates from a character string specifying a !! transposition operation to the relevant BLAST-specified integer !! constant. !! ILATRANS returns an INTEGER. If ILATRANS: < 0, then the input is not !! a character indicating a transposition operator. Otherwise ILATRANS !! returns the constant value corresponding to TRANS. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: trans ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_no_trans = 111 integer(${ik}$), parameter :: blas_trans = 112 integer(${ik}$), parameter :: blas_conj_trans = 113 ! Executable Statements if( stdlib_lsame( trans, 'N' ) ) then stdlib${ii}$_ilatrans = blas_no_trans else if( stdlib_lsame( trans, 'T' ) ) then stdlib${ii}$_ilatrans = blas_trans else if( stdlib_lsame( trans, 'C' ) ) then stdlib${ii}$_ilatrans = blas_conj_trans else stdlib${ii}$_ilatrans = -1 end if return end function stdlib${ii}$_ilatrans integer(${ik}$) function stdlib${ii}$_ilauplo( uplo ) !! This subroutine translated from a character string specifying a !! upper- or lower-triangular matrix to the relevant BLAST-specified !! integer constant. !! ILAUPLO returns an INTEGER. If ILAUPLO: < 0, then the input is not !! a character indicating an upper- or lower-triangular matrix. !! Otherwise ILAUPLO returns the constant value corresponding to UPLO. ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character :: uplo ! ===================================================================== ! Parameters integer(${ik}$), parameter :: blas_upper = 121 integer(${ik}$), parameter :: blas_lower = 122 ! Executable Statements if( stdlib_lsame( uplo, 'U' ) ) then stdlib${ii}$_ilauplo = blas_upper else if( stdlib_lsame( uplo, 'L' ) ) then stdlib${ii}$_ilauplo = blas_lower else stdlib${ii}$_ilauplo = -1 end if return end function stdlib${ii}$_ilauplo pure integer(${ik}$) function stdlib${ii}$_iparmq( ispec, name, opts, n, ilo, ihi, lwork ) !! This program sets problem and machine dependent parameters !! useful for xHSEQR and related subroutines for eigenvalue !! problems. It is called whenever !! IPARMQ is called with 12 <= ISPEC <= 16 ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: ihi, ilo, ispec, lwork, n character, intent(in) :: name*(*), opts*(*) ! ================================================================ ! Parameters integer(${ik}$), parameter :: inmin = 12 integer(${ik}$), parameter :: inwin = 13 integer(${ik}$), parameter :: inibl = 14 integer(${ik}$), parameter :: ishfts = 15 integer(${ik}$), parameter :: iacc22 = 16 integer(${ik}$), parameter :: icost = 17 integer(${ik}$), parameter :: nmin = 75 integer(${ik}$), parameter :: k22min = 14 integer(${ik}$), parameter :: kacmin = 14 integer(${ik}$), parameter :: nibble = 14 integer(${ik}$), parameter :: knwswp = 500 integer(${ik}$), parameter :: rcost = 10 real(sp), parameter :: two = 2.0 ! Local Scalars integer(${ik}$) :: nh, ns integer(${ik}$) :: i, ic, iz character :: subnam*6 ! Intrinsic Functions intrinsic :: log,max,mod,nint,real ! Executable Statements if( ( ispec==ishfts ) .or. ( ispec==inwin ) .or.( ispec==iacc22 ) ) then ! ==== set the number simultaneous shifts ==== nh = ihi - ilo + 1 ns = 2 if( nh>=30 )ns = 4 if( nh>=60 )ns = 10 if( nh>=150 )ns = max( 10, nh / nint( log( real( nh,KIND=dp) ) / log( two ),& KIND=ilp) ) if( nh>=590 )ns = 64 if( nh>=3000 )ns = 128 if( nh>=6000 )ns = 256 ns = max( 2, ns-mod( ns, 2 ) ) end if if( ispec==inmin ) then ! ===== matrices of order smaller than nmin get sent ! . to xlahqr, the classic double shift algorithm. ! . this must be at least 11. ==== stdlib${ii}$_iparmq = nmin else if( ispec==inibl ) then ! ==== inibl: skip a multi-shift qr iteration and ! . whenever aggressive early deflation finds ! . at least (nibble*(window size)/100) deflations. ==== stdlib${ii}$_iparmq = nibble else if( ispec==ishfts ) then ! ==== nshfts: the number of simultaneous shifts ===== stdlib${ii}$_iparmq = ns else if( ispec==inwin ) then ! ==== nw: deflation window size. ==== if( nh<=knwswp ) then stdlib${ii}$_iparmq = ns else stdlib${ii}$_iparmq = 3*ns / 2 end if else if( ispec==iacc22 ) then ! ==== iacc22: whether to accumulate reflections ! . before updating the far-from-diagonal elements ! . and whether to use 2-by-2 block structure while ! . doing it. a small amount of work could be saved ! . by making this choice dependent also upon the ! . nh=ihi-ilo+1. ! convert name to upper case if the first character is lower case. stdlib${ii}$_iparmq = 0 subnam = name ic = ichar( subnam( 1: 1 ) ) iz = ichar( 'Z' ) if( iz==90 .or. iz==122 ) then ! ascii character set if( ic>=97 .and. ic<=122 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=97 .and. ic<=122 )subnam( i: i ) = char( ic-32 ) end do end if else if( iz==233 .or. iz==169 ) then ! ebcdic character set if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 .and. & ic<=169 ) ) then subnam( 1: 1 ) = char( ic+64 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 & .and. ic<=169 ) )subnam( i:i ) = char( ic+64 ) end do end if else if( iz==218 .or. iz==250 ) then ! prime machines: ascii+128 if( ic>=225 .and. ic<=250 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=225 .and. ic<=250 )subnam( i: i ) = char( ic-32 ) end do end if end if if( subnam( 2:6 )=='GGHRD' .or.subnam( 2:6 )=='GGHD3' ) then stdlib${ii}$_iparmq = 1 if( nh>=k22min )stdlib${ii}$_iparmq = 2 else if ( subnam( 4:6 )=='EXC' ) then if( nh>=kacmin )stdlib${ii}$_iparmq = 1 if( nh>=k22min )stdlib${ii}$_iparmq = 2 else if ( subnam( 2:6 )=='HSEQR' .or.subnam( 2:5 )=='LAQR' ) then if( ns>=kacmin )stdlib${ii}$_iparmq = 1 if( ns>=k22min )stdlib${ii}$_iparmq = 2 end if else if( ispec==icost ) then ! === relative cost of near-the-diagonal chase vs ! blas updates === stdlib${ii}$_iparmq = rcost else ! ===== invalid value of ispec ===== stdlib${ii}$_iparmq = -1 end if end function stdlib${ii}$_iparmq pure logical(lk) function stdlib${ii}$_lsamen( n, ca, cb ) !! LSAMEN tests if the first N letters of CA are the same as the !! first N letters of CB, regardless of case. !! LSAMEN returns .TRUE. if CA and CB are equivalent except for case !! and .FALSE. otherwise. LSAMEN also returns .FALSE. if LEN( CA ) !! or LEN( CB ) is less than N. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character(len=*), intent(in) :: ca, cb integer(${ik}$), intent(in) :: n ! ===================================================================== ! Local Scalars integer(${ik}$) :: i ! Intrinsic Functions intrinsic :: len ! Executable Statements stdlib${ii}$_lsamen = .false. if( len( ca )<n .or. len( cb )<n )go to 20 ! do for each character in the two strings. do i = 1, n ! test if the characters are equal using stdlib${ii}$_lsame. if( .not.stdlib_lsame( ca( i: i ), cb( i: i ) ) )go to 20 end do stdlib${ii}$_lsamen = .true. 20 continue return end function stdlib${ii}$_lsamen #:for rk,rt,ri in REAL_KINDS_TYPES pure real(${rk}$) function stdlib${ii}$_${ri}$roundup_lwork( lwork ) !! ROUNDUP_LWORK >= LWORK. !! ROUNDUP_LWORK is guaranteed to have zero decimal part. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: lwork ! ===================================================================== ! Intrinsic Functions intrinsic :: epsilon,real,int ! Executable Statements stdlib${ii}$_${ri}$roundup_lwork = real(lwork,KIND=${rk}$) if (int( stdlib${ii}$_${ri}$roundup_lwork,KIND=ilp)<lwork) then ! force round up of lwork stdlib${ii}$_${ri}$roundup_lwork = stdlib${ii}$_${ri}$roundup_lwork * (1.0e+0_${rk}$ + epsilon(0.0e+0_${rk}$)) endif return end function stdlib${ii}$_${ri}$roundup_lwork #:endfor #:for rk,rt,ri in RC_KINDS_TYPES pure integer(${ik}$) function stdlib${ii}$_ila${ri}$lc( m, n, a, lda ) !! ILADLC: scans A for its last non-zero column. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: m, n, lda ! Array Arguments ${rt}$, intent(in) :: a(lda,*) ! ===================================================================== ! Parameters ${rt}$, parameter :: zero = 0.0_${rk}$ ! Local Scalars integer(${ik}$) :: i ! Executable Statements ! quick test for the common case where one corner is non-zero. if( n==0 ) then stdlib${ii}$_ila${ri}$lc = n else if (a(1, n)/=zero .or. a(m, n)/=zero) then stdlib${ii}$_ila${ri}$lc = n else ! now scan each column from the end, returning with the first non-zero. do stdlib${ii}$_ila${ri}$lc = n, 1, -1 do i = 1, m if (a(i, stdlib${ii}$_ila${ri}$lc)/=zero) return end do end do end if return end function stdlib${ii}$_ila${ri}$lc pure integer(${ik}$) function stdlib${ii}$_ila${ri}$lr( m, n, a, lda ) !! ILADLR: scans A for its last non-zero row. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: m, n, lda ! Array Arguments ${rt}$, intent(in) :: a(lda,*) ! ===================================================================== ! Parameters ${rt}$, parameter :: zero = 0.0_${rk}$ ! Local Scalars integer(${ik}$) :: i, j ! Executable Statements ! quick test for the common case where one corner is non-zero. if( m==0 ) then stdlib${ii}$_ila${ri}$lr = m else if( a(m, 1)/=zero .or. a(m, n)/=zero ) then stdlib${ii}$_ila${ri}$lr = m else ! scan up each column tracking the last zero row seen. stdlib${ii}$_ila${ri}$lr = 0 do j = 1, n i=m do while((a(max(i,1),j)==zero).and.(i>=1)) i=i-1 enddo stdlib${ii}$_ila${ri}$lr = max( stdlib${ii}$_ila${ri}$lr, i ) end do end if return end function stdlib${ii}$_ila${ri}$lr #:endfor #:for ck,ct,ci in CMPLX_KINDS_TYPES pure integer(${ik}$) function stdlib${ii}$_i${ci}$max1( n, zx, incx ) !! I*MAX1: finds the index of the first vector element of maximum absolute value. !! Based on I*AMAX from Level 1 BLAS. !! The change is to use the 'genuine' absolute value. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments integer(${ik}$), intent(in) :: incx, n ! Array Arguments complex(${ck}$), intent(in) :: zx(*) ! ===================================================================== ! Local Scalars real(${ck}$) :: dmax integer(${ik}$) :: i, ix ! Intrinsic Functions intrinsic :: abs ! Executable Statements stdlib${ii}$_i${ci}$max1 = 0 if (n<1 .or. incx<=0) return stdlib${ii}$_i${ci}$max1 = 1 if (n==1) return if (incx==1) then ! code for increment equal to 1 dmax = abs(zx(1)) do i = 2,n if (abs(zx(i))>dmax) then stdlib${ii}$_i${ci}$max1 = i dmax = abs(zx(i)) end if end do else ! code for increment not equal to 1 ix = 1 dmax = abs(zx(1)) ix = ix + incx do i = 2,n if (abs(zx(ix))>dmax) then stdlib${ii}$_i${ci}$max1 = i dmax = abs(zx(ix)) end if ix = ix + incx end do end if return end function stdlib${ii}$_i${ci}$max1 #:endfor pure integer(${ik}$) function stdlib${ii}$_ilaenv( ispec, name, opts, n1, n2, n3, n4 ) !! ILAENV is called from the LAPACK routines to choose problem-dependent !! parameters for the local environment. See ISPEC for a description of !! the parameters. !! ILAENV returns an INTEGER !! if ILAENV >= 0: ILAENV returns the value of the parameter specified by ISPEC !! if ILAENV < 0: if ILAENV = -k, the k-th argument had an illegal value. !! This version provides a set of parameters which should give good, !! but not optimal, performance on many of the currently available !! computers. Users are encouraged to modify this subroutine to set !! the tuning parameters for their particular machine using the option !! and problem size information in the arguments. !! This routine will not function correctly if it is converted to all !! lower case. Converting it to all upper case is allowed. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character(len=*), intent(in) :: name, opts integer(${ik}$), intent(in) :: ispec, n1, n2, n3, n4 ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, ic, iz, nb, nbmin, nx logical(lk) :: cname, sname, twostage character :: c1*1, c2*2, c4*2, c3*3, subnam*16 ! Intrinsic Functions intrinsic :: char,ichar,int,min,real ! Executable Statements go to ( 10, 10, 10, 80, 90, 100, 110, 120,130, 140, 150, 160, 160, 160, 160, 160, 160)& ispec ! invalid value for ispec stdlib${ii}$_ilaenv = -1 return 10 continue ! convert name to upper case if the first character is lower case. stdlib${ii}$_ilaenv = 1 subnam = name ic = ichar( subnam( 1: 1 ) ) iz = ichar( 'Z' ) if( iz==90 .or. iz==122 ) then ! ascii character set if( ic>=97 .and. ic<=122 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=97 .and. ic<=122 )subnam( i: i ) = char( ic-32 ) end do end if else if( iz==233 .or. iz==169 ) then ! ebcdic character set if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 .and. & ic<=169 ) ) then subnam( 1: 1 ) = char( ic+64 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 & .and. ic<=169 ) )subnam( i:i ) = char( ic+64 ) end do end if else if( iz==218 .or. iz==250 ) then ! prime machines: ascii+128 if( ic>=225 .and. ic<=250 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 6 ic = ichar( subnam( i: i ) ) if( ic>=225 .and. ic<=250 )subnam( i: i ) = char( ic-32 ) end do end if end if c1 = subnam( 1: 1 ) sname = c1=='S' .or. c1=='D' cname = c1=='C' .or. c1=='Z' if( .not.( cname .or. sname ) )return c2 = subnam( 2: 3 ) c3 = subnam( 4: 6 ) c4 = c3( 2: 3 ) twostage = len( subnam )>=11.and. subnam( 11: 11 )=='2' go to ( 50, 60, 70 )ispec 50 continue ! ispec = 1: block size ! in these examples, separate code is provided for setting nb for ! real and complex. we assume that nb will take the same value in ! single or double precision. nb = 1 if( subnam(2:6)=='LAORH' ) then ! this is for *laorhr_getrfnp routine if( sname ) then nb = 32 else nb = 32 end if else if( c2=='GE' ) then if( c3=='TRF' ) then if( sname ) then nb = 64 else nb = 64 end if else if( c3=='QRF' .or. c3=='RQF' .or. c3=='LQF' .or.c3=='QLF' ) then if( sname ) then nb = 32 else nb = 32 end if else if( c3=='QR ') then if( n3 == 1) then if( sname ) then ! m*n if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if else if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if end if else if( sname ) then nb = 1 else nb = 1 end if end if else if( c3=='LQ ') then if( n3 == 2) then if( sname ) then ! m*n if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if else if ((n1*n2<=131072).or.(n1<=8192)) then nb = n1 else nb = 32768/n2 end if end if else if( sname ) then nb = 1 else nb = 1 end if end if else if( c3=='HRD' ) then if( sname ) then nb = 32 else nb = 32 end if else if( c3=='BRD' ) then if( sname ) then nb = 32 else nb = 32 end if else if( c3=='TRI' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( c2=='PO' ) then if( c3=='TRF' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( c2=='SY' ) then if( c3=='TRF' ) then if( sname ) then if( twostage ) then nb = 192 else nb = 64 end if else if( twostage ) then nb = 192 else nb = 64 end if end if else if( sname .and. c3=='TRD' ) then nb = 32 else if( sname .and. c3=='GST' ) then nb = 64 end if else if( cname .and. c2=='HE' ) then if( c3=='TRF' ) then if( twostage ) then nb = 192 else nb = 64 end if else if( c3=='TRD' ) then nb = 32 else if( c3=='GST' ) then nb = 64 end if else if( sname .and. c2=='OR' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if end if else if( cname .and. c2=='UN' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nb = 32 end if end if else if( c2=='GB' ) then if( c3=='TRF' ) then if( sname ) then if( n4<=64 ) then nb = 1 else nb = 32 end if else if( n4<=64 ) then nb = 1 else nb = 32 end if end if end if else if( c2=='PB' ) then if( c3=='TRF' ) then if( sname ) then if( n2<=64 ) then nb = 1 else nb = 32 end if else if( n2<=64 ) then nb = 1 else nb = 32 end if end if end if else if( c2=='TR' ) then if( c3=='TRI' ) then if( sname ) then nb = 64 else nb = 64 end if else if ( c3=='EVC' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( c2=='LA' ) then if( c3=='UUM' ) then if( sname ) then nb = 64 else nb = 64 end if end if else if( sname .and. c2=='ST' ) then if( c3=='EBZ' ) then nb = 1 end if else if( c2=='GG' ) then nb = 32 if( c3=='HD3' ) then if( sname ) then nb = 32 else nb = 32 end if end if end if stdlib${ii}$_ilaenv = nb return 60 continue ! ispec = 2: minimum block size nbmin = 2 if( c2=='GE' ) then if( c3=='QRF' .or. c3=='RQF' .or. c3=='LQF' .or. c3=='QLF' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if else if( c3=='HRD' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if else if( c3=='BRD' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if else if( c3=='TRI' ) then if( sname ) then nbmin = 2 else nbmin = 2 end if end if else if( c2=='SY' ) then if( c3=='TRF' ) then if( sname ) then nbmin = 8 else nbmin = 8 end if else if( sname .and. c3=='TRD' ) then nbmin = 2 end if else if( cname .and. c2=='HE' ) then if( c3=='TRD' ) then nbmin = 2 end if else if( sname .and. c2=='OR' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if end if else if( cname .and. c2=='UN' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if else if( c3( 1: 1 )=='M' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nbmin = 2 end if end if else if( c2=='GG' ) then nbmin = 2 if( c3=='HD3' ) then nbmin = 2 end if end if stdlib${ii}$_ilaenv = nbmin return 70 continue ! ispec = 3: crossover point nx = 0 if( c2=='GE' ) then if( c3=='QRF' .or. c3=='RQF' .or. c3=='LQF' .or. c3=='QLF' ) then if( sname ) then nx = 128 else nx = 128 end if else if( c3=='HRD' ) then if( sname ) then nx = 128 else nx = 128 end if else if( c3=='BRD' ) then if( sname ) then nx = 128 else nx = 128 end if end if else if( c2=='SY' ) then if( sname .and. c3=='TRD' ) then nx = 32 end if else if( cname .and. c2=='HE' ) then if( c3=='TRD' ) then nx = 32 end if else if( sname .and. c2=='OR' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nx = 128 end if end if else if( cname .and. c2=='UN' ) then if( c3( 1: 1 )=='G' ) then if( c4=='QR' .or. c4=='RQ' .or. c4=='LQ' .or. c4=='QL' .or. c4=='HR' .or. & c4=='TR' .or. c4=='BR' )then nx = 128 end if end if else if( c2=='GG' ) then nx = 128 if( c3=='HD3' ) then nx = 128 end if end if stdlib${ii}$_ilaenv = nx return 80 continue ! ispec = 4: number of shifts (used by xhseqr) stdlib${ii}$_ilaenv = 6 return 90 continue ! ispec = 5: minimum column dimension (not used) stdlib${ii}$_ilaenv = 2 return 100 continue ! ispec = 6: crossover point for svd (used by xgelss and xgesvd) stdlib${ii}$_ilaenv = int( real( min( n1, n2 ),KIND=dp)*1.6e0,KIND=ilp) return 110 continue ! ispec = 7: number of processors (not used) stdlib${ii}$_ilaenv = 1 return 120 continue ! ispec = 8: crossover point for multishift (used by xhseqr) stdlib${ii}$_ilaenv = 50 return 130 continue ! ispec = 9: maximum size of the subproblems at the bottom of the ! computation tree in the divide-and-conquer algorithm ! (used by xgelsd and xgesdd) stdlib${ii}$_ilaenv = 25 return 140 continue ! ispec = 10: ieee and infinity nan arithmetic can be trusted not to trap ! stdlib${ii}$_ilaenv = 0 stdlib${ii}$_ilaenv = 1 if( stdlib${ii}$_ilaenv==1 ) then stdlib${ii}$_ilaenv = stdlib${ii}$_ieeeck( 1_${ik}$, 0.0, 1.0 ) end if return 150 continue ! ispec = 11: ieee infinity arithmetic can be trusted not to trap ! stdlib${ii}$_ilaenv = 0 stdlib${ii}$_ilaenv = 1 if( stdlib${ii}$_ilaenv==1 ) then stdlib${ii}$_ilaenv = stdlib${ii}$_ieeeck( 0_${ik}$, 0.0, 1.0 ) end if return 160 continue ! 12 <= ispec <= 17: xhseqr or related subroutines. stdlib${ii}$_ilaenv = stdlib${ii}$_iparmq( ispec, name, opts, n1, n2, n3, n4 ) return end function stdlib${ii}$_ilaenv integer(${ik}$) function stdlib${ii}$_iparam2stage( ispec, name, opts,ni, nbi, ibi, nxi ) !! This program sets problem and machine dependent parameters !! useful for xHETRD_2STAGE, xHETRD_HE2HB, xHETRD_HB2ST, !! xGEBRD_2STAGE, xGEBRD_GE2GB, xGEBRD_GB2BD !! and related subroutines for eigenvalue problems. !! It is called whenever ILAENV is called with 17 <= ISPEC <= 21. !! It is called whenever ILAENV2STAGE is called with 1 <= ISPEC <= 5 !! with a direct conversion ISPEC + 16. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! Scalar Arguments character(len=*), intent(in) :: name, opts integer(${ik}$), intent(in) :: ispec, ni, nbi, ibi, nxi ! ================================================================ ! Local Scalars integer(${ik}$) :: i, ic, iz, kd, ib, lhous, lwork, nthreads, factoptnb, qroptnb, & lqoptnb logical(lk) :: rprec, cprec character :: prec*1, algo*3, stag*5, subnam*12, vect*1 ! Intrinsic Functions intrinsic :: char,ichar,max ! Executable Statements ! invalid value for ispec if( (ispec<17).or.(ispec>21) ) then stdlib${ii}$_iparam2stage = -1 return endif ! get the number of threads nthreads = 1 !$ nthreads = omp_get_num_threads() ! write(*,*) 'iparam voici nthreads ispec ',nthreads, ispec if( ispec /= 19 ) then ! convert name to upper case if the first character is lower case. stdlib${ii}$_iparam2stage = -1 subnam = name ic = ichar( subnam( 1: 1 ) ) iz = ichar( 'Z' ) if( iz==90 .or. iz==122 ) then ! ascii character set if( ic>=97 .and. ic<=122 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 12 ic = ichar( subnam( i: i ) ) if( ic>=97 .and. ic<=122 )subnam( i: i ) = char( ic-32 ) end do end if else if( iz==233 .or. iz==169 ) then ! ebcdic character set if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 .and. & ic<=169 ) ) then subnam( 1: 1 ) = char( ic+64 ) do i = 2, 12 ic = ichar( subnam( i: i ) ) if( ( ic>=129 .and. ic<=137 ) .or.( ic>=145 .and. ic<=153 ) .or.( ic>=162 & .and. ic<=169 ) )subnam( i:i ) = char( ic+64 ) end do end if else if( iz==218 .or. iz==250 ) then ! prime machines: ascii+128 if( ic>=225 .and. ic<=250 ) then subnam( 1: 1 ) = char( ic-32 ) do i = 2, 12 ic = ichar( subnam( i: i ) ) if( ic>=225 .and. ic<=250 )subnam( i: i ) = char( ic-32 ) end do end if end if prec = subnam( 1: 1 ) algo = subnam( 4: 6 ) stag = subnam( 8:12 ) rprec = prec=='S' .or. prec=='D' cprec = prec=='C' .or. prec=='Z' ! invalid value for precision if( .not.( rprec .or. cprec ) ) then stdlib${ii}$_iparam2stage = -1 return endif endif ! write(*,*),'rprec,cprec ',rprec,cprec, ! $ ' algo ',algo,' stage ',stag if (( ispec == 17 ) .or. ( ispec == 18 )) then ! ispec = 17, 18: block size kd, ib ! could be also dependent from n but for now it ! depend only on sequential or parallel if( nthreads>4 ) then if( cprec ) then kd = 128 ib = 32 else kd = 160 ib = 40 endif else if( nthreads>1 ) then if( cprec ) then kd = 64 ib = 32 else kd = 64 ib = 32 endif else if( cprec ) then kd = 16 ib = 16 else kd = 32 ib = 16 endif endif if( ispec==17 ) stdlib${ii}$_iparam2stage = kd if( ispec==18 ) stdlib${ii}$_iparam2stage = ib else if ( ispec == 19 ) then ! ispec = 19: ! lhous length of the houselholder representation ! matrix (v,t) of the second stage. should be >= 1. ! will add the vect option here next release vect = opts(1:1) if( vect=='N' ) then lhous = max( 1, 4*ni ) else ! this is not correct, it need to call the algo and the stage2 lhous = max( 1, 4*ni ) + ibi endif if( lhous>=0 ) then stdlib${ii}$_iparam2stage = lhous else stdlib${ii}$_iparam2stage = -1 endif else if ( ispec == 20 ) then ! ispec = 20: (21 for future use) ! lwork length of the workspace for ! either or both stages for trd and brd. should be >= 1. ! trd: ! trd_stage 1: = lt + lw + ls1 + ls2 ! = ldt*kd + n*kd + n*max(kd,factoptnb) + lds2*kd ! where ldt=lds2=kd ! = n*kd + n*max(kd,factoptnb) + 2*kd*kd ! trd_stage 2: = (2nb+1)*n + kd*nthreads ! trd_both : = max(stage1,stage2) + ab ( ab=(kd+1)*n ) ! = n*kd + n*max(kd+1,factoptnb) ! + max(2*kd*kd, kd*nthreads) ! + (kd+1)*n lwork = -1 subnam(1:1) = prec subnam(2:6) = 'GEQRF' qroptnb = stdlib${ii}$_ilaenv( 1_${ik}$, subnam, ' ', ni, nbi, -1_${ik}$, -1_${ik}$ ) subnam(2:6) = 'GELQF' lqoptnb = stdlib${ii}$_ilaenv( 1_${ik}$, subnam, ' ', nbi, ni, -1_${ik}$, -1_${ik}$ ) ! could be qr or lq for trd and the max for brd factoptnb = max(qroptnb, lqoptnb) if( algo=='TRD' ) then if( stag=='2STAG' ) then lwork = ni*nbi + ni*max(nbi+1,factoptnb)+ max(2*nbi*nbi, nbi*nthreads)+ (nbi+& 1)*ni else if( (stag=='HE2HB').or.(stag=='SY2SB') ) then lwork = ni*nbi + ni*max(nbi,factoptnb) + 2*nbi*nbi else if( (stag=='HB2ST').or.(stag=='SB2ST') ) then lwork = (2*nbi+1)*ni + nbi*nthreads endif else if( algo=='BRD' ) then if( stag=='2STAG' ) then lwork = 2*ni*nbi + ni*max(nbi+1,factoptnb)+ max(2*nbi*nbi, nbi*nthreads)+ (& nbi+1)*ni else if( stag=='GE2GB' ) then lwork = ni*nbi + ni*max(nbi,factoptnb) + 2*nbi*nbi else if( stag=='GB2BD' ) then lwork = (3*nbi+1)*ni + nbi*nthreads endif endif lwork = max ( 1, lwork ) if( lwork>0 ) then stdlib${ii}$_iparam2stage = lwork else stdlib${ii}$_iparam2stage = -1 endif else if ( ispec == 21 ) then ! ispec = 21 for future use stdlib${ii}$_iparam2stage = nxi endif end function stdlib${ii}$_iparam2stage integer(${ik}$) function stdlib${ii}$_ilaenv2stage( ispec, name, opts, n1, n2, n3, n4 ) !! ILAENV2STAGE is called from the LAPACK routines to choose problem-dependent !! parameters for the local environment. See ISPEC for a description of !! the parameters. !! It sets problem and machine dependent parameters useful for *_2STAGE and !! related subroutines. !! ILAENV2STAGE returns an INTEGER !! if ILAENV2STAGE >= 0: ILAENV2STAGE returns the value of the parameter !! specified by ISPEC !! if ILAENV2STAGE < 0: if ILAENV2STAGE = -k, the k-th argument had an !! illegal value. !! This version provides a set of parameters which should give good, !! but not optimal, performance on many of the currently available !! computers for the 2-stage solvers. Users are encouraged to modify this !! subroutine to set the tuning parameters for their particular machine using !! the option and problem size information in the arguments. !! This routine will not function correctly if it is converted to all !! lower case. Converting it to all upper case is allowed. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- ! july 2017 ! Scalar Arguments character(len=*), intent(in) :: name, opts integer(${ik}$), intent(in) :: ispec, n1, n2, n3, n4 ! ===================================================================== ! Local Scalars integer(${ik}$) :: iispec ! Executable Statements go to ( 10, 10, 10, 10, 10 )ispec ! invalid value for ispec stdlib${ii}$_ilaenv2stage = -1 return 10 continue ! 2stage eigenvalues and svd or related subroutines. iispec = 16 + ispec stdlib${ii}$_ilaenv2stage = stdlib${ii}$_iparam2stage( iispec, name, opts,n1, n2, n3, n4 ) return end function stdlib${ii}$_ilaenv2stage #:endfor end module stdlib_linalg_lapack_aux