! -*- f90 -*-
!
! Contains wrappers for the following LAPACK routines:
!
!  Driver routines for generalized eigenvalue and singular value problems:
!  
!   sygv,hegv (GSEP, symmetric-definite eigenvalues/vectors)
!   sygvd,hegvd (GSEP, symmetric-definite eigenvalues/vectors, D&C)
!   sygvx,hegvx (GSEP, symmetric-definite eigenvalues/vectors, expert) - Not Implemented
!   spgv, hpgv, spgvd, hpgvd, spgvx, hpgvx (..., packed storage) - Not Implemented
!   sbgv, hbgv, sbgvd, hbgvd, sbgvx, hbgvx (..., band) - Not Implemented
!   gges,ggesx (GNEP, general, Schur Factorization) - Not Implemented
!   ggev,ggevx (GNEP, general, eigenvalues/vectors)
!   ggsvd (GSVD, general, singular values/vectors) - Not Implemented
!   gegv (general, eigenvalues/vectors, deprecated, use ggev instead) - Removed
!

! <sym=sy,sy,he,he>
! <rwork=,,rwork\,,\2>
! <rworkptr=,,float*\,,double*\,>
! <rworkl=,,rwork\,lrwork\,,\2>
! <rworklc=,,rwork\,&lrwork\,,\2>
! <rworklptr=,,float*\,int*\,,double*\,int*\,>

subroutine <prefix><sym>gv(itype,compute_v,lower,n,w,a,b,work,lwork,<rwork>info)
  !
  ! w,v,info = sygv|hegv(a,b,itype=1,compute_v=1,lower=0,lwork=min_lwork,overwrite_a=0,overwrite_b=0)
  !
  integer check(1<=itype && itype<=3):: itype = 1
  integer :: compute_v=1
  integer :: lower=0
  integer intent(hide),depend(a) :: n = shape(a,0)
  <ftype> dimension(n,n),intent(in,out,copy,out=v) :: a
  <ftype> dimension(n,n),intent(in,copy) :: b
  <ftypereal> dimension(n),intent(out) :: w
  <_lwork=3*n-1,\0,2*n-1,\2>
  integer optional,intent(in),depend(n) :: lwork=<_lwork>
  check(<_lwork>\<=lwork) lwork
  <ftype> dimension(lwork),intent(hide,cache),depend(lwork) :: work
  <ftypereal> dimension(3*n-2),intent(hide,cache),depend(n) :: rwork
  integer intent(out) :: info
  callstatement (*f2py_func)(&itype,(compute_v?"V":"N"),(lower?"L":"U"),&n,a,&n,b,&n,w,work,&lwork,<rwork>&info)
  callprotoargument int*,char*,char*,int*,<ctype>*,int*,<ctype>*,int*,<ctypereal>*,<ctype>*,int*,<rworkptr>int*
end subroutine <prefix><sym>gv

subroutine <prefix><sym>gvd(itype,compute_v,lower,n,w,a,b,work,lwork,<rworkl>iwork,liwork,info)
  !
  ! w,v,info = sygvd|hegvd(a,b,itype=1,compute_v=1,lower=0,lwork=min_lwork,overwrite_a=0,overwrite_b=0)
  !
  integer check(1<=itype && itype<=3):: itype = 1
  integer :: compute_v=1
  integer :: lower=0
  integer intent(hide),depend(a) :: n = shape(a,0)
  <ftype> dimension(n,n),intent(in,out,copy,out=v) :: a
  <ftype> dimension(n,n),intent(in,copy) :: b
  <ftypereal> dimension(n),intent(out) :: w
  <_lwork=(compute_v?1+6*n+2*n*n:2*n+1),\0,(compute_v?2*n+n*n:n+1),\2>
  integer optional,intent(in),depend(n,compute_v) :: lwork=<_lwork>
  check(<_lwork>\<=lwork) lwork
  <ftype> dimension(lwork),intent(hide,cache),depend(lwork) :: work
  integer intent(hide),depend(n,compute_v) :: lrwork = (compute_v?1+5*n+2*n*n:n)
  <ftypereal> dimension(lrwork),intent(hide,cache),depend(lrwork) :: rwork
  integer intent(hide),depend(compute_v,n) :: liwork = (compute_v?3+5*n:1)
  integer intent(hide,cache),dimension(liwork),depend(liwork) :: iwork
  integer intent(out) :: info
  callstatement (*f2py_func)(&itype,(compute_v?"V":"N"),(lower?"L":"U"),&n,a,&n,b,&n,w,work,&lwork,<rworklc>iwork,&liwork,&info)
  callprotoargument int*,char*,char*,int*,<ctype>*,int*,<ctype>*,int*,<ctypereal>*,<ctype>*,int*,<rworklptr>int*,int*,int*
end subroutine <prefix><sym>gvd

! <alpha=alphar\,alphai,\0,alpha,\2>
! <alphaptr=float*\,float*,double*\,double*,complex_float*,complex_double*>

subroutine <prefix>ggev(compute_vl,compute_vr,n,a,b,<alpha>,beta,vl,ldvl,vr,ldvr,work,lwork,<rwork>info)

     callstatement {(*f2py_func)((compute_vl?"V":"N"),(compute_vr?"V":"N"),&n,a,&n,b,&n,<alpha>,beta,vl,&ldvl,vr,&ldvr,work,&lwork,<rwork>&info);}
     callprotoargument char*,char*,int*,<ctype>*,int*,<ctype>*,int*,<alphaptr>,<ctype>*,<ctype>*,int*,<ctype>*,int*,<ctype>*,int*,<rworkptr>int*

    integer optional,intent(in):: compute_vl = 1
    check(compute_vl==1||compute_vl==0) compute_vl
    integer optional,intent(in):: compute_vr = 1
    check(compute_vr==1||compute_vr==0) compute_vr

    integer intent(hide),depend(a) :: n = shape(a,0)
    <ftype>  dimension(n,n),intent(in,copy) :: a
    check(shape(a,0)==shape(a,1)) :: a

    <ftype> intent(in,copy), dimension(n,n) :: b
    check(shape(b,0)==shape(b,1)) :: b

    <ftype> intent(out), dimension(n), depend(n) :: <alpha>
    <ftype> intent(out), dimension(n), depend(n) :: beta

    <ftype>  depend(ldvl,n), dimension(ldvl,n),intent(out) :: vl
    integer intent(hide),depend(n,compute_vl) :: ldvl=(compute_vl?n:1)
    
    <ftype>  depend(ldvr,n), dimension(ldvr,n),intent(out) :: vr
    integer intent(hide),depend(n,compute_vr) :: ldvr=(compute_vr?n:1)

    ! <_lwork=8*n,\0,2*n,\2>
    integer optional,intent(in),depend(n,compute_vl,compute_vr) :: lwork=<_lwork>
    check(lwork>=<_lwork>) :: lwork
    <ftype> intent(hide,cache), dimension(lwork), depend(lwork) :: work
    <ftypereal> intent(hide), dimension(8*n), depend(n) :: rwork

    integer intent(out):: info

end subroutine <prefix>ggev

